diff --git a/build.gradle b/build.gradle index dc4d822df..2b8fb1ad7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,16 @@ import org.gradle.plugins.signing.Sign +buildscript { + repositories { + jcenter() + maven { url 'http://dl.bintray.com/content/aalmiray/kordamp' } + } + dependencies { + classpath 'org.kordamp:markdown-gradle-plugin:0.1.1' + } +} +apply plugin: 'org.kordamp.gradle.markdown' + allprojects { apply plugin: 'java' apply plugin: 'eclipse' @@ -9,7 +20,7 @@ allprojects { isSnapshot = true gitCommit = getGitCommit() javadocAllDir = new File(buildDir, 'javadoc') - documentationDir = new File(projectDir, 'documentation') + documentationDir = new File(buildDir, 'documentation') releasedocsDir = new File(buildDir, 'releasedocs') rootConfigDir = new File(rootDir, 'config') sonatypeCredentialsAvailable = project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword') @@ -101,7 +112,13 @@ task prepareReleasedocs(type: Copy) { filter(ReplaceTokens, tokens: [version: version, releasedate: builtDate, targetCompatibility: targetCompatibility.toString()]) } -task distributionZip(type: Zip, dependsOn: [javadocAll, prepareReleasedocs]) { +markdownToHtml { + sourceDir = new File(projectDir, "/documentation") + outputDir documentationDir + configuration = [tables: true, fencedCodeBlocks: true] +} + +task distributionZip(type: Zip, dependsOn: [javadocAll, prepareReleasedocs, markdownToHtml]) { classifier builtDate into ('javadoc') { from(javadocAllDir) diff --git a/documentation/connections.html b/documentation/connections.html deleted file mode 100644 index a5f694c4f..000000000 --- a/documentation/connections.html +++ /dev/null @@ -1,94 +0,0 @@ - -
-- Creating a Connection -
- -- The org.jivesoftware.smack.XMPPConnection class manages your connection to an XMPP - server. A default implementation is the org.jivesoftware.smack.XMPPTCPConnection - class. Two constructors are mainly used. The first, XMPPTCPConnection(String) takes - the server name you'd like to connect to as an argument. All default connection settings will - be used: -
- Connect and Disconnect -
- --// Create the configuration for this new connection -ConnectionConfiguration config = new ConnectionConfiguration("jabber.org", 5222); -config.setCompressionEnabled(true); - -AbstractXMPPConnection connection = new XMPPTCPConnection(config); -// Connect to the server -connection.connect(); -// Log into the server -connection.login("username", "password", "SomeResource"); -.... -// Disconnect from the server -connection.disconnect(); -
-By default Smack will try to reconnect the connection in case it was abruptly disconnected. Use
-ConnectionConfiguration#setReconnectionAllowed(boolean) to turn on/off this feature. The reconnection
-manager will try to immediately reconnect to the server and increase the delay between attempts as
-successive reconnections keep failing.
-
-In case you want to force a reconnection while the reconnetion manager is waiting for the next
-reconnection, you can just use AbstractXMPPConnection#connect() and a new attempt will be made.
-If the manual attempt also failed then the reconnection manager will still continue the
-reconnection job.
-
-Smack includes two built-in debugging consoles that will let you track all XML traffic between -the client and server. A lite debugger which is part of the smack-core.jar -and an enhanced debugger contained in smack-debug.jar. -
- --Debugging mode can be enabled in two different ways: -
- -- SmackConfiguration.DEBUG_ENABLED = true;
- -
- java -Dsmack.debugEnabled=true SomeApp -
-If you wish to explicitly disable debug mode in your application, including using the command-line parameter, -add the following line to your application before opening new connections: -
- --SmackConfiguration.DEBUG_ENABLED = false; -
- --Smack uses the following logic to decide the debugger console to use: -
- -- java -Dsmack.debuggerClass=my.company.com.MyDebugger SomeApp
- -
- -
-This section details the usage of Smacks implementation of Entity Capabilities. -
-XEP related: XEP-0115: Entity Capabilities - -- -Entity Capabilities is a XMPP Protocol extension, which, in order to minimize network impact, caches the capabilities of XMPP entities. Those capabilities are determined with the help of the Service Discovery Protocol (XEP-0030). - -
- -Usage
-
-Entity Capabilities work silenty in background when enabled. If the remote XMPP entity does not support XEP-0115 but XEP-0030 then XEP-0030 mechanisms are transparently used. You can enable or disable Entity Capabilities by using EntityCapsManager.
-
-The cache used by Smack for Entity Capabilities is non-persistent as default. That is, the cache only uses memory. But it is also possible to set a persistent Entity Capabilities cache, which is recommended.
-
-
-Enable Entity Capabilities
-
-
-- -Configure a persistent cache for Entity Capabilities -- // Get an instance of entity caps manager for the specified connection - EntityCapsManager mgr = EntityCapsManager.getInstanceFor(connection); - - // Enable entity capabilities - mgr.enableEntityCaps(); --
-- - -- // Get an instance of entity caps manager for the specified connection - EntityCapsManager mgr = EntityCapsManager.getInstanceFor(connection); - - // Create an cache, see smackx.entitycaps.cache for pre-defined cache implementations - EntityCapsPersistentCache cache = new SimpleDirectoryPersistentCache(new File("/foo/cachedir")); - - // Set the cache - mgr.setPersistentCache(cache); --
- -Allows to exchange structured data between users and applications for common -tasks such as registration and searching using Forms. - -
-XEP related: XEP-4 - -- -Description
- -An XMPP entity may need to gather data from another XMPP entity. Therefore, the data-gathering -entity will need to create a new Form, specify the fields that will conform the Form and finally -send the Form to the data-providing entity.
- -Usage- -In order to create a Form to fill out use the Form's constructor passing the constant -Form.TYPE_FORM as the parameter. The next step is to create the form fields and add them to -the form. In order to create and customize a FormField use the FormField's -constructor specifying the variable name of the field as the parameter. Then use setType(String type) -to set the field's type (e.g. FormField.TYPE_HIDDEN, FormField.TYPE_TEXT_SINGLE). Once we have the -Form instance and the FormFields the last step is to send addField(FormField field) -for each field that we want to add to the form.
- -Once the form to fill out is finished we will want to send it in a message. Send getDataFormToSend() to -the form and add the answer as an extension to the message to send.
- -Examples
-
-In this example we can see how to create and send a form to fill out:
-
-- -// Create a new form to gather data - Form formToSend = new Form(Form.TYPE_FORM); - formToSend.setInstructions( - "Fill out this form to report your case.\nThe case will be created automatically."); - formToSend.setTitle("Case configurations"); - // Add a hidden variable to the form - FormField field = new FormField("hidden_var"); - field.setType(FormField.TYPE_HIDDEN); - field.addValue("Some value for the hidden variable"); - formToSend.addField(field); - // Add a fixed variable to the form - field = new FormField(); - field.addValue("Section 1: Case description"); - formToSend.addField(field); - // Add a text-single variable to the form - field = new FormField("name"); - field.setLabel("Enter a name for the case"); - field.setType(FormField.TYPE_TEXT_SINGLE); - formToSend.addField(field); - // Add a text-multi variable to the form - field = new FormField("description"); - field.setLabel("Enter a description"); - field.setType(FormField.TYPE_TEXT_MULTI); - formToSend.addField(field); - - // Create a chat with "user2@host.com" - Chat chat = conn1.createChat("user2@host.com" ); - - Message msg = chat.createMessage(); - msg.setBody("To enter a case please fill out this form and send it back to me"); - // Add the form to fill out to the message to send - msg.addExtension(formToSend.getDataFormToSend()); - - // Send the message with the form to fill out - chat.sendMessage(msg); --
- -Description
- -Under many situations an XMPP entity could receive a form to fill out. For example, some hosts -may require to fill out a form in order to register new users. Smack lets the data-providing entity -to complete the form in an easy way and send it back to the data-gathering entity.
- -Usage- -The form to fill out contains useful information that could be used for rendering the form. But it -cannot be used to actually complete it. Instead it's necessary to create a new form based on the original -form whose purpose is to hold all the answers.
- -In order to create a new Form to complete based on the original Form just send -createAnswerForm() to the original Form. Once you have a valid form that could be actually -completed all you have to do is send setAnswer(String variable, String value) to the form where variable -is the variable of the FormField that you want to answer and value is the String representation -of the answer. If the answer consist of several values you could then use setAnswer(String variable, List values) -where values is a List of Strings.
- -Once the form has been completed we will want to send it back in a message. Send getDataFormToSend() to -the form and add the answer as an extension to the message to send back.
- -Examples
-
-In this example we can see how to retrieve a form to fill out, complete the form and send it back:
-
-- - - \ No newline at end of file diff --git a/documentation/extensions/dataforms.md b/documentation/extensions/dataforms.md new file mode 100644 index 000000000..2c9af700e --- /dev/null +++ b/documentation/extensions/dataforms.md @@ -0,0 +1,127 @@ +Data Forms +========== + +Allows to exchange structured data between users and applications for common +tasks such as registration and searching using Forms. + + * Create a Form to fill out + * Answer a Form + +**XEP related:** [XEP-4](http://www.xmpp.org/extensions/xep-0004.html) + +Create a Form to fill out +------------------------- + +**Description** + +An XMPP entity may need to gather data from another XMPP entity. Therefore, +the data-gathering entity will need to create a new Form, specify the fields +that will conform the Form and finally send the Form to the data-providing +entity. + +**Usage** + +In order to create a Form to fill out use the _**Form**_'s constructor passing +the constant **Form.TYPE_FORM** as the parameter. The next step is to create +the form fields and add them to the form. In order to create and customize a +_**FormField**_ use the _**FormField**_'s constructor specifying the variable +name of the field as the parameter. Then use **setType(String type)** to set +the field's type (e.g. FormField.TYPE_HIDDEN, FormField.TYPE_TEXT_SINGLE). +Once we have the _**Form**_ instance and the _**FormFields**_ the last step is +to send **addField(FormField field)** for each field that we want to add to +the form. + +Once the form to fill out is finished we will want to send it in a message. +Send **getDataFormToSend()** to the form and add the answer as an extension to +the message to send. + +**Examples** + +In this example we can see how to create and send a form to fill out: + +``` +// Create a new form to gather data +Form formToSend = new Form(Form.TYPE_FORM); +formToSend.setInstructions(Fill out this form to report your case.\nThe case will be created automatically."); +formToSend.setTitle("Case configurations"); +// Add a hidden variable to the form +FormField field = new FormField("hidden_var"); +field.setType(FormField.TYPE_HIDDEN); +field.addValue("Some value for the hidden variable"); +formToSend.addField(field); +// Add a fixed variable to the form +field = new FormField(); +field.addValue("Section 1: Case description"); +formToSend.addField(field); +// Add a text-single variable to the form +field = new FormField("name"); +field.setLabel("Enter a name for the case"); +field.setType(FormField.TYPE_TEXT_SINGLE); +formToSend.addField(field); +// Add a text-multi variable to the form +field = new FormField("description"); +field.setLabel("Enter a description"); +field.setType(FormField.TYPE_TEXT_MULTI); +formToSend.addField(field); +// Create a chat with "user2@host.com" +Chat chat = conn1.createChat("user2@host.com" ); +Message msg = chat.createMessage(); +msg.setBody("To enter a case please fill out this form and send it back"); +// Add the form to fill out to the message to send +msg.addExtension(formToSend.getDataFormToSend()); +// Send the message with the form to fill out +chat.sendMessage(msg); +``` + +Answer a Form +------------- + +**Description** + +Under many situations an XMPP entity could receive a form to fill out. For +example, some hosts may require to fill out a form in order to register new +users. Smack lets the data-providing entity to complete the form in an easy +way and send it back to the data-gathering entity. + +**Usage** + +The form to fill out contains useful information that could be used for +rendering the form. But it cannot be used to actually complete it. Instead +it's necessary to create a new form based on the original form whose purpose +is to hold all the answers. + +In order to create a new _**Form**_ to complete based on the original +_**Form**_ just send **createAnswerForm()** to the original _**Form**_. Once +you have a valid form that could be actually completed all you have to do is +send **setAnswer(String variable, String value)** to the form where variable +is the variable of the _**FormField**_ that you want to answer and value is +the String representation of the answer. If the answer consist of several +values you could then use **setAnswer(String variable, List values)** where +values is a List of Strings. + +Once the form has been completed we will want to send it back in a message. +Send **getDataFormToSend()** to the form and add the answer as an extension to +the message to send back. + +**Examples** + +In this example we can see how to retrieve a form to fill out, complete the +form and send it back: + +``` +// Get the message with the form to fill out +Message msg2 = chat2.nextMessage(); +// Retrieve the form to fill out from the message +Form formToRespond = Form.getFormFrom(msg2); +// Obtain the form to send with the replies +Form completedForm = formToRespond.createAnswerForm(); +// Add the answers to the form +completedForm.setAnswer("name", "Credit card number invalid"); +completedForm.setAnswer("description", "The ATM says that my credit card number is invalid"); +msg2 = chat2.createMessage(); +msg2.setBody("To enter a case please fill out this form and send it back"): +// Add the completed form to the message to send back +msg2.addExtension(completedForm.getDataFormToSend()); +// Send the message with the completed form +chat2.sendMessage(msg2); +``` diff --git a/documentation/extensions/disco.html b/documentation/extensions/disco.html deleted file mode 100644 index 1af4a5298..000000000 --- a/documentation/extensions/disco.html +++ /dev/null @@ -1,236 +0,0 @@ - - -// Get the message with the form to fill out - Message msg2 = chat2.nextMessage(); - // Retrieve the form to fill out from the message - Form formToRespond = Form.getFormFrom(msg2); - // Obtain the form to send with the replies - Form completedForm = formToRespond.createAnswerForm(); - // Add the answers to the form - completedForm.setAnswer("name", "Credit card number invalid"); - completedForm.setAnswer( - "description", - "The ATM says that my credit card number is invalid. What's going on?"); - - msg2 = chat2.createMessage(); - msg2.setBody("To enter a case please fill out this form and send it back to me"); - // Add the completed form to the message to send back - msg2.addExtension(completedForm.getDataFormToSend()); - // Send the message with the completed form - chat2.sendMessage(msg2); --
- -The service discovery extension allows to discover items and information about XMPP -entities. Follow these links to learn how to use this extension. - -
- -Description
- -Any XMPP entity may receive a discovery request and must answer with its associated items or -information. Therefore, your Smack client may receive a discovery request that must respond -to (i.e., if your client supports XHTML-IM). This extension automatically responds to a -discovery request with the information that you previously configured.
- -Usage
-
-In order to configure the supported features by your client you should first obtain the
-ServiceDiscoveryManager associated with your XMPPConnection. To get your ServiceDiscoveryManager
-send getInstanceFor(connection) to the class ServiceDiscoveryManager where
-connection is your XMPPConnection.
Once you have your ServiceDiscoveryManager you will be able to manage the supported features. To -register a new feature send addFeature(feature) to your ServiceDiscoveryManager -where feature is a String that represents the supported feature. To remove a supported feature send -removeFeature(feature) to your ServiceDiscoveryManager where feature is a -String that represents the feature to remove.
- -Examples
-
-In this example we can see how to add and remove supported features:
-
-- -// Obtain the ServiceDiscoveryManager associated with my XMPPConnection - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); - - // Register that a new feature is supported by this XMPP entity - discoManager.addFeature(namespace1); - - // Remove the specified feature from the supported features by this XMPP entity - discoManager.removeFeature(namespace2); --
- -Description
- -Your XMPP entity may receive a discovery request for items non-addressable as a JID such as -the MUC rooms where you are joined. In order to answer the correct information it is necessary -to configure the information providers associated to the items/nodes within the Smack client.
- -Usage
-
-In order to configure the associated nodes within the Smack client you will need to create a
-NodeInformationProvider and register it with the ServiceDiscoveryManager. To get
-your ServiceDiscoveryManager send getInstanceFor(connection) to the class ServiceDiscoveryManager
-where connection is your XMPPConnection.
Once you have your ServiceDiscoveryManager you will be able to register information providers -for the XMPP entity's nodes. To register a new node information provider send setNodeInformationProvider(String node, NodeInformationProvider listener) -to your ServiceDiscoveryManager where node is the item non-addressable as a JID and -listener is the NodeInformationProvider to register. To unregister a NodeInformationProvider -send removeNodeInformationProvider(String node) to your ServiceDiscoveryManager where -node is the item non-addressable as a JID whose information provider we want to unregister.
- -Examples
-
-In this example we can see how to register a NodeInformationProvider with a ServiceDiscoveryManager that will provide
-information concerning a node named "http://jabber.org/protocol/muc#rooms":
-
-- -// Set the NodeInformationProvider that will provide information about the - // joined rooms whenever a disco request is received - ServiceDiscoveryManager.getInstanceFor(connection).setNodeInformationProvider( - "http://jabber.org/protocol/muc#rooms", - new NodeInformationProvider() { - public List getNodeItems() { - ArrayList answer = new ArrayList(); - Iterator rooms = MultiUserChat.getJoinedRooms(connection); - while (rooms.hasNext()) { - answer.add(new DiscoverItems.Item((String)rooms.next())); - } - return answer; - } - }); --
- -Description
- -In order to obtain information about a specific item you have to first discover the items available -in an XMPP entity.
- -Usage- -
Once you have your ServiceDiscoveryManager you will be able to discover items associated with -an XMPP entity. To discover the items of a given XMPP entity send discoverItems(entityID) -to your ServiceDiscoveryManager where entityID is the ID of the entity. The message -discoverItems(entityID) will answer an instance of DiscoverItems that contains -the discovered items.
- -Examples
-
-In this example we can see how to discover the items associated with an online catalog service:
-
-- -// Obtain the ServiceDiscoveryManager associated with my XMPPConnection - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); - - // Get the items of a given XMPP entity - // This example gets the items associated with online catalog service - DiscoverItems discoItems = discoManager.discoverItems("plays.shakespeare.lit"); - - // Get the discovered items of the queried XMPP entity - Iterator it = discoItems.getItems(); - // Display the items of the remote XMPP entity - while (it.hasNext()) { - DiscoverItems.Item item = (DiscoverItems.Item) it.next(); - System.out.println(item.getEntityID()); - System.out.println(item.getNode()); - System.out.println(item.getName()); - } --
- -Description
- -Once you have discovered the entity ID and name of an item, you may want to find out more -about the item. The information desired generally is of two kinds: 1) The item's identity -and 2) The features offered by the item.
- -This information helps you determine what actions are possible with regard to this -item (registration, search, join, etc.) as well as specific feature types of interest, if -any (e.g., for the purpose of feature negotiation).
- -Usage- -
Once you have your ServiceDiscoveryManager you will be able to discover information associated with -an XMPP entity. To discover the information of a given XMPP entity send discoverInfo(entityID) -to your ServiceDiscoveryManager where entityID is the ID of the entity. The message -discoverInfo(entityID) will answer an instance of DiscoverInfo that contains -the discovered information.
- -Examples
-
-In this example we can see how to discover the information of a conference room:
-
-- -// Obtain the ServiceDiscoveryManager associated with my XMPPConnection - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); - - // Get the information of a given XMPP entity - // This example gets the information of a conference room - DiscoverInfo discoInfo = discoManager.discoverInfo("balconyscene@plays.shakespeare.lit"); - - // Get the discovered identities of the remote XMPP entity - Iterator it = discoInfo.getIdentities(); - // Display the identities of the remote XMPP entity - while (it.hasNext()) { - DiscoverInfo.Identity identity = (DiscoverInfo.Identity) it.next(); - System.out.println(identity.getName()); - System.out.println(identity.getType()); - System.out.println(identity.getCategory()); - } - - // Check if room is password protected - discoInfo.containsFeature("muc_passwordprotected"); --
- -Description
- -Publish your entity items to some kind of persistent storage. This enables other entities to query -that entity using the disco#items namespace and receive a result even when the entity being queried -is not online (or available).
- -Usage- -
Once you have your ServiceDiscoveryManager you will be able to publish items to some kind of -persistent storage. To publish the items of a given XMPP entity you have to first create an instance -of DiscoverItems and configure it with the items to publish. Then you will have to -send publishItems(String entityID, DiscoverItems discoverItems) to your ServiceDiscoveryManager -where entityID is the address of the XMPP entity that will persist the items and discoverItems contains the items -to publish.
- -Examples
-
-In this example we can see how to publish new items:
-
-- - - diff --git a/documentation/extensions/disco.md b/documentation/extensions/disco.md new file mode 100644 index 000000000..7a3c40a66 --- /dev/null +++ b/documentation/extensions/disco.md @@ -0,0 +1,224 @@ +Service Discovery +================= + +The service discovery extension allows to discover items and information about +XMPP entities. Follow these links to learn how to use this extension. + + * Manage XMPP entity features + * Provide node information + * Discover items associated with an XMPP entity + * Discover information about an XMPP entity + * Publish publicly available items + +**XEP related:** [XEP-30](http://www.xmpp.org/extensions/xep-0030.html) + +Manage XMPP entity features +--------------------------- + +**Description** + +Any XMPP entity may receive a discovery request and must answer with its +associated items or information. Therefore, your Smack client may receive a +discovery request that must respond to (i.e., if your client supports XHTML- +IM). This extension automatically responds to a discovery request with the +information that you previously configured. + +**Usage** + +In order to configure the supported features by your client you should first +obtain the ServiceDiscoveryManager associated with your XMPPConnection. To get +your ServiceDiscoveryManager send **getInstanceFor(connection)** to the class +_**ServiceDiscoveryManager**_ where connection is your XMPPConnection. + +Once you have your ServiceDiscoveryManager you will be able to manage the +supported features. To register a new feature send **addFeature(feature)** to +your _**ServiceDiscoveryManager**_ where feature is a String that represents +the supported feature. To remove a supported feature send +**removeFeature(feature)** to your _**ServiceDiscoveryManager**_ where feature +is a String that represents the feature to remove. + +**Examples** + +In this example we can see how to add and remove supported features: + +``` +// Obtain the ServiceDiscoveryManager associated with my XMPP connection +ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); +// Register that a new feature is supported by this XMPP entity +discoManager.addFeature(namespace1); +// Remove the specified feature from the supported features +discoManager.removeFeature(namespace2); +``` + +Provide node information +------------------------ + +**Description** + +Your XMPP entity may receive a discovery request for items non-addressable as +a JID such as the MUC rooms where you are joined. In order to answer the +correct information it is necessary to configure the information providers +associated to the items/nodes within the Smack client. + +**Usage** + +In order to configure the associated nodes within the Smack client you will +need to create a NodeInformationProvider and register it with the +_**ServiceDiscoveryManager**_. To get your ServiceDiscoveryManager send +**getInstanceFor(connection)** to the class _**ServiceDiscoveryManager**_ +where connection is your XMPPConnection. + +Once you have your ServiceDiscoveryManager you will be able to register +information providers for the XMPP entity's nodes. To register a new node +information provider send **setNodeInformationProvider(String node, +NodeInformationProvider listener)** to your _**ServiceDiscoveryManager**_ +where node is the item non-addressable as a JID and listener is the +_**NodeInformationProvider**_ to register. To unregister a +_**NodeInformationProvider**_ send **removeNodeInformationProvider(String +node)** to your _**ServiceDiscoveryManager**_ where node is the item non- +addressable as a JID whose information provider we want to unregister. + +**Examples** + +In this example we can see how to register a NodeInformationProvider with a +ServiceDiscoveryManager that will provide information concerning a node named +"http://jabber.org/protocol/muc#rooms": + +``` +// Set the NodeInformationProvider that will provide information about the +// joined rooms whenever a disco request is received +ServiceDiscoveryManager.getInstanceFor(connection).setNodeInformationProvider( + "http://jabber.org/protocol/muc#rooms", + new NodeInformationProvider() { + public List getNodeItems() { + ArrayList answer = new ArrayList(); + Iterator rooms = MultiUserChat.getJoinedRooms(connection); + while (rooms.hasNext()) { + answer.add(new DiscoverItems.Item((String)rooms.next())); + } + return answer; + } +}); +``` + +Discover items associated with an XMPP entity +--------------------------------------------- + +**Description** + +In order to obtain information about a specific item you have to first +discover the items available in an XMPP entity. + +**Usage** + +Once you have your ServiceDiscoveryManager you will be able to discover items +associated with an XMPP entity. To discover the items of a given XMPP entity +send **discoverItems(entityID)** to your _**ServiceDiscoveryManager**_ where +entityID is the ID of the entity. The message **discoverItems(entityID)** will +answer an instance of _**DiscoverItems**_ that contains the discovered items. + +**Examples** + +In this example we can see how to discover the items associated with an online +catalog service: + +``` +// Obtain the ServiceDiscoveryManager associated with my XMPPConnection +ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); +// Get the items of a given XMPP entity +// This example gets the items associated with online catalog service +DiscoverItems discoItems = discoManager.discoverItems("plays.shakespeare.lit"); +// Get the discovered items of the queried XMPP entity +Iterator it = discoItems.getItems(); +// Display the items of the remote XMPP entity +while (it.hasNext()) { + DiscoverItems.Item item = (DiscoverItems.Item) it.next(); + System.out.println(item.getEntityID()); + System.out.println(item.getNode()); + System.out.println(item.getName()); +} +``` + +Discover information about an XMPP entity +----------------------------------------- + +**Description** + +Once you have discovered the entity ID and name of an item, you may want to +find out more about the item. The information desired generally is of two +kinds: 1) The item's identity and 2) The features offered by the item. + +This information helps you determine what actions are possible with regard to +this item (registration, search, join, etc.) as well as specific feature types +of interest, if any (e.g., for the purpose of feature negotiation). + +**Usage** + +Once you have your ServiceDiscoveryManager you will be able to discover +information associated with an XMPP entity. To discover the information of a +given XMPP entity send **discoverInfo(entityID)** to your +_**ServiceDiscoveryManager**_ where entityID is the ID of the entity. The +message **discoverInfo(entityID)** will answer an instance of +_**DiscoverInfo**_ that contains the discovered information. + +**Examples** + +In this example we can see how to discover the information of a conference +room: + +``` +// Obtain the ServiceDiscoveryManager associated with my XMPPConnection +ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); +// Get the information of a given XMPP entity +// This example gets the information of a conference room +DiscoverInfo discoInfo = discoManager.discoverInfo("balconyscene@plays.shakespeare.lit"); +// Get the discovered identities of the remote XMPP entity +Iterator it = discoInfo.getIdentities(); +// Display the identities of the remote XMPP entity +while (it.hasNext()) { + DiscoverInfo.Identity identity = (DiscoverInfo.Identity) it.next(); + System.out.println(identity.getName()); + System.out.println(identity.getType()); + System.out.println(identity.getCategory()); +} +// Check if room is password protected +discoInfo.containsFeature("muc_passwordprotected"); +``` + +Publish publicly available items +-------------------------------- + +**Description** + +Publish your entity items to some kind of persistent storage. This enables +other entities to query that entity using the disco#items namespace and +receive a result even when the entity being queried is not online (or +available). + +**Usage** + +Once you have your ServiceDiscoveryManager you will be able to publish items +to some kind of persistent storage. To publish the items of a given XMPP +entity you have to first create an instance of _**DiscoverItems**_ and +configure it with the items to publish. Then you will have to send +**publishItems(String entityID, DiscoverItems discoverItems)** to your +_**ServiceDiscoveryManager**_ where entityID is the address of the XMPP entity +that will persist the items and discoverItems contains the items to publish. + +**Examples** + +In this example we can see how to publish new items: + +``` +// Obtain the ServiceDiscoveryManager associated with my XMPPConnection +ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); +// Create a DiscoverItems with the items to publish +DiscoverItems itemsToPublish = new DiscoverItems(); +DiscoverItems.Item itemToPublish = new DiscoverItems.Item("pubsub.shakespeare.lit"); +itemToPublish.setName("Avatar"); +itemToPublish.setNode("romeo/avatar"); +itemToPublish.setAction(DiscoverItems.Item.UPDATE_ACTION); +itemsToPublish.addItem(itemToPublish); +// Publish the new items by sending them to the server +discoManager.publishItems("host", itemsToPublish); +``` diff --git a/documentation/extensions/filetransfer.html b/documentation/extensions/filetransfer.html deleted file mode 100644 index 8211b27b4..000000000 --- a/documentation/extensions/filetransfer.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - -// Obtain the ServiceDiscoveryManager associated with my XMPPConnection - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); - - // Create a DiscoverItems with the items to publish - DiscoverItems itemsToPublish = new DiscoverItems(); - DiscoverItems.Item itemToPublish = new DiscoverItems.Item("pubsub.shakespeare.lit"); - itemToPublish.setName("Avatar"); - itemToPublish.setNode("romeo/avatar"); - itemToPublish.setAction(DiscoverItems.Item.UPDATE_ACTION); - itemsToPublish.addItem(itemToPublish); - - // Publish the new items by sending them to the server - discoManager.publishItems("host", itemsToPublish); --
- -The file transfer extension allows the user to transmit and receive files. - -
- -Description
- -A user may wish to send a file to another user. The other user has the option of acception, -rejecting, or ignoring the users request. Smack provides a simple interface in order -to enable the user to easily send a file. - -Usage
- -In order to send a file you must first construct an instance of the FileTransferManager class. -In order to instantiate the manager you should call FileTransferManager.getInstanceFor(connection) - -
Once you have your FileTransferManager you will need to create an outgoing -file transfer to send a file. The method to use on the FileTransferManager -is the createOutgoingFileTransfer(userID) method. The userID you provide to this -method is the fully-qualified jabber ID of the user you wish to send the file to. A -fully-qualified jabber ID consists of a node, a domain, and a resource, the user -must be connected to the resource in order to be able to recieve the file transfer. - -
Now that you have your OutgoingFileTransfer instance you will want -to send the file. The method to send a file is sendFile(file, description). The file - you provide to this method should be a readable file on the local file system, and the description is a short - description of the file to help the user decide whether or not they would like to recieve the file. - -
For information on monitoring the progress of a file transfer see the monitoring progress -section of this document. - -
Other means to send a file are also provided as part of the OutgoingFileTransfer. Please -consult the Javadoc for more information. - - -Examples
-
-In this example we can see how to send a file:
-
-- -- // Create the file transfer manager - FileTransferManager manager = FileTransferManager.getInstanceFor(connection); - - // Create the outgoing file transfer - OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer("romeo@montague.net"); - - // Send the file - transfer.sendFile(new File("shakespeare_complete_works.txt"), "You won't believe this!"); - --
- -Description
- -The user may wish to recieve files from another user. The process of recieving a file is event driven, -new file transfer requests are recieved from other users via a listener registered with the file transfer -manager.
- -Usage- -In order to recieve a file you must first construct an instance of the FileTransferManager class. -In order to instantiate the manager you should call FileTransferManager.getInstanceFor(connection) - -
Once you have your FileTransferManager you will need to register a listener -with it. The FileTransferListner interface has one method, fileTransferRequest(request). -When a request is recieved through this method, you can either accept or reject the -request. To help you make your decision there are several methods in the FileTransferRequest -class that return information about the transfer request. - -
To accept the file transfer, call the accept(), -this method will create an IncomingFileTransfer. After you have the file transfer you may start -to transfer the file by calling the recieveFile(file) method. -The file provided to this method will be where the data from thefile transfer is saved.
- -Finally, to reject the file transfer the only method you need to call is reject() -on the IncomingFileTransfer. - -
For information on monitoring the progress of a file transfer see the monitoring progress -section of this document. - -
Other means to recieve a file are also provided as part of the IncomingFileTransfer. Please -consult the Javadoc for more information. - -Examples
-
-In this example we can see how to approve or reject a file transfer request:
-
-- -// Create the file transfer manager - FileTransferManager manager = FileTransferManager.getInstanceFor(connection); - - // Create the listener - manager.addFileTransferListener(new FileTransferListener() { - public void fileTransferRequest(FileTransferRequest request) { - // Check to see if the request should be accepted - if(shouldAccept(request)) { - // Accept it - IncomingFileTransfer transfer = request.accept(); - transfer.recieveFile(new File("shakespeare_complete_works.txt")); - } else { - // Reject it - request.reject(); - } - } - }); --
- -Description
- -While a file transfer is in progress you may wish to monitor the progress of a file transfer.
- -Usage- -
Both the IncomingFileTransfer and the OutgoingFileTransfer -extend the FileTransfer class which provides several methods to monitor -how a file transfer is progressing: -
-
-In this example we can see how to monitor a file transfer:
-
-- - - diff --git a/documentation/extensions/filetransfer.md b/documentation/extensions/filetransfer.md new file mode 100644 index 000000000..172be71bb --- /dev/null +++ b/documentation/extensions/filetransfer.md @@ -0,0 +1,147 @@ +File Transfer +============= + +The file transfer extension allows the user to transmit and receive files. + + * Send a file to another user + * Recieving a file from another user + * Monitoring the progress of a file transfer + +**XEP related:** [XEP-95](http://www.xmpp.org/extensions/xep-0095.html) [XEP-96](http://www.xmpp.org/extensions/xep-0096.html) [XEP-65](http://www.xmpp.org/extensions/xep-0065.html) [XEP-47](http://www.xmpp.org/extensions/xep-0047.html) + +Send a file to another user +--------------------------- + +**Description** + +A user may wish to send a file to another user. The other user has the option +of acception, rejecting, or ignoring the users request. Smack provides a +simple interface in order to enable the user to easily send a file. **Usage** + +In order to send a file you must first construct an instance of the +**_FileTransferManager_** class. In order to instantiate the manager +you should call _FileTransferManager.getInstanceFor(connection)_ + +Once you have your **_FileTransferManager_** you will need to create an +outgoing file transfer to send a file. The method to use on the +**_FileTransferManager_** is the **createOutgoingFileTransfer(userID)** +method. The userID you provide to this method is the fully-qualified jabber ID +of the user you wish to send the file to. A fully-qualified jabber ID consists +of a node, a domain, and a resource, the user must be connected to the +resource in order to be able to recieve the file transfer. + +Now that you have your **_OutgoingFileTransfer_** instance you will want to +send the file. The method to send a file is **sendFile(file, description)**. +The file you provide to this method should be a readable file on the local +file system, and the description is a short description of the file to help +the user decide whether or not they would like to recieve the file. + +For information on monitoring the progress of a file transfer see the +monitoring progress section of this document. + +Other means to send a file are also provided as part of the +**_OutgoingFileTransfer_**. Please consult the Javadoc for more information. +**Examples** + +In this example we can see how to send a file: + +``` +// Create the file transfer manager +FileTransferManager manager = FileTransferManager.getInstanceFor(connection); +// Create the outgoing file transfer +OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer("romeo@montague.net"); +// Send the file +transfer.sendFile(new File("shakespeare_complete_works.txt"), "You won't believe this!"); +``` + +Recieving a file from another user +---------------------------------- + +**Description** + +The user may wish to recieve files from another user. The process of recieving +a file is event driven, new file transfer requests are recieved from other +users via a listener registered with the file transfer manager. + +**Usage** + +In order to recieve a file you must first construct an instance of the +**_FileTransferManager_** class. This class has one constructor with one +parameter which is your XMPPConnection. In order to instantiate the manager +you should call _FileTransferManager.getInstanceFor(connection)_ + +Once you have your **_FileTransferManager_** you will need to register a +listener with it. The FileTransferListner interface has one method, +**fileTransferRequest(request)**. When a request is recieved through this +method, you can either accept or reject the request. To help you make your +decision there are several methods in the **_FileTransferRequest_** class that +return information about the transfer request. + +To accept the file transfer, call the **accept()**, this method will create an +**_IncomingFileTransfer_**. After you have the file transfer you may start to +transfer the file by calling the **recieveFile(file)** method. The file +provided to this method will be where the data from thefile transfer is saved. + +Finally, to reject the file transfer the only method you need to call is +**reject()** on the **_IncomingFileTransfer_**. + +For information on monitoring the progress of a file transfer see the +monitoring progress section of this document. + +Other means to recieve a file are also provided as part of the +**_IncomingFileTransfer_**. Please consult the Javadoc for more information. +**Examples** + +In this example we can see how to approve or reject a file transfer request: + +``` +// Create the file transfer manager +final FileTransferManager manager = FileTransferManager.getInstanceFor(connection); +// Create the listener +manager.addFileTransferListener(new FileTransferListener() { + public void fileTransferRequest(FileTransferRequest request) { + // Check to see if the request should be accepted + if(shouldAccept(request)) { + // Accept it + IncomingFileTransfer transfer = request.accept(); + transfer.recieveFile(new File("shakespeare_complete_works.txt")); + } else { + // Reject it + request.reject(); + } +} +}); +``` + +Monitoring the progress of a file transfer +------------------------------------------ + +**Description** + +While a file transfer is in progress you may wish to monitor the progress of a +file transfer. + +**Usage** + +Both the **_IncomingFileTransfer_** and the **_OutgoingFileTransfer_** extend +the **_FileTransfer_** class which provides several methods to monitor how a +file transfer is progressing: + + * **getStatus()** - The file transfer can be in several states, negotiating, rejected, canceled, in progress, error, and complete. This method will return which state the file transfer is currently in. + * **getProgress()** - if the status of the file transfer is in progress this method will return a number between 0 and 1, 0 being the transfer has not yet started and 1 being the transfer is complete. It may also return a -1 if the transfer is not in progress. + * **isDone()** - Similar to getProgress() except it returns a _boolean_. If the state is rejected, canceled, error, or complete then true will be returned and false otherwise. + * **getError()** - If there is an error during the file transfer this method will return the type of error that occured. **Examples** + +In this example we can see how to monitor a file transfer: + +``` +while(!transfer.isDone()) { + if(transfer.getStatus().equals(Status.ERROR)) { + System.out.println("ERROR!!! " + transfer.getError()); + } else { + System.out.println(transfer.getStatus()); + System.out.println(transfer.getProgress()); + } + sleep(1000); +} +``` diff --git a/documentation/extensions/hoxt.html b/documentation/extensions/hoxt.html deleted file mode 100644 index 96f3dd559..000000000 --- a/documentation/extensions/hoxt.html +++ /dev/null @@ -1,156 +0,0 @@ - - -while(!transfer.isDone()) { - if(transfer.getStatus().equals(Status.ERROR)) { - System.out.println("ERROR!!! " + transfer.getError()); - } else { - System.out.println(transfer.getStatus()); - System.out.println(transfer.getProgress()); - } - sleep(1000); - } --
- -Allows to transport HTTP communication over XMPP peer-to-peer networks.
- -
- -- -Description
- -Before using this extension you must ensure that your counterpart supports it also.
- -Usage- -
Once you have your ServiceDiscoveryManager you will be able to discover information associated with -an XMPP entity. To discover the information of a given XMPP entity send discoverInfo(entityID) -to your ServiceDiscoveryManager where entityID is the ID of the entity. The message -discoverInfo(entityID) will answer an instance of DiscoverInfo that contains -the discovered information.
- -Examples
-
-In this example we can see how to check if the counterpart supports HOXT:
-
-- -// Obtain the ServiceDiscoveryManager associated with my XMPPConnection - ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); - - // Get the information of a given XMPP entity - DiscoverInfo discoInfo = discoManager.discoverInfo("juliet@capulet.com"); - - // Check if room is HOXT is supported - discoInfo.containsFeature("urn:xmpp:http"); --
- -Description
- -You can use IQ's to perform HTTP requests and responses. -This is applicable to relatively short requests and responses (due to limitation of XMPP message size).
- -Usage- -
First you need to register a PacketListener to be able to handle intended IQs.
-For the HTTP client you: -
-
-In this example we are HTTP client, so we send request (POST) and handle the response:
-
-- -// register listener for IQ packets - connection.addPacketListener(new IqPacketListener(), new PacketTypeFilter(IQ.class)); - - // create a request body - String urlEncodedMessage = "I_love_you"; - - // create request - HttpOverXmppReq.Req req = new HttpOverXmppReq.Req(HttpMethod.POST, "/mailbox"); - req.setVersion("1.1"); - - // prepare headers - Set<Header> set = new HashSet<Header>(); - set.add(new Header("Host", "juliet.capulet.com")); - set.add(new Header("Content-Type", "application/x-www-form-urlencoded")); - set.add(new Header("Content-Length", Integer.toString(urlEncodedMessage.length()))); - req.setHeaders(new HeadersExtension(set)); - - // provide body or request (not mandatory, - empty body is used for GET) - AbstractHttpOverXmpp.Text child = new AbstractHttpOverXmpp.Text(urlEncodedMessage); - AbstractHttpOverXmpp.Data data = new AbstractHttpOverXmpp.Data(child); - req.setData(data); - - // create IQ packet - HttpOverXmppReq packet = new HttpOverXmppReq(); - packet.setReq(req); - packet.setTo("juliet@capulet.com/balcony"); - packet.setType(IQ.Type.SET); - packet.setPacketID("42"); - - // send it - connection.sendPacket(packet); - - - // then in your PacketListener - private class IqPacketListener implements PacketListener { - - @Override - public void processPacket(Packet packet) { - IQ iq = (IQ) packet; - - // verify from and packed ID - if (iq.getFrom().equals("juliet@capulet.com/balcony") && (iq.getPacketID().equals("42"))) { - - // ensure it's not ERROR - if (iq.getType().equals(IQ.Type.RESULT)) { - - // check if correct IQ implementation arrived - if (iq instanceof HttpOverXmppResp) { - HttpOverXmppResp resp = (HttpOverXmppResp) iq; - - // check HTTP response code - if (resp.getResp().getStatusCode() == 200) { - - // get content of the response - AbstractHttpOverXmpp.DataChild child = resp.getResp().getData().getChild(); - - // check which type of content of the response arrived - if (child instanceof AbstractHttpOverXmpp.Xml) { - - // print the message and anxiously read if from console ;) - System.out.println(((AbstractHttpOverXmpp.Xml) child).getText()); - } else { - // process other AbstractHttpOverXmpp.DataChild subtypes - } - } - } - } - } - } - } --
The XMPP protocol includes a base protocol and many optional extensions - typically documented as "XEP's". Smack provides the org.jivesoftware.smack - package for the core XMPP protocol, and the org.jivesoftware.smackx package for - many of the protocol extensions.
- -This manual provides details about each of the "smackx" extensions, including what - it is, how to use it, and some simple example code.
- -
- -
Name | XEP # | Description | -
Private Data | -XEP-0049 | -Manages private data. | -
XHTML Messages | -XEP-0071 | -Allows send and receiving formatted messages using XHTML. | -
Message Events | -XEP-0022 | -Requests and responds to message events. | -
Data Forms | -XEP-0004 | -Allows to gather data using Forms. | -
Multi User Chat | -XEP-0045 | -Allows configuration of, participation in, and administration of individual text-based conference rooms. | -
Roster Item Exchange | -XEP-0093 | -Allows roster data to be shared between users. | -
Time Exchange | -XEP-0090 | -Allows local time information to be shared between users. | -
Group Chat Invitations | -N/A | -Send invitations to other users to join a group chat room. | -
Service Discovery | -XEP-0030 | -Allows to discover services in XMPP entities. | -
File Transfer | -XEP-0096 | -Transfer files between two users over XMPP. | -
PubSub | -XEP-0060 | -Generic publish and subscribe functionality. | -
Entity Capabilities | -XEP-0115 | -Broadcasting and dynamic discovery of entity capabilities. | -
Privacy Lists | -XEP-0016 | -Enabling or disabling communication with other entities. | -
HTTP over XMPP transport | -XEP-0332 | -Allows to transport HTTP communication over XMPP peer-to-peer networks. | -
Jive Properties | -N/A | -TODO | -
- -The group chat invitation packet extension is used to invite other -users to a group chat room. - -
- --XEP related: N/A -- this protocol is outdated now that the Multi-User Chat (MUC) XEP is available -(XEP-45). However, most -existing clients still use this older protocol. Once MUC support becomes more -widespread, this API may be deprecated. - -
- -To use the GroupChatInvitation packet extension -to invite another user to a group chat room, address a new message to the -user and set the room name appropriately, as in the following code example: - -
-Message message = new Message("user@chat.example.com"); -message.setBody("Join me for a group chat!"); -message.addExtension(new GroupChatInvitation("room@chat.example.com")); -con.sendPacket(message); -- -The XML generated for the invitation portion of the code above would be: - -
-<x xmlns="jabber:x:conference" jid="room@chat.example.com"/> -
- -
- -To listen for group chat invitations, use a PacketExtensionFilter for the -x element name and jabber:x:conference namespace, as in the -following code example: - -
-PacketFilter filter = new PacketExtensionFilter("x", "jabber:x:conference"); -// Create a packet collector or packet listeners using the filter... -- - - - \ No newline at end of file diff --git a/documentation/extensions/invitation.md b/documentation/extensions/invitation.md new file mode 100644 index 000000000..30f968ee7 --- /dev/null +++ b/documentation/extensions/invitation.md @@ -0,0 +1,42 @@ +Group Chat Invitations +====================== + +The group chat invitation packet extension is used to invite other users to a +group chat room. + + * Inviting Other Users + * Listen for Invitations + +**XEP related:** N/A -- this protocol is outdated now that the Multi-User Chat (MUC) XEP is available ([XEP-45](http://www.xmpp.org/extensions/xep-0045.html)). However, most existing clients still use this older protocol. Once MUC support becomes more widespread, this API may be deprecated. + +Inviting Other Users +-------------------- + +To use the GroupChatInvitation packet extension to invite another user to a +group chat room, address a new message to the user and set the room name +appropriately, as in the following code example: + +``` +Message message = new Message("user@chat.example.com"); +message.setBody("Join me for a group chat!"); +message.addExtension(new GroupChatInvitation("room@chat.example.com")); +con.sendPacket(message); +``` + +The XML generated for the invitation portion of the code above would be: + +``` +
- -Allows configuration of, participation in, and administration of individual text-based conference rooms.
- -
- -Description
- -Allowed users may create new rooms. There are two types of rooms that you can create. Instant rooms -which are available for immediate access and are automatically created based on some default -configuration and Reserved rooms which are manually configured by the room creator before -anyone is allowed to enter.
- -Usage- -In order to create a room you will need to first create an instance of MultiUserChat. The -room name passed to the constructor will be the name of the room to create. The next step is to send -create(String nickname) to the MultiUserChat instance where nickname is the nickname -to use when joining the room.
- -Depending on the type of room that you want to create you will have to use different configuration forms. In -order to create an Instant room just send sendConfigurationForm(Form form) where form is an empty form. -But if you want to create a Reserved room then you should first get the room's configuration form, complete -the form and finally send it back to the server.
- -Examples
-
-In this example we can see how to create an instant room:
-
-- -In this example we can see how to create a reserved room. The form is completed with default values:// Create a MultiUserChat using a XMPPConnection for a room - MultiUserChat muc = new MultiUserChat(conn1, "myroom@conference.jabber.org"); - - // Create the room - muc.create("testbot"); - - // Send an empty room configuration form which indicates that we want - // an instant room - muc.sendConfigurationForm(new Form(Form.TYPE_SUBMIT)); --
-- -// Create a MultiUserChat using a XMPPConnection for a room - MultiUserChat muc = new MultiUserChat(conn1, "myroom@conference.jabber.org"); - - // Create the room - muc.create("testbot"); - - // Get the the room's configuration form - Form form = muc.getConfigurationForm(); - // Create a new form to submit based on the original form - Form submitForm = form.createAnswerForm(); - // Add default answers to the form to submit - for (Iterator fields = form.getFields(); fields.hasNext();) { - FormField field = (FormField) fields.next(); - if (!FormField.TYPE_HIDDEN.equals(field.getType()) && field.getVariable() != null) { - // Sets the default value as the answer - submitForm.setDefaultAnswer(field.getVariable()); - } - } - // Sets the new owner of the room - List owners = new ArrayList(); - owners.add("johndoe@jabber.org"); - submitForm.setAnswer("muc#roomconfig_roomowners", owners); - // Send the completed form (with default values) to the server to configure the room - muc.sendConfigurationForm(submitForm); --
- -Description
- -Your usual first step in order to send messages to a room is to join the room. Multi User Chat allows -to specify several parameter while joining a room. Basically you can control the amount of history to -receive after joining the room as well as provide your nickname within the room and a password if the -room is password protected.
- -Usage- -In order to join a room you will need to first create an instance of MultiUserChat. The -room name passed to the constructor will be the name of the room to join. The next step is to send -join(...) to the MultiUserChat instance. But first you will have to decide which -join message to send. If you want to just join the room without a password and without specifying the amount -of history to receive then you could use join(String nickname) where nickname if your nickname in -the room. In case the room requires a password in order to join you could then use -join(String nickname, String password). And finally, the most complete way to join a room is to send -join(String nickname, String password, DiscussionHistory history, long timeout) -where nickname is your nickname in the room, , password is your password to join the room, history is -an object that specifies the amount of history to receive and timeout is the milliseconds to wait -for a response from the server.
- -Examples
-
-In this example we can see how to join a room with a given nickname:
-
-- -In this example we can see how to join a room with a given nickname and password:// Create a MultiUserChat using a XMPPConnection for a room - MultiUserChat muc2 = new MultiUserChat(conn1, "myroom@conference.jabber.org"); - - // User2 joins the new room - // The room service will decide the amount of history to send - muc2.join("testbot2"); --
-- -In this example we can see how to join a room with a given nickname specifying the amount of history -to receive:// Create a MultiUserChat using a XMPPConnection for a room - MultiUserChat muc2 = new MultiUserChat(conn1, "myroom@conference.jabber.org"); - - // User2 joins the new room using a password - // The room service will decide the amount of history to send - muc2.join("testbot2", "password"); --
-- -// Create a MultiUserChat using a XMPPConnection for a room - MultiUserChat muc2 = new MultiUserChat(conn1, "myroom@conference.jabber.org"); - - // User2 joins the new room using a password and specifying - // the amount of history to receive. In this example we are requesting the last 5 messages. - DiscussionHistory history = new DiscussionHistory(); - history.setMaxStanzas(5); - muc2.join("testbot2", "password", history, SmackConfiguration.getPacketReplyTimeout()); --
- -Description
- -It can be useful to invite another user to a room in which one is an occupant. Depending on the -room's type the invitee could receive a password to use to join the room and/or be added to the -member list if the room is of type members-only. Smack allows to send room invitations and let -potential invitees to listening for room invitations and inviters to listen for invitees' -rejections.
- -Usage- -In order to invite another user to a room you must be already joined to the room. Once you are -joined just send invite(String participant, String reason) to the MultiUserChat -where participant is the user to invite to the room (e.g. hecate@shakespeare.lit) and reason is -the reason why the user is being invited.
- -If potential invitees want to listen for room invitations then the invitee must add an InvitationListener -to the MultiUserChat class. Since the InvitationListener is an interface, -it is necessary to create a class that implements this interface. If an inviter wants to -listen for room invitation rejections, just add an InvitationRejectionListener -to the MultiUserChat. InvitationRejectionListener is also an -interface so you will need to create a class that implements this interface.
- -Examples
-
-In this example we can see how to invite another user to the room and lister for possible rejections:
-
-- -In this example we can see how to listen for room invitations and decline invitations:// User2 joins the room - MultiUserChat muc2 = new MultiUserChat(conn2, room); - muc2.join("testbot2"); - - // User2 listens for invitation rejections - muc2.addInvitationRejectionListener(new InvitationRejectionListener() { - public void invitationDeclined(String invitee, String reason) { - // Do whatever you need here... - } - }); - - // User2 invites user3 to join to the room - muc2.invite("user3@host.org/Smack", "Meet me in this excellent room"); --
-- -// User3 listens for MUC invitations - MultiUserChat.addInvitationListener(conn3, new InvitationListener() { - public void invitationReceived(XMPPConnection conn, String room, String inviter, String reason, String password) { - // Reject the invitation - MultiUserChat.decline(conn, room, inviter, "I'm busy right now"); - } - }); --
- -Description
- -A user may want to discover if one of the user's contacts supports the Multi-User Chat protocol.
- -Usage- -In order to discover if one of the user's contacts supports MUC just send -isServiceEnabled(XMPPConnection connection, String user) to the MultiUserChat -class where user is a fully qualified XMPP ID, e.g. jdoe@example.com. You will receive -a boolean indicating whether the user supports MUC or not.
- -Examples
-
-In this example we can see how to discover support of MUC:
-
-- -// Discover whether user3@host.org supports MUC or not - boolean supports = MultiUserChat.isServiceEnabled(conn, "user3@host.org/Smack"); --
- -Description
- -A user may also want to query a contact regarding which rooms the contact is in.
- -Usage- -In order to get the rooms where a user is in just send -getJoinedRooms(XMPPConnection connection, String user) to the MultiUserChat -class where user is a fully qualified XMPP ID, e.g. jdoe@example.com. You will get an Iterator -of Strings as an answer where each String represents a room name.
- -Examples
-
-In this example we can see how to get the rooms where a user is in:
-
-- -// Get the rooms where user3@host.org has joined - Iterator joinedRooms = MultiUserChat.getJoinedRooms(conn, "user3@host.org/Smack"); --
- -Description
- -A user may need to discover information about a room without having to actually join the room. The server -will provide information only for public rooms.
- -Usage- -In order to discover information about a room just send getRoomInfo(XMPPConnection connection, String room) -to the MultiUserChat class where room is the XMPP ID of the room, e.g. -roomName@conference.myserver. You will get a RoomInfo object that contains the discovered room -information.
- -Examples
-
-In this example we can see how to discover information about a room:
-
-- -// Discover information about the room roomName@conference.myserver - RoomInfo info = MultiUserChat.getRoomInfo(conn, "roomName@conference.myserver"); - System.out.println("Number of occupants:" + info.getOccupantsCount()); - System.out.println("Room Subject:" + info.getSubject()); --
- -Description
- -A room occupant may want to start a private chat with another room occupant even though they -don't know the fully qualified XMPP ID (e.g. jdoe@example.com) of each other.
- -Usage- -To create a private chat with another room occupant just send createPrivateChat(String participant) -to the MultiUserChat that you used to join the room. The parameter participant is the -occupant unique room JID (e.g. 'darkcave@macbeth.shakespeare.lit/Paul'). You will receive -a regular Chat object that you can use to chat with the other room occupant.
- -Examples
-
-In this example we can see how to start a private chat with another room occupant:
-
-- -// Start a private chat with another participant - Chat chat = muc2.createPrivateChat("myroom@conference.jabber.org/johndoe"); - chat.sendMessage("Hello there"); --
- -Description
- -A common feature of multi-user chat rooms is the ability to change the subject within the room. As a -default, only users with a role of "moderator" are allowed to change the subject in a room. Although -some rooms may be configured to allow a mere participant or even a visitor to change the subject.
- -Every time the room's subject is changed you may want to be notified of the modification. The new subject -could be used to display an in-room message.
- -Usage- -In order to modify the room's subject just send changeSubject(String subject) to the -MultiUserChat that you used to join the room where subject is the new room's subject. On -the other hand, if you want to be notified whenever the room's subject is modified you should add a -SubjectUpdatedListener to the MultiUserChat by sending -addSubjectUpdatedListener(SubjectUpdatedListener listener) to the MultiUserChat. -Since the SubjectUpdatedListener is an interface, it is necessary to create a class -that implements this interface.
- -Examples
-
-In this example we can see how to change the room's subject and react whenever the room's subject is
-modified:
-
-- -// An occupant wants to be notified every time the room's subject is changed - muc3.addSubjectUpdatedListener(new SubjectUpdatedListener() { - public void subjectUpdated(String subject, String from) { - .... - } - }); - - // A room's owner changes the room's subject - muc2.changeSubject("New Subject"); --
- -Description
- -There are four defined roles that an occupant can have:
-- -These roles are temporary in that they do not persist across a user's visits to the room -and can change during the course of an occupant's visit to the room.
- -A moderator is the most powerful occupant within the context of the room, and can to some -extent manage other occupants' roles in the room. A participant has fewer privileges than a -moderator, although he or she always has the right to speak. A visitor is a more restricted -role within the context of a moderated room, since visitors are not allowed to send messages -to all occupants.
- -Roles are granted, revoked, and maintained based on the occupant's room nickname or full -JID. Whenever an occupant's role is changed Smack will trigger specific events.
- -Usage- -In order to grant voice (i.e. make someone a participant) just send the message -grantVoice(String nickname) to MultiUserChat. Use revokeVoice(String nickname) -to revoke the occupant's voice (i.e. make the occupant a visitor).
- -In order to grant moderator privileges to a participant or visitor just send the message -grantModerator(String nickname) to MultiUserChat. Use revokeModerator(String nickname) -to revoke the moderator privilege from the occupant thus making the occupant a participant.
- -Smack allows you to listen for role modification events. If you are interested in listening role modification -events of any occupant then use the listener ParticipantStatusListener. But if you are interested -in listening for your own role modification events, use the listener UserStatusListener. Both listeners -should be added to the MultiUserChat by using -addParticipantStatusListener(ParticipantStatusListener listener) or -addUserStatusListener(UserStatusListener listener) respectively. These listeners include several notification -events but you may be interested in just a few of them. Smack provides default implementations for these listeners -avoiding you to implement all the interfaces' methods. The default implementations are DefaultUserStatusListener -and DefaultParticipantStatusListener. Below you will find the sent messages to the listeners whenever -an occupant's role has changed.
- -These are the triggered events when the role has been upgraded: -
-Old | New | Events |
None | Visitor | -- |
Visitor | Participant | voiceGranted |
Participant | Moderator | moderatorGranted |
None | Participant | voiceGranted |
None | Moderator | voiceGranted + moderatorGranted |
Visitor | Moderator | voiceGranted + moderatorGranted |
- -These are the triggered events when the role has been downgraded: -
-Old | New | Events |
Moderator | Participant | moderatorRevoked |
Participant | Visitor | voiceRevoked |
Visitor | None | kicked |
Moderator | Visitor | voiceRevoked + moderatorRevoked |
Moderator | None | kicked |
Participant | None | kicked |
-
-In this example we can see how to grant voice to a visitor and listen for the notification events:
-
-- -// User1 creates a room - muc = new MultiUserChat(conn1, "myroom@conference.jabber.org"); - muc.create("testbot"); - - // User1 (which is the room owner) configures the room as a moderated room - Form form = muc.getConfigurationForm(); - Form answerForm = form.createAnswerForm(); - answerForm.setAnswer("muc#roomconfig_moderatedroom", "1"); - muc.sendConfigurationForm(answerForm); - - // User2 joins the new room (as a visitor) - MultiUserChat muc2 = new MultiUserChat(conn2, "myroom@conference.jabber.org"); - muc2.join("testbot2"); - // User2 will listen for his own "voice" notification events - muc2.addUserStatusListener(new DefaultUserStatusListener() { - public void voiceGranted() { - super.voiceGranted(); - ... - } - public void voiceRevoked() { - super.voiceRevoked(); - ... - } - }); - - // User3 joins the new room (as a visitor) - MultiUserChat muc3 = new MultiUserChat(conn3, "myroom@conference.jabber.org"); - muc3.join("testbot3"); - // User3 will lister for other occupants "voice" notification events - muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() { - public void voiceGranted(String participant) { - super.voiceGranted(participant); - ... - } - - public void voiceRevoked(String participant) { - super.voiceRevoked(participant); - ... - } - }); - - // The room's owner grants voice to user2 - muc.grantVoice("testbot2"); --
- -Description
- -There are five defined affiliations that a user can have in relation to a room:
-- -These affiliations are semi-permanent in that they persist across a user's visits to the room and -are not affected by happenings in the room. Affiliations are granted, revoked, and maintained -based on the user's bare JID.
- -If a user without a defined affiliation enters a room, the user's affiliation is defined as "none"; -however, this affiliation does not persist across visits.
- -Owners and admins are by definition immune from certain actions. Specifically, an owner or admin cannot -be kicked from a room and cannot be banned from a room. An admin must first lose his or her affiliation -(i.e., have an affiliation of "none" or "member") before such actions could be performed -on them.
- -The member affiliation provides a way for a room owner or admin to specify a "whitelist" of users -who are allowed to enter a members-only room. When a member enters a members-only room, his or her affiliation -does not change, no matter what his or her role is. The member affiliation also provides a way for users to -effectively register with an open room and thus be permanently associated with that room in some way (one -result may be that the user's nickname is reserved in the room).
- -An outcast is a user who has been banned from a room and who is not allowed to enter the room. Whenever a -user's affiliation is changed Smack will trigger specific events.
- -Usage- -In order to grant membership to a room, administrator privileges or owner priveliges just send -grantMembership(String jid), grantAdmin(String jid) or grantOwnership(String jid) -to MultiUserChat respectively. Use revokeMembership(String jid), revokeAdmin(String jid) -or revokeOwnership(String jid) to revoke the membership to a room, administrator privileges or -owner priveliges respectively.
- -In order to ban a user from the room just send the message banUser(String jid, String reason) to -MultiUserChat.
- -Smack allows you to listen for affiliation modification events. If you are interested in listening affiliation modification -events of any user then use the listener ParticipantStatusListener. But if you are interested -in listening for your own affiliation modification events, use the listener UserStatusListener. Both listeners -should be added to the MultiUserChat by using -addParticipantStatusListener(ParticipantStatusListener listener) or -addUserStatusListener(UserStatusListener listener) respectively. These listeners include several notification -events but you may be interested in just a few of them. Smack provides default implementations for these listeners -avoiding you to implement all the interfaces' methods. The default implementations are DefaultUserStatusListener -and DefaultParticipantStatusListener. Below you will find the sent messages to the listeners whenever -a user's affiliation has changed.
- -These are the triggered events when the affiliation has been upgraded: -
-Old | New | Events |
None | Member | membershipGranted |
Member | Admin | membershipRevoked + adminGranted |
Admin | Owner | adminRevoked + ownershipGranted |
None | Admin | adminGranted |
None | Owner | ownershipGranted |
Member | Owner | membershipRevoked + ownershipGranted |
- -These are the triggered events when the affiliation has been downgraded: -
-Old | New | Events |
Owner | Admin | ownershipRevoked + adminGranted |
Admin | Member | adminRevoked + membershipGranted |
Member | None | membershipRevoked |
Owner | Member | ownershipRevoked + membershipGranted |
Owner | None | ownershipRevoked |
Admin | None | adminRevoked |
Anyone | Outcast | banned |
-
-In this example we can see how to grant admin privileges to a user and listen for the notification events:
-
-- - - \ No newline at end of file diff --git a/documentation/extensions/muc.md b/documentation/extensions/muc.md new file mode 100644 index 000000000..9c3aa3644 --- /dev/null +++ b/documentation/extensions/muc.md @@ -0,0 +1,620 @@ +Multi User Chat +=============== + +Allows configuration of, participation in, and administration of individual +text-based conference rooms. + + * Create a new Room + * Join a room + * Manage room invitations + * Discover MUC support + * Discover joined rooms + * Discover room information + * Start a private chat + * Manage changes on room subject + * Manage role modifications + * Manage affiliation modifications + +**XEP related:** [XEP-45](http://www.xmpp.org/extensions/xep-0045.html) + +Create a new Room +----------------- + +**Description** + +Allowed users may create new rooms. There are two types of rooms that you can +create. **Instant rooms** which are available for immediate access and are +automatically created based on some default configuration and **Reserved +rooms** which are manually configured by the room creator before anyone is +allowed to enter. + +**Usage** + +In order to create a room you will need to first create an instance of +_**MultiUserChat**_. The room name passed to the constructor will be the name +of the room to create. The next step is to send **create(String nickname)** to +the _**MultiUserChat**_ instance where nickname is the nickname to use when +joining the room. + +Depending on the type of room that you want to create you will have to use +different configuration forms. In order to create an Instant room just send +**sendConfigurationForm(Form form)** where form is an empty form. But if you +want to create a Reserved room then you should first get the room's +configuration form, complete the form and finally send it back to the server. + +**Examples** + +In this example we can see how to create an instant room: + +``` +// Create a MultiUserChat using a XMPPConnection for a room +MultiUserChat muc = new MultiUserChat(conn1, "myroom@conference.jabber.org"); + +// Create the room +muc.create("testbot"); + +// Send an empty room configuration form which indicates that we want +// an instant room +muc.sendConfigurationForm(new Form(Form.TYPE_SUBMIT)); +``` + +In this example we can see how to create a reserved room. The form is +completed with default values: + + +// Create a MultiUserChat using a XMPPConnection for a room +MultiUserChat muc = new MultiUserChat(conn1, "myroom@conference.jabber.org"); + +// Create the room +muc.create("testbot"); + +// Get the the room's configuration form +Form form = muc.getConfigurationForm(); +// Create a new form to submit based on the original form +Form submitForm = form.createAnswerForm(); +// Add default answers to the form to submit +for (Iterator fields = form.getFields(); fields.hasNext();) { + FormField field = (FormField) fields.next(); + if (!FormField.TYPE_HIDDEN.equals(field.getType()) && field.getVariable() != null) { + // Sets the default value as the answer + submitForm.setDefaultAnswer(field.getVariable()); +} +} +// Sets the new owner of the room +List owners = new ArrayList(); +owners.add("johndoe@jabber.org"); +submitForm.setAnswer("muc#roomconfig_roomowners", owners); +// Send the completed form (with default values) to the server to configure the room +muc.sendConfigurationForm(submitForm); +``` + +Join a room +----------- + +**Description** + +Your usual first step in order to send messages to a room is to join the room. +Multi User Chat allows to specify several parameter while joining a room. +Basically you can control the amount of history to receive after joining the +room as well as provide your nickname within the room and a password if the +room is password protected. + +**Usage** + +In order to join a room you will need to first create an instance of +_**MultiUserChat**_. The room name passed to the constructor will be the name +of the room to join. The next step is to send **join(...)** to the +_**MultiUserChat**_ instance. But first you will have to decide which join +message to send. If you want to just join the room without a password and +without specifying the amount of history to receive then you could use +**join(String nickname)** where nickname if your nickname in the room. In case +the room requires a password in order to join you could then use **join(String +nickname, String password)**. And finally, the most complete way to join a +room is to send **join(String nickname, String password, DiscussionHistory +history, long timeout)** where nickname is your nickname in the room, , +password is your password to join the room, history is an object that +specifies the amount of history to receive and timeout is the milliseconds to +wait for a response from the server. + +**Examples** + +In this example we can see how to join a room with a given nickname: + +``` +// Create a MultiUserChat using a XMPPConnection for a room +MultiUserChat muc2 = new MultiUserChat(conn1, "myroom@conference.jabber.org"); +// User2 joins the new room +// The room service will decide the amount of history to send +muc2.join("testbot2"); +``` + +In this example we can see how to join a room with a given nickname and +password: + +``` +// Create a MultiUserChat using a XMPPConnection for a room +MultiUserChat muc2 = new MultiUserChat(conn1, "myroom@conference.jabber.org"); + +// User2 joins the new room using a password +// The room service will decide the amount of history to send +muc2.join("testbot2", "password"); +``` + +In this example we can see how to join a room with a given nickname specifying +the amount of history to receive: + +``` +// Create a MultiUserChat using a XMPPConnection for a room +MultiUserChat muc2 = new MultiUserChat(conn1, "myroom@conference.jabber.org"); + +// User2 joins the new room using a password and specifying +// the amount of history to receive. In this example we are requesting the last 5 messages. +DiscussionHistory history = new DiscussionHistory(); +history.setMaxStanzas(5); +muc2.join("testbot2", "password", history, conn1.getPacketReplyTimeout()); +``` + +Manage room invitations +----------------------- + +**Description** + +It can be useful to invite another user to a room in which one is an occupant. +Depending on the room's type the invitee could receive a password to use to +join the room and/or be added to the member list if the room is of type +members-only. Smack allows to send room invitations and let potential invitees +to listening for room invitations and inviters to listen for invitees' +rejections. + +**Usage** + +In order to invite another user to a room you must be already joined to the +room. Once you are joined just send **invite(String participant, String +reason)** to the _**MultiUserChat**_ where participant is the user to invite +to the room (e.g. hecate@shakespeare.lit) and reason is the reason why the +user is being invited. + +If potential invitees want to listen for room invitations then the invitee +must add an _**InvitationListener**_ to the _**MultiUserChat**_ class. Since +the _**InvitationListener**_ is an _interface_, it is necessary to create a +class that implements this _interface_. If an inviter wants to listen for room +invitation rejections, just add an _**InvitationRejectionListener**_ to the +_**MultiUserChat**_. _**InvitationRejectionListener**_ is also an interface so +you will need to create a class that implements this interface. + +**Examples** + +In this example we can see how to invite another user to the room and lister +for possible rejections: + +``` +// User2 joins the room +MultiUserChat muc2 = new MultiUserChat(conn2, room); +muc2.join("testbot2"); +// User2 listens for invitation rejections +muc2.addInvitationRejectionListener(new InvitationRejectionListener() { + public void invitationDeclined(String invitee, String reason) { + // Do whatever you need here... + } +}); +// User2 invites user3 to join to the room +muc2.invite("user3@host.org/Smack", "Meet me in this excellent room"); +``` + +In this example we can see how to listen for room invitations and decline +invitations: + +``` +// User3 listens for MUC invitations +MultiUserChat.addInvitationListener(conn3, new InvitationListener() { + public void invitationReceived(XMPPConnection conn, String room, String inviter, String reason, String password) { + // Reject the invitation + MultiUserChat.decline(conn, room, inviter, "I'm busy right now"); + } +}); +``` + +Discover MUC support +-------------------- + +**Description** + +A user may want to discover if one of the user's contacts supports the Multi- +User Chat protocol. + +**Usage** + +In order to discover if one of the user's contacts supports MUC just send +**isServiceEnabled(XMPPConnection connection, String user)** to the +_**MultiUserChat**_ class where user is a fully qualified XMPP ID, e.g. +jdoe@example.com. You will receive a boolean indicating whether the user +supports MUC or not. + +**Examples** + +In this example we can see how to discover support of MUC: + +``` +// Discover whether user3@host.org supports MUC or not +boolean supports = MultiUserChat.isServiceEnabled(conn, "user3@host.org/Smack"); +``` + +Discover joined rooms +--------------------- + +**Description** + +A user may also want to query a contact regarding which rooms the contact is +in. + +**Usage** + +In order to get the rooms where a user is in just send +**getJoinedRooms(XMPPConnection connection, String user)** to the +_**MultiUserChat**_ class where user is a fully qualified XMPP ID, e.g. +jdoe@example.com. You will get an Iterator of Strings as an answer where each +String represents a room name. + +**Examples** + +In this example we can see how to get the rooms where a user is in: + +``` +// Get the rooms where user3@host.org has joined +Iterator joinedRooms = MultiUserChat.getJoinedRooms(conn, "user3@host.org/Smack"); +``` + +Discover room information +------------------------- + +**Description** + +A user may need to discover information about a room without having to +actually join the room. The server will provide information only for public +rooms. + +**Usage** + +In order to discover information about a room just send +**getRoomInfo(XMPPConnection connection, String room)** to the +_**MultiUserChat**_ class where room is the XMPP ID of the room, e.g. +roomName@conference.myserver. You will get a RoomInfo object that contains the +discovered room information. + +**Examples** + +In this example we can see how to discover information about a room: + +``` +// Discover information about the room roomName@conference.myserver +RoomInfo info = MultiUserChat.getRoomInfo(conn, "roomName@conference.myserver"); +System.out.println("Number of occupants:" + info.getOccupantsCount()); +System.out.println("Room Subject:" + info.getSubject()); +``` + +Start a private chat +-------------------- + +**Description** + +A room occupant may want to start a private chat with another room occupant +even though they don't know the fully qualified XMPP ID (e.g. +jdoe@example.com) of each other. + +**Usage** + +To create a private chat with another room occupant just send +**createPrivateChat(String participant)** to the _**MultiUserChat**_ that you +used to join the room. The parameter participant is the occupant unique room +JID (e.g. 'darkcave@macbeth.shakespeare.lit/Paul'). You will receive a regular +_**Chat**_ object that you can use to chat with the other room occupant. + +**Examples** + +In this example we can see how to start a private chat with another room +occupant: + +``` +// Start a private chat with another participant +Chat chat = muc2.createPrivateChat("myroom@conference.jabber.org/johndoe"); +chat.sendMessage("Hello there"); +``` + +Manage changes on room subject +------------------------------ + +**Description** + +A common feature of multi-user chat rooms is the ability to change the subject +within the room. As a default, only users with a role of "moderator" are +allowed to change the subject in a room. Although some rooms may be configured +to allow a mere participant or even a visitor to change the subject. + +Every time the room's subject is changed you may want to be notified of the +modification. The new subject could be used to display an in-room message. + +**Usage** + +In order to modify the room's subject just send **changeSubject(String +subject)** to the _**MultiUserChat**_ that you used to join the room where +subject is the new room's subject. On the other hand, if you want to be +notified whenever the room's subject is modified you should add a +_**SubjectUpdatedListener**_ to the _**MultiUserChat**_ by sending +**addSubjectUpdatedListener(SubjectUpdatedListener listener)** to the +_**MultiUserChat**_. Since the _**SubjectUpdatedListener**_ is an _interface_, +it is necessary to create a class that implements this _interface_. + +**Examples** + +In this example we can see how to change the room's subject and react whenever +the room's subject is modified: + +``` +// An occupant wants to be notified every time the room's subject is changed +muc3.addSubjectUpdatedListener(new SubjectUpdatedListener() { + public void subjectUpdated(String subject, String from) { + .... + } +}); +// A room's owner changes the room's subject +muc2.changeSubject("New Subject"); +``` + +Manage role modifications +------------------------- + +**Description** + +There are four defined roles that an occupant can have: + + 1. Moderator + 2. Participant + 3. Visitor + 4. None (the absence of a role) + +These roles are temporary in that they do not persist across a user's visits +to the room and can change during the course of an occupant's visit to the +room. + +A moderator is the most powerful occupant within the context of the room, and +can to some extent manage other occupants' roles in the room. A participant +has fewer privileges than a moderator, although he or she always has the right +to speak. A visitor is a more restricted role within the context of a +moderated room, since visitors are not allowed to send messages to all +occupants. + +Roles are granted, revoked, and maintained based on the occupant's room +nickname or full JID. Whenever an occupant's role is changed Smack will +trigger specific events. + +**Usage** + +In order to grant voice (i.e. make someone a _participant_) just send the +message **grantVoice(String nickname)** to _**MultiUserChat**_. Use +**revokeVoice(String nickname)** to revoke the occupant's voice (i.e. make the +occupant a _visitor_). + +In order to grant moderator privileges to a participant or visitor just send +the message **grantModerator(String nickname)** to _**MultiUserChat**_. Use +**revokeModerator(String nickname)** to revoke the moderator privilege from +the occupant thus making the occupant a participant. + +Smack allows you to listen for role modification events. If you are interested +in listening role modification events of any occupant then use the listener +**_ParticipantStatusListener_**. But if you are interested in listening for +your own role modification events, use the listener **_UserStatusListener_**. +Both listeners should be added to the _**MultiUserChat**_ by using +**addParticipantStatusListener(ParticipantStatusListener listener)** or +**addUserStatusListener(UserStatusListener listener)** respectively. These +listeners include several notification events but you may be interested in +just a few of them. Smack provides default implementations for these listeners +avoiding you to implement all the interfaces' methods. The default +implementations are **_DefaultUserStatusListener_** and +**_DefaultParticipantStatusListener_**. Below you will find the sent messages +to the listeners whenever an occupant's role has changed. + +These are the triggered events when the role has been upgraded: + +| Old | New | Events | +|-----|-----|--------| +| None | Visitor | -- | +| Visitor | Participant | voiceGranted | +| Participant | Moderator | moderatorGranted | +| None | Participant | voiceGranted | +| None | Moderator | voiceGranted + moderatorGranted | +| Visitor | Moderator | voiceGranted + moderatorGranted | + +These are the triggered events when the role has been downgraded: + +| Old | New | Events | +|-----|-----|--------| +| Moderator | Participant | moderatorRevoked | +| Participant | Visitor | voiceRevoked | +| Visitor | None | kicked | +| Moderator | Visitor | voiceRevoked + moderatorRevoked | +| Moderator | None | kicked | +| Participant | None | kicked | + +**Examples** + +In this example we can see how to grant voice to a visitor and listen for the +notification events: + +``` +// User1 creates a room +muc = new MultiUserChat(conn1, "myroom@conference.jabber.org"); +muc.create("testbot"); +// User1 (which is the room owner) configures the room as a moderated room +Form form = muc.getConfigurationForm(); +Form answerForm = form.createAnswerForm(); +answerForm.setAnswer("muc#roomconfig_moderatedroom", "1"); +muc.sendConfigurationForm(answerForm); +// User2 joins the new room (as a visitor) +MultiUserChat muc2 = new MultiUserChat(conn2, "myroom@conference.jabber.org"); +muc2.join("testbot2"); +// User2 will listen for his own "voice" notification events +muc2.addUserStatusListener(new DefaultUserStatusListener() { + public void voiceGranted() { + super.voiceGranted(); + ... + } + public void voiceRevoked() { + super.voiceRevoked(); + ... + } +}); +// User3 joins the new room (as a visitor) +MultiUserChat muc3 = new MultiUserChat(conn3, "myroom@conference.jabber.org"); +muc3.join("testbot3"); +// User3 will lister for other occupants "voice" notification events +muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() { + public void voiceGranted(String participant) { + super.voiceGranted(participant); + ... + } + public void voiceRevoked(String participant) { + super.voiceRevoked(participant); + ... + } +}); + +// The room's owner grants voice to user2 +muc.grantVoice("testbot2"); +``` + +Manage affiliation modifications +-------------------------------- + +**Description** + +There are five defined affiliations that a user can have in relation to a +room: + + 1. Owner + 2. Admin + 3. Member + 4. Outcast + 5. None (the absence of an affiliation) + +These affiliations are semi-permanent in that they persist across a user's +visits to the room and are not affected by happenings in the room. +Affiliations are granted, revoked, and maintained based on the user's bare +JID. + +If a user without a defined affiliation enters a room, the user's affiliation +is defined as "none"; however, this affiliation does not persist across +visits. + +Owners and admins are by definition immune from certain actions. Specifically, +an owner or admin cannot be kicked from a room and cannot be banned from a +room. An admin must first lose his or her affiliation (i.e., have an +affiliation of "none" or "member") before such actions could be performed on +them. + +The member affiliation provides a way for a room owner or admin to specify a +"whitelist" of users who are allowed to enter a members-only room. When a +member enters a members-only room, his or her affiliation does not change, no +matter what his or her role is. The member affiliation also provides a way for +users to effectively register with an open room and thus be permanently +associated with that room in some way (one result may be that the user's +nickname is reserved in the room). + +An outcast is a user who has been banned from a room and who is not allowed to +enter the room. Whenever a user's affiliation is changed Smack will trigger +specific events. + +**Usage** + +In order to grant membership to a room, administrator privileges or owner +priveliges just send **grantMembership(String jid)**, **grantAdmin(String +jid)** or **grantOwnership(String jid)** to _**MultiUserChat**_ respectively. +Use **revokeMembership(String jid)**, **revokeAdmin(String jid)** or +**revokeOwnership(String jid)** to revoke the membership to a room, +administrator privileges or owner priveliges respectively. + +In order to ban a user from the room just send the message **banUser(String +jid, String reason)** to _**MultiUserChat**_. + +Smack allows you to listen for affiliation modification events. If you are +interested in listening affiliation modification events of any user then use +the listener **_ParticipantStatusListener_**. But if you are interested in +listening for your own affiliation modification events, use the listener +**_UserStatusListener_**. Both listeners should be added to the +_**MultiUserChat**_ by using +**addParticipantStatusListener(ParticipantStatusListener listener)** or +**addUserStatusListener(UserStatusListener listener)** respectively. These +listeners include several notification events but you may be interested in +just a few of them. Smack provides default implementations for these listeners +avoiding you to implement all the interfaces' methods. The default +implementations are **_DefaultUserStatusListener_** and +**_DefaultParticipantStatusListener_**. Below you will find the sent messages +to the listeners whenever a user's affiliation has changed. + +These are the triggered events when the affiliation has been upgraded: + +| Old | New | Events | +|-----|-----|--------| +| None | Member | membershipGranted | +| Member | Admin | membershipRevoked + adminGranted | +| Admin | Owner | adminRevoked + ownershipGranted | +| None | Admin | adminGranted | +| None | Owner | ownershipGranted | +| Member | Owner | membershipRevoked + ownershipGranted | + +These are the triggered events when the affiliation has been downgraded: + +| Old | New | Events | +|-----|-----|--------| +| Owner | Admin | ownershipRevoked + adminGranted | +| Admin | Member | adminRevoked + membershipGranted | +| Member | None | membershipRevoked | +| Owner | Member | ownershipRevoked + membershipGranted | +| Owner | None | ownershipRevoked | +| Admin | None | adminRevoked | +| _Anyone_ | Outcast | banned | + +**Examples** + +In this example we can see how to grant admin privileges to a user and listen +for the notification events: + +``` +// User1 creates a room +muc = new MultiUserChat(conn1, "myroom@conference.jabber.org"); +muc.create("testbot"); +// User1 (which is the room owner) configures the room as a moderated room +Form form = muc.getConfigurationForm(); +Form answerForm = form.createAnswerForm(); +answerForm.setAnswer("muc#roomconfig_moderatedroom", "1"); +muc.sendConfigurationForm(answerForm); +// User2 joins the new room (as a visitor) +MultiUserChat muc2 = new MultiUserChat(conn2, "myroom@conference.jabber.org"); +muc2.join("testbot2"); +// User2 will listen for his own admin privileges +muc2.addUserStatusListener(new DefaultUserStatusListener() { + public void membershipRevoked() { + super.membershipRevoked(); + ... + } + public void adminGranted() { + super.adminGranted(); + ... + } +}); +// User3 joins the new room (as a visitor) +MultiUserChat muc3 = new MultiUserChat(conn3, "myroom@conference.jabber.org"); +muc3.join("testbot3"); +// User3 will lister for other users admin privileges +muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() { + public void membershipRevoked(String participant) { + super.membershipRevoked(participant); + ... + } + public void adminGranted(String participant) { + super.adminGranted(participant); + ... + } +}); +// The room's owner grants admin privileges to user2 +muc.grantAdmin("user2@jabber.org"); +``` diff --git a/documentation/extensions/privacy.html b/documentation/extensions/privacy.html deleted file mode 100644 index 025905aef..000000000 --- a/documentation/extensions/privacy.html +++ /dev/null @@ -1,164 +0,0 @@ - - -// User1 creates a room - muc = new MultiUserChat(conn1, "myroom@conference.jabber.org"); - muc.create("testbot"); - - // User1 (which is the room owner) configures the room as a moderated room - Form form = muc.getConfigurationForm(); - Form answerForm = form.createAnswerForm(); - answerForm.setAnswer("muc#roomconfig_moderatedroom", "1"); - muc.sendConfigurationForm(answerForm); - - // User2 joins the new room (as a visitor) - MultiUserChat muc2 = new MultiUserChat(conn2, "myroom@conference.jabber.org"); - muc2.join("testbot2"); - // User2 will listen for his own admin privileges - muc2.addUserStatusListener(new DefaultUserStatusListener() { - public void membershipRevoked() { - super.membershipRevoked(); - ... - } - public void adminGranted() { - super.adminGranted(); - ... - } - }); - - // User3 joins the new room (as a visitor) - MultiUserChat muc3 = new MultiUserChat(conn3, "myroom@conference.jabber.org"); - muc3.join("testbot3"); - // User3 will lister for other users admin privileges - muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() { - public void membershipRevoked(String participant) { - super.membershipRevoked(participant); - ... - } - public void adminGranted(String participant) { - super.adminGranted(participant); - ... - } - }); - - // The room's owner grants admin privileges to user2 - muc.grantAdmin("user2@jabber.org"); --
What is?
-
-Privacy is a method for users to block communications from particular other users. In XMPP this is done by managing one's privacy lists.
-Server-side privacy lists enable successful completion of the following use cases:
-
- -
How can I use it?
- --The API implementation releases three main public classes: -
- // Create a privacy manager for the current connection. - PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); - // Retrieve server privacy lists - PrivacyList[] lists = privacyManager.getPrivacyLists(); --
- // Set the name of the list - String listName = "newList"; - - // Create the list of PrivacyItem that will allow or deny some privacy aspect - String user = "tybalt@example.com"; - String groupName = "enemies"; - ArrayList privacyItems = new ArrayList(); - - PrivacyItem item = new PrivacyItem(PrivacyItem.Type.jid, user, true, 1); - privacyItems.add(item); - - item = new PrivacyItem(PrivacyItem.Type.subscription, PrivacyItem.SUBSCRIPTION_BOTH, true, 2); - privacyItems.add(item); - - item = new PrivacyItem(PrivacyItem.Type.group, groupName, false, 3); - item.setFilterMessage(true); - privacyItems.add(item); - - // Get the privacy manager for the current connection. - PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); - // Create the new list. - privacyManager.createPrivacyList(listName, privacyItems); --
- // Set the name of the list - String listName = "existingList"; - // Get the privacy manager for the current connection. - PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); - // Sent the new list to the server. - privacyManager.updatePrivacyList(listName, items); --
- // Set the name of the list - String listName = "existingList"; - // Get the privacy manager for the current connection. - PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); - // Remove the list. - privacyManager.deletePrivacyList(listName); --
- // Get the privacy manager for the current connection. - PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); - // Decline the use of the active list. - privacyManager.declineActiveList(); --
- // Get the privacy manager for the current connection. - PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); - // Decline the use of the default list. - privacyManager.declineDefaultList(); --
Listening for Privacy Changes
-
-In order to handle privacy changes, clients SHOULD listen manager's updates.
-When a list is changed the manager notifies every added listener. Listeners MUST implement the PrivacyListListener interface.
-
-
-
-Clients may need to react when a privacy list is modified. The PrivacyListManager lets you add listerners that will be notified when a list has been changed. Listeners should implement the PrivacyListListener interface.
-The most important notification is updatedPrivacyList that is performed when a privacy list changes its privacy items.
-
-The listener becomes notified after performing:
-
- // Get the privacy manager for the current connection. - PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection); - // Add the listener (this) to get notified - privacyManager.addListener(this); --
References
- - - -- -Manages private data, which is a mechanism to allow users to store arbitrary XML -data on an XMPP server. Each private data chunk is defined by a element name and -XML namespace. Example private data: - -
-<color xmlns="http://example.com/xmpp/color"> - <favorite>blue</blue> - <leastFavorite>puce</leastFavorite> -</color> -
- -XEP related: XEP-49 - -
-Smack provides an easy mechanism for attaching arbitrary properties to packets. Each property -has a String name, and a value that is a Java primitive (int, long, float, double, boolean) or -any Serializable object (a Java object is Serializable when it implements the Serializable -interface). -
- --Using the API -
- --All major objects have property support, such as Message objects. The following code -demonstrates how to set properties: -
- --Message message = chat.createMessage(); -JivePropertiesExtension jpe = new JivePropertiesExtension(); -// Add a Color object as a property. -jpe.setProperty("favoriteColor", new Color(0, 0, 255)); -// Add an int as a property. -jpe.setProperty("favoriteNumber", 4); -// Add the JivePropertiesExtension to the message packet -message.addPacketExtension(jpe); -chat.sendMessage(message); -
-Getting those same properties would use the following code: -
- --Message message = chat.nextMessage(); -// Get the JivePropertiesExtension -JivePropertiesExtension jpe = message.getExtension(JivePropertiesExtension.NAMESPACE); -// Get a Color object property. -Color favoriteColor = (Color)jpe.getProperty("favoriteColor"); -// Get an int property. Note that properties are always returned as -// Objects, so we must cast the value to an Integer, then convert -// it to an int. -int favoriteNumber = ((Integer)jpe.getProperty("favoriteNumber")).intValue(); -
-For convenience JivePropertiesManager
contains two helper
-methods namely addProperty(Packet packet, String name, Object
-value)
and
-getProperty(Packet packet, String name)
.
-
-Objects as Properties -
- --Using objects as property values is a very powerful and easy way to exchange data. However, -you should keep the following in mind: -
- --XML Format -
- --The current XML format used to send property data is not a standard, so will likely not be -recognized by clients not using Smack. The XML looks like the following (comments added for -clarity): -
- --<!-- All properties are in a x block. --> -<properties xmlns="http://www.jivesoftware.com/xmlns/xmpp/properties"> - <!-- First, a property named "prop1" that's an integer. --> - <property> - <name>prop1</name> - <value type="integer">123</value> - <property> - <!-- Next, a Java object that's been serialized and then converted - from binary data to base-64 encoded text. --> - <property> - <name>blah2</name> - <value type="java-object">adf612fna9nab</value> - <property> -</properties> -
-The currently supported types are: integer, long, float, -double, boolean, string, and java-object. -
- - - - - diff --git a/documentation/extensions/properties.md b/documentation/extensions/properties.md new file mode 100644 index 000000000..9a8e5d9a8 --- /dev/null +++ b/documentation/extensions/properties.md @@ -0,0 +1,83 @@ +Packet Properties +================= + +Smack provides an easy mechanism for attaching arbitrary properties to +packets. Each property has a String name, and a value that is a Java primitive +(int, long, float, double, boolean) or any Serializable object (a Java object +is Serializable when it implements the Serializable interface). + +Using the API +------------- + +All major objects have property support, such as Message objects. The +following code demonstrates how to set properties: + +``` +Message message = chat.createMessage(); +JivePropertiesExtension jpe = new JivePropertiesExtension(); +// Add a Color object as a property._ +jpe.setProperty("favoriteColor", new Color(0, 0, 255)); +// Add an int as a property._ +jpe.setProperty("favoriteNumber", 4); +// Add the JivePropertiesExtension to the message packet_ +message.addPacketExtension(jpe); +chat.sendMessage(message); +``` + +Getting those same properties would use the following code: + +``` +Message message = chat.nextMessage(); +// Get the JivePropertiesExtension_ +JivePropertiesExtension jpe = message.getExtension(JivePropertiesExtension.NAMESPACE); +// Get a Color object property._ +Color favoriteColor = (Color)jpe.getProperty("favoriteColor"); +// Get an int property. Note that properties are always returned as +// Objects, so we must cast the value to an Integer, then convert +// it to an int._ +int favoriteNumber = ((Integer)jpe.getProperty("favoriteNumber")).intValue(); +``` + +For convenience `JivePropertiesManager` contains two helper methods namely +`addProperty(Packet packet, String name, Object value)` and +`getProperty(Packet packet, String name)`. + +Objects as Properties +--------------------- + +Using objects as property values is a very powerful and easy way to exchange +data. However, you should keep the following in mind: + + * When you send a Java object as a property, only clients running Java will be able to interpret the data. So, consider using a series of primitive values to transfer data instead. + * Objects sent as property values must implement Serialiable. Additionally, both the sender and receiver must have identical versions of the class, or a serialization exception will occur when de-serializing the object. + * Serialized objects can potentially be quite large, which will use more bandwidth and server resources. + +XML Format +---------- + +The current XML format used to send property data is not a standard, so will +likely not be recognized by clients not using Smack. The XML looks like the +following (comments added for clarity): + + + + +-This section details the usage of an API designed for accessing an XMPP based -implementation of a publish and subscribe -based messaging system. It has functionality for creation, configuration of, -subscription and publishing to pubsub nodes.
- -
- -Description
-Allowed users may create and configure pubsub nodes. There are two types of nodes that can be created, -leaf nodes and collection nodes. -
- -In order to create a node you will need to first create an instance of PubSubManager. There -are several options for node creation which range from creating an instant node, default configuration, or -a fully configured node.
- -Examples
-
-Create an instant node:
-
-- -Create a node with default configuration and then configure it:- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Create the node - LeafNode leaf = mgr.createNode(); --
--Create and configure a node:- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Create the node - LeafNode leaf = mgr.createNode("testNode"); - ConfigureForm form = new ConfigureForm(FormType.submit); - form.setAccessModel(AccessModel.open); - form.setDeliverPayloads(false); - form.setNotifyRetract(true); - form.setPersistentItems(true); - form.setPublishModel(PublishModel.open); - - leaf.sendConfigurationForm(form); - --
--- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Create the node - ConfigureForm form = new ConfigureForm(FormType.submit); - form.setAccessModel(AccessModel.open); - form.setDeliverPayloads(false); - form.setNotifyRetract(true); - form.setPersistentItems(true); - form.setPublishModel(PublishModel.open); - LeafNode leaf = mgr.createNode("testNode", form); - --
- -Description
-This section deals with the publish portion of pubsub. - -Usage of a node typically involves either sending or receiving data, referred to as items. -Depending on the context of the nodes usage, the item being sent to it can have different -properties. - -It can contain application data known as payload, or the publisher may choose to supply -meaningful unique id's. Determination of an items acceptable properties is defined by a -combination of node configuration and its purpose. -
- -Usage-To publish to a node, you will have to either create or retrieve an existing node and then -create and send items to that node. The ability for any given person to publish to the node -will be dependent on its configuration. -
- -Examples
-In this example we publish an item to a node that does not take payload:
-
--In this example we publish an item to a node that does take payload:- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get the node - LeafNode node = mgr.getNode("testNode"); - - // Publish an Item, let service set the id - node.send(new Item()); - - // Publish an Item with the specified id - node.send(new Item("123abc")); --
-- -- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get the node - LeafNode node = mgr.getNode("testNode"); - - // Publish an Item with payload - node.send(new PayloadItem-("test" + System.currentTimeMillis(), - new SimplePayload("book", "pubsub:test:book", " "))); - - Two Towers
- -Description
-This section deals with the subscribe portion of pubsub. - -As mentioned in the last section, usage of a node typically involves either sending or receiving -items. Subscribers are interested in being notified when items are published to the pubsub -node. These items may or may not have application specific data (payload), as that -is dependent on the context in which the node is being used. -
- -Usage-To get messages asynchronously when items are published to a node, you will have to -
-Please note that you should register the listener before subscribing so that all messages -sent after subscribing are received. If done in the reverse order, messages that are sent -after subscribing but before registering a listener may not be processed as expected. -
- -Examples
-
-In this example we can see how to create a listener and register it and then subscribe for
-messages.
-
-- -Where the listener is defined like so: - -- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get the node - LeafNode node = mgr.getNode("testNode"); - - node.addItemEventListener(new ItemEventCoordinator<Item>()); - node.subscribe(myJid); --
-- -In addition to receiving published items, there are notifications for several other -events that occur on a node as well. -- - class ItemEventCoordinator-implements ItemEventListener - { - @Override - public void handlePublishedItems(ItemPublishEvent items) - { - System.out.println("Item count: " + items.getItems().size()); - System.out.println(items); - } - } -
-In this example we can see how to create a listener, register it and then subscribe for
-item deletion messages.
-
-- -Where the handler is defined like so: - -- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get the node - LeafNode node = mgr.getNode("testNode"); - - node.addItemDeleteListener(new ItemDeleteCoordinator<Item>()); - node.subscribe(myJid); - node.deleteItem("id_one"); --
--In this example we can see how to create a listener, register it and then subscribe for -node configuration messages.- - class ItemDeleteCoordinator implements ItemDeleteListener-- { - @Override - public void handleDeletedItems(ItemDeleteEvent items) - { - System.out.println("Item count: " + items.getItemIds().size()); - System.out.println(items); - } - - @Override - public void handlePurge() - { - System.out.println("All items have been deleted from node"); - } - } -
-- -Where the handler is defined like so: - -- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get the node - Node node = mgr.getNode("testNode"); - - node.addConfigurationListener(new NodeConfigCoordinator()); - node.subscribe(myJid); - - ConfigureForm form = new ConfigureForm(FormType.submit); - form.setAccessModel(AccessModel.open); - form.setDeliverPayloads(false); - form.setNotifyRetract(true); - form.setPersistentItems(true); - form.setPublishModel(PublishModel.open); - - node.sendConfigurationForm(form); - --
--- - class NodeConfigCoordinator implements NodeConfigListener-- { - @Override - public void handleNodeConfiguration(ConfigurationEvent config) - { - System.out.println("New configuration"); - System.out.println(config.getConfiguration()); - } - } -
- -Description
- -When persistent nodes are used, the subscription and registration methods described in the last section -will not enable the retrieval of items that already exist in the node. This section deals with the -specific methods for retrieving these items. - -There are several means of retrieving existing items. You can retrieve all items at once, the last N -items, or the items specified by a collection of id's. - -Please note that the service may, according to the pubsub specification, reply with a list of items -that contains only the item id's (no payload) to save on bandwidth. This will not occur when the id's -are specified since this is the means of guaranteeing retrieval of payload.
- -Usage- -To synchronously retrieve existing items from a persistent node, you will have to get an instance -of a LeafNode and call one of the retrieve methods. -
- -Examples
-
-In this example we can see how to retrieve the existing items from a node:
-
-- -In this example we can see how to retrieve the last N existing items:- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get the node - LeafNode node = mgr.getNode("testNode"); - - Collection<? extends Item> items = node.getItems(); - --
--In this example we can see how to retrieve the specified existing items:- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get the node - LeafNode node = mgr.getNode("testNode"); - - List<? extends Item> items = node.getItems(100); - --
--- - // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get the node - LeafNode node = mgr.getNode("testNode"); - Collection<String> ids = new ArrayList<String>(3); - ids.add("1"); - ids.add("3"); - ids.add("4"); - - List<? extends Item> items = node.getItems(ids); - --
- -Description
- -A user may want to query a server or node for a variety of pubsub related information.
- -Usage- -To retrieve information, a user will simply use either the PubSubManager -or Node classes depending on what type of information is required. - -Examples
-
-In this example we can see how to get pubsub capabilities:
-
-- -In this example we can see how to get pubsub subscriptions for all nodes:- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get the pubsub features that are supported - DiscoverInfo supportedFeatures = mgr.getSupportedFeatures(); --
-- -In this example we can see how to get all affiliations for the users bare JID on the pubsub service:- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get all the subscriptions in the pubsub service - List<Subscription> subscriptions = mgr.getSubscriptions(); --
-- -In this example we can see how to get information about the node:- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - - // Get the affiliations for the users bare JID - List<Affiliation> affiliations = mgr.getAffiliations(); --
-- -In this example we can see how to discover the node items:- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - Node node = mgr.getNode("testNode"); - - // Get the node information - DiscoverInfo nodeInfo = node.discoverInfo(); --
-- -In this example we can see how to get node subscriptions:- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - Node node = mgr.getNode("testNode"); - - // Discover the node items - DiscoverItems nodeItems = node.discoverItems(); --
--- // Create a pubsub manager using an existing XMPPConnection - PubSubManager mgr = new PubSubManager(con); - Node node = mgr.getNode("testNode"); - - // Discover the node subscriptions - List<Subscription> subscriptions = node.getSubscriptions(); --
-This extension is used to send rosters, roster groups and roster entries from one XMPP -Entity to another. It also provides an easy way to hook up custom logic when entries -are received from other XMPP clients. -
Follow these links to learn how to send and receive roster items:
- -XEP related: XEP-93 - -- -Description
- -Sometimes it is useful to send a whole roster to another user. Smack provides a -very easy way to send a complete roster to another XMPP client.
- -Usage- -Create an instance of RosterExchangeManager and use the #send(Roster, String) -message to send a roster to a given user. The first parameter is the roster to send and -the second parameter is the id of the user that will receive the roster entries.
- -Example- -In this example we can see how user1 sends his roster to user2. -
-- -// Connect to the server and log in - conn1 = new XMPPTCPConnection(host); - conn1.login(server_user1, pass1); - - // Create a new roster exchange manager on conn1 - RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1); - // Send user1's roster to user2 - rosterExchangeManager.send(conn1.getRoster(), user2); --
- -Description
- -It is also possible to send a roster group to another XMPP client. A roster group groups -a set of roster entries under a name.
- -Usage- -Create an instance of RosterExchangeManager and use the #send(RosterGroup, String) -message to send a roster group to a given user. The first parameter is the roster group to send and -the second parameter is the id of the user that will receive the roster entries.
- -Example- -In this example we can see how user1 sends his roster groups to user2. -
-- -// Connect to the server and log in - conn1 = new XMPPTCPConnection(host); - conn1.login(server_user1, pass1); - - // Create a new roster exchange manager on conn1 - RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1); - // Send user1's RosterGroups to user2 - for (Iterator it = conn1.getRoster().getGroups(); it.hasNext(); ) - rosterExchangeManager.send((RosterGroup)it.next(), user2); --
- -Description
- -Sometimes you may need to send a single roster entry to another XMPP client. Smack also lets you send -items at this granularity level.
- -Usage- -Create an instance of RosterExchangeManager and use the #send(RosterEntry, String) -message to send a roster entry to a given user. The first parameter is the roster entry to send and -the second parameter is the id of the user that will receive the roster entries.
- -Example- -In this example we can see how user1 sends a roster entry to user2. -
-- -// Connect to the server and log in - conn1 = new XMPPTCPConnection(host); - conn1.login(server_user1, pass1); - - // Create a new roster exchange manager on conn1 - RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1); - // Send a roster entry (any) to user2 - rosterExchangeManager1.send((RosterEntry)conn1.getRoster().getEntries().next(), user2); --
- -Description
- -Since roster items are sent between XMPP clients, it is necessary to listen to possible roster entries -receptions. Smack provides a mechanism that you can use to execute custom logic when roster entries are -received.
- -Usage- -
- -In this example we can see how user1 sends a roster entry to user2 and user2 adds the received -entries to his roster. -
-- - - diff --git a/documentation/extensions/rosterexchange.md b/documentation/extensions/rosterexchange.md new file mode 100644 index 000000000..bf32906a3 --- /dev/null +++ b/documentation/extensions/rosterexchange.md @@ -0,0 +1,167 @@ +Roster Item Exchange +==================== + +This extension is used to send rosters, roster groups and roster entries from +one XMPP Entity to another. It also provides an easy way to hook up custom +logic when entries are received from other XMPP clients. + +Follow these links to learn how to send and receive roster items: + + * Send a complete roster + * Send a roster's group + * Send a roster's entry + * Receive roster entries + +**XEP related:** [XEP-93](http://www.xmpp.org/extensions/xep-0093.html) + +Send a entire roster +------------------- + +**Description** + +Sometimes it is useful to send a whole roster to another user. Smack provides +a very easy way to send a complete roster to another XMPP client. + +**Usage** + +Create an instance of _**RosterExchangeManager**_ and use the **#send(Roster, +String)** message to send a roster to a given user. The first parameter is the +roster to send and the second parameter is the id of the user that will +receive the roster entries. + +**Example** + +In this example we can see how user1 sends his roster to user2. + +``` +// Connect to the server and log in +conn1 = new XMPPConnection(host); +conn1.login(server_user1, pass1); + +// Create a new roster exchange manager on conn1 +RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1); +// Send user1's roster to user2 +rosterExchangeManager.send(conn1.getRoster(), user2); +``` + +Send a roster group +------------------- + +**Description** + +It is also possible to send a roster group to another XMPP client. A roster +group groups a set of roster entries under a name. + +**Usage** + +Create an instance of _**RosterExchangeManager**_ and use the +**#send(RosterGroup, String)** message to send a roster group to a given user. +The first parameter is the roster group to send and the second parameter is +the id of the user that will receive the roster entries. + +**Example** + +In this example we can see how user1 sends his roster groups to user2. + +``` +// Connect to the server and log in +conn1 = new XMPPConnection(host); +conn1.login(server_user1, pass1); + +// Create a new roster exchange manager on conn1 +RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1); +// Send user1's RosterGroups to user2 +for (Iterator it = conn1.getRoster().getGroups(); it.hasNext(); ) +rosterExchangeManager.send((RosterGroup)it.next(), user2); +``` + +Send a roster entry +------------------- + +**Description** + +Sometimes you may need to send a single roster entry to another XMPP client. +Smack also lets you send items at this granularity level. + +**Usage** + +Create an instance of _**RosterExchangeManager**_ and use the +**#send(RosterEntry, String)** message to send a roster entry to a given user. +The first parameter is the roster entry to send and the second parameter is +the id of the user that will receive the roster entries. + +**Example** + +In this example we can see how user1 sends a roster entry to user2. + +``` +// Connect to the server and log in +conn1 = new XMPPConnection(host); +conn1.login(server_user1, pass1); + +// Create a new roster exchange manager on conn1 +RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1); +// Send a roster entry (any) to user2 +rosterExchangeManager1.send((RosterEntry)conn1.getRoster().getEntries().next(), user2); +``` + +Receive roster entries +---------------------- + +**Description** + +Since roster items are sent between XMPP clients, it is necessary to listen to +possible roster entries receptions. Smack provides a mechanism that you can +use to execute custom logic when roster entries are received. + +**Usage** + + 1. Create a class that implements the _**RosterExchangeListener**_ interface. + 2. Implement the method **entriesReceived(String, Iterator)** that will be called when new entries are received with custom logic. + 3. Add the listener to the _RosterExchangeManager_ that works on the desired _XMPPConnection_. + +**Example** + +In this example we can see how user1 sends a roster entry to user2 and user2 +adds the received entries to his roster. + +``` +// Connect to the server and log in the users +conn1 = new XMPPConnection(host); +conn1.login(server_user1, pass1); +conn2 = new XMPPConnection(host); +conn2.login(server_user2, pass2); +final Roster user2_roster = conn2.getRoster(); + +// Create a RosterExchangeManager that will help user2 to listen and accept +the entries received +RosterExchangeManager rosterExchangeManager2 = new RosterExchangeManager(conn2); +// Create a RosterExchangeListener that will iterate over the received roster entries +RosterExchangeListener rosterExchangeListener = new RosterExchangeListener() { +public void entriesReceived(String from, Iterator remoteRosterEntries) { +while (remoteRosterEntries.hasNext()) { +try { +// Get the received entry +RemoteRosterEntry remoteRosterEntry = (RemoteRosterEntry) remoteRosterEntries.next(); +// Display the remote entry on the console +System.out.println(remoteRosterEntry); +// Add the entry to the user2's roster +user2_roster.createEntry( +remoteRosterEntry.getUser(), +remoteRosterEntry.getName(), +remoteRosterEntry.getGroupArrayNames()); +} +catch (XMPPException e) { +e.printStackTrace(); +} +} +} +}; +// Add the RosterExchangeListener to the RosterExchangeManager that user2 is using +rosterExchangeManager2.addRosterListener(rosterExchangeListener); + +// Create a RosterExchangeManager that will help user1 to send his roster +RosterExchangeManager rosterExchangeManager1 = new RosterExchangeManager(conn1); +// Send user1's roster to user2 +rosterExchangeManager1.send(conn1.getRoster(), user2); +``` diff --git a/documentation/extensions/style.css b/documentation/extensions/style.css deleted file mode 100644 index 5fbf1a70f..000000000 --- a/documentation/extensions/style.css +++ /dev/null @@ -1,57 +0,0 @@ -BODY { - font-size : 100%; - background-color : #fff; -} -BODY, TD, TH { - font-family : tahoma, arial, helvetica; - font-size : 0.8em; -} -PRE, TT, CODE { - font-family : courier new, monospaced; - font-size : 1.0em; -} -A:hover { - text-decoration : none; -} -LI { - padding-bottom : 4px; -} -.header { - font-size : 1.4em; - font-weight : bold; - width : 100%; - border-bottom : 1px #ccc solid; - padding-bottom : 2px; -} -.subheader { - font-size: 1.1em; - font-weight : bold; -} -.footer { - font-size : 0.8em; - color : #999; - text-align : center; - width : 100%; - border-top : 1px #ccc solid; - padding-top : 2px; -} -.code { - border : 1px #ccc solid; - padding : 0em 1.0em 0em 1.0em; - margin : 4px 0px 4px 0px; -} -.nav, .nav A { - font-family : verdana; - font-size : 0.85em; - color : #600; - text-decoration : none; - font-weight : bold; -} -.nav { - width : 100%; - border-bottom : 1px #ccc solid; - padding : 3px 3px 5px 1px; -} -.nav A:hover { - text-decoration : underline; -} \ No newline at end of file diff --git a/documentation/extensions/time.html b/documentation/extensions/time.html deleted file mode 100644 index 800a26169..000000000 --- a/documentation/extensions/time.html +++ /dev/null @@ -1,22 +0,0 @@ - - -// Connect to the server and log in the users - conn1 = new XMPPTCPConnection(host); - conn1.login(server_user1, pass1); - conn2 = new XMPPTCPConnection(host); - conn2.login(server_user2, pass2); - final Roster user2_roster = conn2.getRoster(); - - // Create a RosterExchangeManager that will help user2 to listen and accept - the entries received - RosterExchangeManager rosterExchangeManager2 = new RosterExchangeManager(conn2); - // Create a RosterExchangeListener that will iterate over the received roster entries - RosterExchangeListener rosterExchangeListener = new RosterExchangeListener() { - public void entriesReceived(String from, Iterator remoteRosterEntries) { - while (remoteRosterEntries.hasNext()) { - try { - // Get the received entry - RemoteRosterEntry remoteRosterEntry = (RemoteRosterEntry) remoteRosterEntries.next(); - // Display the remote entry on the console - System.out.println(remoteRosterEntry); - // Add the entry to the user2's roster - user2_roster.createEntry( - remoteRosterEntry.getUser(), - remoteRosterEntry.getName(), - remoteRosterEntry.getGroupArrayNames()); - } - catch (XMPPException e) { - e.printStackTrace(); - } - } - } - }; - // Add the RosterExchangeListener to the RosterExchangeManager that user2 is using - rosterExchangeManager2.addRosterListener(rosterExchangeListener); - - // Create a RosterExchangeManager that will help user1 to send his roster - RosterExchangeManager rosterExchangeManager1 = new RosterExchangeManager(conn1); - // Send user1's roster to user2 - rosterExchangeManager1.send(conn1.getRoster(), user2); --
- -Supports a protocol that XMPP clients use to exchange their respective local -times and time zones.
- -XEP related: XEP-90 - -
- -
-
-Private Data
-XHTML Messages
-Message Events
-Data Forms
-Multi User Chat
-Roster Item Exchange
-Time Exchange
-Group Chat Invitations
-Service Discovery
-File Transfer
-PubSub
-Entity Capabilities
-Privacy
-HTTP over XMPP
-JiveProperties
-
- -Provides the ability to send and receive formatted messages using XHTML. - -
Follow these links to learn how to compose, send, receive and discover support for -XHTML messages:
-- -Description
- -The first step in order to send an XHTML message is to compose it. Smack provides a special -class that helps to build valid XHTML messages hiding any low level complexity. -For special situations, advanced users may decide not to use the helper class and generate -the XHTML by themselves. Even for these situations Smack provides a well defined entry point -in order to add the generated XHTML content to a given message.
- --Note: not all clients are able to view XHTML formatted messages. Therefore, -it's recommended that you include a normal body in that message that is either an -unformatted version of the text or a note that XHTML support is required -to view the message contents.
- -Usage- -Create an instance of XHTMLText specifying the style and language of the body. -You can add several XHTML bodies to the message but each body should be for a different language. -Once you have an XHTMLText you can start to append tags and text to it. In order to append tags there -are several messages that you can use. For each XHTML defined tag there is a message that you can send. -In order to add text you can send the message #append(String textToAppend).
- -After you have configured the XHTML text, the last step you have to do is to add the XHTML text -to the message you want to send. If you decided to create the XHTML text by yourself, you will have to -follow this last step too. In order to add the XHTML text to the message send the message -#addBody(Message message, String body) to the XHTMLManager class where message -is the message that will receive the XHTML body and body is the string to add as an XHTML body to -the message.
- -Example
-
-In this example we can see how to compose the following XHTML message:
-<body><p style='font-size:large'>Hey John, this is my new <span
- style='color:green'>green</span><em>!!!!</em></p></body>
-
-- -// Create a message to send - Message msg = chat.createMessage(); - msg.setSubject("Any subject you want"); - msg.setBody("Hey John, this is my new green!!!!"); - - // Create an XHTMLText to send with the message - XHTMLText xhtmlText = new XHTMLText(null, null); - xhtmlText.appendOpenParagraphTag("font-size:large"); - xhtmlText.append("Hey John, this is my new "); - xhtmlText.appendOpenSpanTag("color:green"); - xhtmlText.append("green"); - xhtmlText.appendCloseSpanTag(); - xhtmlText.appendOpenEmTag(); - xhtmlText.append("!!!!"); - xhtmlText.appendCloseEmTag(); - xhtmlText.appendCloseParagraphTag(); - - // Add the XHTML text to the message - XHTMLManager.addBody(msg, xhtmlText.toString()); - --
- -Description
- -After you have composed an XHTML message you will want to send it. Once you have added -the XHTML content to the message you want to send you are almost done. The last step is to send -the message as you do with any other message.
- -Usage- -An XHTML message is like any regular message, therefore to send the message you can follow -the usual steps you do in order to send a message. For example, to send a message as part -of a chat just use the message #send(Message) of Chat or you can use -the message #send(Packet) of XMPPConnection.
- -Example- -In this example we can see how to send a message with XHTML content as part of a chat. -
-- -// Create a message to send - Message msg = chat.createMessage(); - // Obtain the XHTML text to send from somewhere - String xhtmlBody = getXHTMLTextToSend(); - - // Add the XHTML text to the message - XHTMLManager.addBody(msg, xhtmlBody); - - // Send the message that contains the XHTML - chat.sendMessage(msg); --
- -Description
- -It is also possible to obtain the XHTML content from a received message. Remember -that the specification defines that a message may contain several XHTML bodies -where each body should be for a different language.
- -Usage- -To get the XHTML bodies of a given message just send the message #getBodies(Message) - to the class XHTMLManager. The answer of this message will be an - Iterator with the different XHTML bodies of the message or null if none.
- -Example- -In this example we can see how to create a PacketListener that obtains the XHTML bodies of any received message. -
-- -// Create a listener for the chat and display any XHTML content - PacketListener packetListener = new PacketListener() { - public void processPacket(Packet packet) { - Message message = (Message) packet; - // Obtain the XHTML bodies of the message - Iterator it = XHTMLManager.getBodies(message); - if (it != null) { - // Display the bodies on the console - while (it.hasNext()) { - String body = (String) it.next(); - System.out.println(body); - } - } - }; - chat.addMessageListener(packetListener); - --
- -Description
- -Before you start to send XHTML messages to a user you should discover if the user supports XHTML messages. -There are two ways to achieve the discovery, explicitly and implicitly. Explicit is when you first try -to discover if the user supports XHTML before sending any XHTML message. Implicit is when you send -XHTML messages without first discovering if the conversation partner's client supports XHTML and depenging on -the answer (normal message or XHTML message) you find out if the user supports XHTML messages or not. This -section explains how to explicitly discover for XHTML support.
- -Usage- -In order to discover if a remote user supports XHTML messages send #isServiceEnabled(XMPPConnection -connection, String userID) to the class XHTMLManager where connection is the connection -to use to perform the service discovery and userID is the user to check (A fully qualified xmpp ID, -e.g. jdoe@example.com). This message will return true if the specified user handles XHTML messages.
- -Example- -In this example we can see how to discover if a remote user supports XHTML Messages. -
-- - - diff --git a/documentation/extensions/xhtml.md b/documentation/extensions/xhtml.md new file mode 100644 index 000000000..ab5fee5e4 --- /dev/null +++ b/documentation/extensions/xhtml.md @@ -0,0 +1,202 @@ +XHTML Messages +============== + +Provides the ability to send and receive formatted messages using XHTML. + +Follow these links to learn how to compose, send, receive and discover support +for XHTML messages: + + * Compose an XHTML Message + * Send an XHTML Message + * Receive an XHTML Message + * Discover support for XHTML Messages + +**XEP related:** [XEP-71](http://www.xmpp.org/extensions/xep-0071.html) + +Compose an XHTML Message +------------------------ + +**Description** + +The first step in order to send an XHTML message is to compose it. Smack +provides a special class that helps to build valid XHTML messages hiding any +low level complexity. For special situations, advanced users may decide not to +use the helper class and generate the XHTML by themselves. Even for these +situations Smack provides a well defined entry point in order to add the +generated XHTML content to a given message. + +Note: not all clients are able to view XHTML formatted messages. Therefore, +it's recommended that you include a normal body in that message that is either +an unformatted version of the text or a note that XHTML support is required to +view the message contents. + +**Usage** + +Create an instance of _**XHTMLText**_ specifying the style and language of the +body. You can add several XHTML bodies to the message but each body should be +for a different language. Once you have an XHTMLText you can start to append +tags and text to it. In order to append tags there are several messages that +you can use. For each XHTML defined tag there is a message that you can send. +In order to add text you can send the message **#append(String +textToAppend)**. + +After you have configured the XHTML text, the last step you have to do is to +add the XHTML text to the message you want to send. If you decided to create +the XHTML text by yourself, you will have to follow this last step too. In +order to add the XHTML text to the message send the message **#addBody(Message +message, String body)** to the _**XHTMLManager**_ class where _message_ is the +message that will receive the XHTML body and _body_ is the string to add as an +XHTML body to the message.** + +**Example** + +In this example we can see how to compose the following XHTML message: + +``` + +Message msg = chat.createMessage(); - // Include a normal body in the message - msg.setBody(getTextToSend()); - // Check if the other user supports XHTML messages - if (XHTMLManager.isServiceEnabled(connection, chat.getParticipant())) { - // Obtain the XHTML text to send from somewhere - String xhtmlBody = getXHTMLTextToSend(); - - // Include an XHTML body in the message - XHTMLManager.addBody(msg, xhtmlBody); - } - - // Send the message - chat.sendMessage(msg); --
Hey John, this is my new + green + !!!! +
+ +``` + +``` +// Create a message to send +Message msg = chat.createMessage(); +msg.setSubject("Any subject you want"); +msg.setBody("Hey John, this is my new green!!!!"); + +// Create an XHTMLText to send with the message +XHTMLText xhtmlText = new XHTMLText(null, null); +xhtmlText.appendOpenParagraphTag("font-size:large"); +xhtmlText.append("Hey John, this is my new "); +xhtmlText.appendOpenSpanTag("color:green"); +xhtmlText.append("green"); +xhtmlText.appendCloseSpanTag(); +xhtmlText.appendOpenEmTag(); +xhtmlText.append("!!!!"); +xhtmlText.appendCloseEmTag(); +xhtmlText.appendCloseParagraphTag(); + +// Add the XHTML text to the message +XHTMLManager.addBody(msg, xhtmlText.toString()); +``` + +Send an XHTML Message +--------------------- + +**Description** + +After you have composed an XHTML message you will want to send it. Once you +have added the XHTML content to the message you want to send you are almost +done. The last step is to send the message as you do with any other message. + +**Usage** + +An XHTML message is like any regular message, therefore to send the message +you can follow the usual steps you do in order to send a message. For example, +to send a message as part of a chat just use the message **#send(Message)** of +_**Chat**_ or you can use the message **#send(Packet)** of +_**XMPPConnection**_. + +**Example** + +In this example we can see how to send a message with XHTML content as part of +a chat. + +``` +// Create a message to send +Message msg = chat.createMessage(); +// Obtain the XHTML text to send from somewhere +String xhtmlBody = getXHTMLTextToSend(); + +// Add the XHTML text to the message +XHTMLManager.addBody(msg, xhtmlBody); + +// Send the message that contains the XHTML +chat.sendMessage(msg); +``` + +Receive an XHTML Message +------------------------ + +**Description** + +It is also possible to obtain the XHTML content from a received message. +Remember that the specification defines that a message may contain several +XHTML bodies where each body should be for a different language. + +**Usage** + +To get the XHTML bodies of a given message just send the message +**#getBodies(Message)** to the class _**XHTMLManager**_. The answer of this +message will be an _**Iterator**_ with the different XHTML bodies of the +message or null if none. + +**Example** + +In this example we can see how to create a PacketListener that obtains the +XHTML bodies of any received message. + +``` +// Create a listener for the chat and display any XHTML content +PacketListener packetListener = new PacketListener() { +public void processPacket(Packet packet) { +Message message = (Message) packet; +// Obtain the XHTML bodies of the message +Iterator it = XHTMLManager.getBodies(message); +if (it != null) { + // Display the bodies on the console + while (it.hasNext()) { + String body = (String) it.next(); + System.out.println(body); + } +} +}; +chat.addMessageListener(packetListener); +``` + +Discover support for XHTML Messages +----------------------------------- + +**Description** + +Before you start to send XHTML messages to a user you should discover if the +user supports XHTML messages. There are two ways to achieve the discovery, +explicitly and implicitly. Explicit is when you first try to discover if the +user supports XHTML before sending any XHTML message. Implicit is when you +send XHTML messages without first discovering if the conversation partner's +client supports XHTML and depenging on the answer (normal message or XHTML +message) you find out if the user supports XHTML messages or not. This section +explains how to explicitly discover for XHTML support. + +**Usage** + +In order to discover if a remote user supports XHTML messages send +**#isServiceEnabled(XMPPConnection connection, String userID)** to the class +_**XHTMLManager**_ where connection is the connection to use to perform the +service discovery and userID is the user to check (A fully qualified xmpp ID, +e.g. jdoe@example.com). This message will return true if the specified user +handles XHTML messages. + +**Example** + +In this example we can see how to discover if a remote user supports XHTML +Messages. + +``` +Message msg = chat.createMessage(); +// Include a normal body in the message +msg.setBody(getTextToSend()); +// Check if the other user supports XHTML messages +if (XHTMLManager.isServiceEnabled(connection, chat.getParticipant())) { + // Obtain the XHTML text to send from somewhere + String xhtmlBody = getXHTMLTextToSend(); + // Include an XHTML body in the message + qHTMLManager.addBody(msg, xhtmlBody); +} + +// Send the message +chat.sendMessage(msg); +``` diff --git a/documentation/gettingstarted.html b/documentation/gettingstarted.html deleted file mode 100644 index 08da7ea85..000000000 --- a/documentation/gettingstarted.html +++ /dev/null @@ -1,152 +0,0 @@ - - --This document will introduce you to the Smack API and provide an overview of -important classes and concepts. -
- --JAR Files and Requirements -
- -Smack is meant to be easily embedded into any existing Java application. -The library ships as several JAR files to provide more flexibility over which features applications require: - -Configuration
-Smack has an initialization process that involves 2 phases. --Initialization is accomplished via a configuration file. By default, -Smack will load the one embedded in the Smack jar -at org.jivesoftware.smack/smack-config.xml. This particular -configuration contains a list of initializer classes to load. All -manager type classes that need to be initialized are contained in this -list of initializers. -
- --Establishing a Connection -
- -The classes subclassing AbstractXMPPConnection are used to -create a connection to an XMPP server. Below are code examples for -making a connection:- -
-// Create a connection to the jabber.org server. -AbstractXMPPConnection conn1 = new XMPPTCPConnection("jabber.org"); -conn1.connect(); - -// Create a connection to the jabber.org server on a specific port. -ConnectionConfiguration config = new ConnectionConfiguration("jabber.org", 5222); -AbstractXMPPConnection conn2 = new XMPPTCPConnection(config); -conn2.connect(); -
Note that maximum security will be used when connecting to the server by default (and when possible), - including use of TLS encryption. The ConnectionConfiguration class provides advanced control - over the connection created, such as the ability to disable or require encryption. See - XMPPConnection Management for full details.
- -Once you've created a connection, you should login using a username and password -with the AbstractXMPPConnection.login(String username, String password) method. -Once you've logged in, you can being chatting with other users by creating -new Chat or GroupChat objects. - -
-Working with the Roster -
-The roster lets you keep track of the availability (presence) of other users. Users -can be organized into groups such as "Friends" and "Co-workers", and then you -discover whether each user is online or offline.- -Retrieve the roster using the XMPPConnection.getRoster() method. The roster -class allows you to find all the roster entries, the groups they belong to, and the -current presence status of each entry. - -
-Reading and Writing Packets -
- -Each message to the XMPP server from a client is called a packet and is -sent as XML. The org.jivesoftware.smack.packet package contains -classes that encapsulate the three different basic packet types allowed by -XMPP (message, presence, and IQ). Classes such as Chat and GroupChat -provide higher-level constructs that manage creating and sending packets -automatically, but you can also create and send packets directly. Below -is a code example for changing your presence to let people know you're unavailable -and "out fishing":- -
-// Create a new presence. Pass in false to indicate we're unavailable. -Presence presence = new Presence(Presence.Type.unavailable); -presence.setStatus("Gone fishing"); -// Send the packet (assume we have a AbstractXMPPConnection instance called "con"). -con.sendPacket(presence); -
- -Smack provides two ways to read incoming packets: PacketListener, and -PacketCollector. Both use PacketFilter instances to determine -which packets should be processed. A packet listener is used for event style programming, -while a packet collector has a result queue of packets that you can do -polling and blocking operations on. So, a packet listener is useful when -you want to take some action whenever a packet happens to come in, while a -packet collector is useful when you want to wait for a specific packet -to arrive. Packet collectors and listeners can be created using an -Connection instance. - - -
- - - diff --git a/documentation/gettingstarted.md b/documentation/gettingstarted.md new file mode 100644 index 000000000..2e73b11b9 --- /dev/null +++ b/documentation/gettingstarted.md @@ -0,0 +1,107 @@ +Smack: Getting Started +====================== + +[Back](index.html) + +This document will introduce you to the Smack API and provide an overview of +important classes and concepts. + +JAR Files and Requirements +-------------------------- + +Smack is meant to be easily embedded into any existing Java application. The +library ships as several JAR files to provide more flexibility over which +features applications require: + + * `smack-core.jar` -- provides core XMPP functionality. All XMPP features that are part of the XMPP RFCs are included. + * `smack-extensions.jar` -- support for many of the extensions (XEPs) defined by the XMPP Standards Foundation, including multi-user chat, file transfer, user search, etc. The extensions are documented in the [extensions manual](extensions/index.html). + * `smack-experimental.jar` -- support for experimental extensions (XEPs) defined by the XMPP Standards Foundation. The API and functionality of those extensions should be considered as unstable. + * `smack-legacy.jar` -- support for legacy extensions (XEPs) defined by the XMPP Standards Foundation. + * `smack-bosh.jar` -- support for BOSH (XEP-0124). This code should be considered as beta. + * `smack-jingle.jar` -- support for Jingle. This code is old and currenlty unmaintained. + * `smack-resolver-dnsjava.jar` -- support for resolving DNS SRV records with the help of dnsjava. Ideal for platforms that do not support the javax.naming API. + * `smack-resolver-javax.jar` -- support for resolving DNS SRV records with the javax namespace API. + * `smack-debug.jar` -- an enhanced GUI debugger for protocol traffic. It will automatically be used when found in the classpath and when [debugging](debugging.html) is enabled. + +Configuration +------------- + +Smack has an initialization process that involves 2 phases. + + * Initializing system properties - Initializing all the system properties accessible through the class **SmackConfiguration**. These properties are retrieve by the _getXXX_ methods on that class. + * Initializing startup classes - Initializing any classes meant to be active at startup by instantiating the class, and then calling the _initialize_ method on that class if it extends **SmackInitializer**. If it does not extend this interface, then initialization will have to take place in a static block of code which is automatically executed when the class is loaded. + +Initialization is accomplished via a configuration file. By default, Smack +will load the one embedded in the Smack jar at _org.jivesoftware.smack/smack- +config.xml_. This particular configuration contains a list of initializer +classes to load. All manager type classes that need to be initialized are +contained in this list of initializers. + +Establishing a Connection +------------------------- + +The `XMPPTCPConnection` class is used to create a connection to an XMPP +server. Below are code examples for making a connection: + +``` +// Create a connection to the jabber.org server._ +XMPPConnection conn1 = **new** XMPPTCPConnection("jabber.org"); +conn1.connect(); + +// Create a connection to the jabber.org server on a specific port._ +ConnectionConfiguration config = new ConnectionConfiguration("jabber.org", 5222); +XMPPConnection conn2 = **new** XMPPTCPConnection(config); +conn2.connect(); +``` + +Note that maximum security will be used when connecting to the server by +default (and when possible), including use of TLS encryption. The +ConnectionConfiguration class provides advanced control over the connection +created, such as the ability to disable or require encryption. See +[XMPPConnection Management](connections.html) for full details. + +Once you've created a connection, you should login using a username and +password with the `XMPPConnection.login(String username, String password)` +method. Once you've logged in, you can being chatting with other users by +creating new `Chat` or `GroupChat` objects. + +Working with the Roster +---------------------- + +The roster lets you keep track of the availability (presence) of other users. +Users can be organized into groups such as "Friends" and "Co-workers", and +then you discover whether each user is online or offline. + +Retrieve the roster using the `XMPPConnection.getRoster()` method. The roster +class allows you to find all the roster entries, the groups they belong to, +and the current presence status of each entry. + +Reading and Writing Packets + +Each message to the XMPP server from a client is called a packet and is sent +as XML. The `org.jivesoftware.smack.packet` package contains classes that +encapsulate the three different basic packet types allowed by XMPP (message, +presence, and IQ). Classes such as `Chat` and `GroupChat` provide higher-level +constructs that manage creating and sending packets automatically, but you can +also create and send packets directly. Below is a code example for changing +your presence to let people know you're unavailable and "out fishing": + +``` +// Create a new presence. Pass in false to indicate we're unavailable._ +Presence presence = new Presence(Presence.Type.unavailable); +presence.setStatus("Gone fishing"); +// Send the packet (assume we have a XMPPConnection instance called "con"). +con.sendPacket(presence); +``` + +Smack provides two ways to read incoming packets: `PacketListener`, and +`PacketCollector`. Both use `PacketFilter` instances to determine which +packets should be processed. A packet listener is used for event style +programming, while a packet collector has a result queue of packets that you +can do polling and blocking operations on. So, a packet listener is useful +when you want to take some action whenever a packet happens to come in, while +a packet collector is useful when you want to wait for a specific packet to +arrive. Packet collectors and listeners can be created using an Connection +instance. + +Copyright (C) Jive Software 2002-2008 diff --git a/documentation/index.html b/documentation/index.html deleted file mode 100644 index fd5b77951..000000000 --- a/documentation/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - --Contents: -
- --
-
- Sending messages back and forth is at the core of instant messaging. Although individual - messages - can be sent and received as packets, it's generally easier to treat the string of messages - as a chat using the org.jivesoftware.smack.Chat class. -
- -- Chat -
- -A chat creates a new thread of messages (using a thread ID) between two users. The -following code snippet demonstrates how to create a new Chat with a user and then send -them a text message:- -
// Assume we've created a XMPPConnection name "connection". -ChatManager chatmanager = connection.getChatManager(); -Chat newChat = chatmanager.createChat("jsmith@jivesoftware.com", new MessageListener() { - public void processMessage(Chat chat, Message message) { - System.out.println("Received message: " + message); - } -}); - -try { - newChat.sendMessage("Howdy!"); -} -catch (XMPPException e) { - System.out.println("Error Delivering block"); -} --
- - The Chat.sendMessage(String) method is a convenience method that creates a Message - object, sets the body using the String parameter, then sends the message. In the case - that you wish to set additional values on a Message before sending it, use the - Chat.createMessage() and Chat.sendMessage(Message) methods, as in the - following code snippet: - -
- -
-Message newMessage = new Message(); -newMessage.setBody("Howdy!"); -message.setProperty("favoriteColor", "red"); -newChat.sendMessage(newMessage); --
- - You'll also notice in the example above that we specified a MessageListener when creating a - chat. - The listener is notified any time a new message arrives from the other user in the chat. - The following code snippet uses the listener as a parrot-bot -- it echoes back everything the - other user types. - -
- -
- // Assume a MessageListener we've setup with a chat. - - public void processMessage(Chat chat, Message message) { - // Send back the same text the other user sent us. - chat.sendMessage(message.getBody()); - } --
- Incoming Chat -
- -When chats are prompted by another user, the setup is slightly different since -you are receiving a chat message first. Instead of explicitly creating a chat to send -messages, you need to register to handle newly created Chat instances when the ChatManager -creates them. - - -The ChatManager will already find a matching chat (by thread id) and if none exists, then it -will create a new one that does match. To get this new chat, you have to register to be -notified when it happens. You can register a message listener to receive all future messages as -part of this handler.- -
// Assume we've created a XMPPConnection name "connection". -ChatManager chatmanager = connection.getChatManager().addChatListener( - new ChatManagerListener() { - @Override - public void chatCreated(Chat chat, boolean createdLocally) - { - if (!createdLocally) - chat.addMessageListener(new MyNewMessageListener());; - } - }); --
-
-
-
-
- -Smack is a library for communicating with XMPP servers to perform real-time communications, including -instant messaging and group chat.
- -
-Smack Key Advantages -
- --XMPPConnection connection = new XMPPTCPConnection("jabber.org"); -connection.connect(); -connection.login("mtucker", "password"); -Chat chat = connection.getChatManager().createChat("jsmith@jivesoftware.com", new MessageListener() { - - public void processMessage(Chat chat, Message message) { - System.out.println("Received message: " + message); - } -}); -chat.sendMessage("Howdy!"); -
-About XMPP -
- -XMPP (eXtensible Messaging and Presence Protocol) is an open protocol standardized by the IETF -and supported and extended by the XMPP Standards Foundation -((http://www.xmpp.org). - --How To Use This Documentation -
- -This documentation assumes that you're already familiar with the main features of XMPP -instant messaging. It's also highly recommended that you open the Javadoc API guide and -use that as a reference while reading through this documentation. - -- -Smack provides a flexible framework for processing incoming packets using two constructs: -
- -The org.jivesoftware.smack.filter.PacketFilter interface determines which -specific packets will be delivered to a PacketCollector or PacketListener. -Many pre-defined filters can be found in the org.jivesoftware.smack.filter package. - -
-The following code snippet demonstrates registering both a packet collector and a packet -listener:
- -
-// Create a packet filter to listen for new messages from a particular -// user. We use an AndFilter to combine two other filters. -PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class), - new FromContainsFilter("mary@jivesoftware.com")); -// Assume we've created a XMPPConnection name "connection". - -// First, register a packet collector using the filter we created. -PacketCollector myCollector = connection.createPacketCollector(filter); -// Normally, you'd do something with the collector, like wait for new packets. - -// Next, create a packet listener. We use an anonymous inner class for brevity. -PacketListener myListener = new PacketListener() { - public void processPacket(Packet packet) { - // Do something with the incoming packet here. - } - }; -// Register the listener. -connection.addPacketListener(myListener, filter); -
- -
-Standard Packet Filters -
- -A rich set of packet filters are included with Smack, or you can create your own filters by coding -to the PacketFilter interface. The default set of filters includes: --
Introduction
- -The Smack provider architecture is a system for plugging in -custom XML parsing of packet extensions and IQ packets. The -standard Smack Extensions -are built using the provider architecture. There are two types of -providers:-Whenever a packet extension is found in a packet, parsing will -be passed to the correct provider. Each provider can either implement the -PacketExtensionProvider interface or be a standard Java Bean. In the -former case, each extension provider is responsible for parsing the raw -XML stream, via the XML Pull Parser, to contruct an object. In the latter case, bean introspection -is used to try to automatically set the properties of the class using -the values in the packet extension sub-element. -
-When no extension provider is registered for an element name and -namespace combination, Smack will store all top-level elements of the -sub-packet in the DefaultPacketExtension object and then attach it to the packet. - -
-Management of these providers is accomplished via the ProviderManager -class. There are multiple ways to add providers to the manager.
- ProviderManager.getInstance().addIQProvider("element", "namespace", new MyIQProvider()); - ProviderManager.getInstance().addExtensionProvider("element", "namespace", new MyExtProvider()); --
- ProviderManager.getInstance().addLoader(new ProviderFileLoader(FileUtils.getStreamForUrl("classpath:com/myco/provider/myco_custom.providers", null))); --
- -Dsmack.provider.file=classpath:com/myco/provider/myco_custom.providers - or - -Dsmack.provider.file=file:///c:/myco/provider/myco_custom.providers --
IQ Providers
- -The IQ provider class can either implement the IQProvider -interface, or extend the IQ class. In the former case, each IQProvider is -responsible for parsing the raw XML stream to create an IQ instance. In -the latter case, bean introspection is used to try to automatically set -properties of the IQ instance using the values found in the IQ packet XML. -For example, an XMPP time packet resembles the following: - --Introspection -
-Time Packet -
- <iq type='result' to='joe@example.com' from='mary@example.com' id='time_1'> - <query xmlns='jabber:iq:time'> - <utc>20020910T17:58:35</utc> - <tz>MDT</tz> - <display>Tue Sep 10 12:58:35 2002</display> - </query> - </iq> -- -
-Time IQ Class -
- class Time extends IQ { - private Date utc; - private TimeZone timeZone; - private String display; - - @Override - public String getChildElementXML() { - return null; - } - - public void setUtc(String utcString) { - try { - utc = StringUtils.parseDate(utcString); - } catch (ParseException e) { - } - } - - public void setTimeZone(String zone) { - timeZone = TimeZone.getTimeZone(zone); - } - - public void setDisplay(String timeDisplay) { - display = timeDisplay; - } - } -- -The introspection service will automatically try to convert the String -value from the XML into a boolean, int, long, float, double, or Class depending on the -type the IQ instance expects. - -
-IQProvider Implementation -
-Disco Items Packet -
- <iq type='result' from='shakespeare.lit' to='romeo@montague.net/orchard' id='items1'> - <query xmlns='http://jabber.org/protocol/disco#items'> - <item jid='people.shakespeare.lit' name='Directory of Characters'/> - <item jid='plays.shakespeare.lit' name='Play-Specific Chatrooms'/> - <item jid='mim.shakespeare.lit' name='Gateway to Marlowe IM'/> - <item jid='words.shakespeare.lit' name='Shakespearean Lexicon'/> - <item jid='globe.shakespeare.lit' name='Calendar of Performances'/> - <item jid='headlines.shakespeare.lit' name='Latest Shakespearean News'/> - <item jid='catalog.shakespeare.lit' name='Buy Shakespeare Stuff!'/> - <item jid='en2fr.shakespeare.lit' name='French Translation Service'/> - </query> - </iq> -- -
-Disco Items IQProvider -
- public class DiscoverItemsProvider implements IQProvider { - - public IQ parseIQ(XmlPullParser parser) throws Exception { - DiscoverItems discoverItems = new DiscoverItems(); - boolean done = false; - DiscoverItems.Item item; - String jid = ""; - String name = ""; - String action = ""; - String node = ""; - discoverItems.setNode(parser.getAttributeValue("", "node")); - while (!done) { - int eventType = parser.next(); - - if (eventType == XmlPullParser.START_TAG && "item".equals(parser.getName())) { - // Initialize the variables from the parsed XML - jid = parser.getAttributeValue("", "jid"); - name = parser.getAttributeValue("", "name"); - node = parser.getAttributeValue("", "node"); - action = parser.getAttributeValue("", "action"); - } - else if (eventType == XmlPullParser.END_TAG && "item".equals(parser.getName())) { - // Create a new Item and add it to DiscoverItems. - item = new DiscoverItems.Item(jid); - item.setName(name); - item.setNode(node); - item.setAction(action); - discoverItems.addItem(item); - } - else if (eventType == XmlPullParser.END_TAG && "query".equals(parser.getName())) { - done = true; - } - } - return discoverItems; - } - } -- -
Extension Providers
- -Packet extension providers are responsible for parsing packet extensions, which are -child elements in a custom namespace of IQ, message and presence packets. --Pubsub Subscription Packet - -
- <iq type='result' from='pubsub.shakespeare.lit' to='francisco@denmark.lit/barracks' id='sub1'> - <pubsub xmlns='http://jabber.org/protocol/pubsub'> - <subscription node='princely_musings' jid='francisco@denmark.lit' subscription='unconfigured'> - <subscribe-options> - <required/> - </subscribe-options> - </subscription> - </pubsub> - </iq> -- -
-Subscription PacketExtensionProvider Implementation - -
- public class SubscriptionProvider implements PacketExtensionProvider { - public PacketExtension parseExtension(XmlPullParser parser) throws Exception { - String jid = parser.getAttributeValue(null, "jid"); - String nodeId = parser.getAttributeValue(null, "node"); - String subId = parser.getAttributeValue(null, "subid"); - String state = parser.getAttributeValue(null, "subscription"); - boolean isRequired = false; - - int tag = parser.next(); - - if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("subscribe-options")) { - tag = parser.next(); - - if ((tag == XmlPullParser.START_TAG) && parser.getName().equals("required")) - isRequired = true; - - while (parser.next() != XmlPullParser.END_TAG && parser.getName() != "subscribe-options"); - } - while (parser.getEventType() != XmlPullParser.END_TAG) parser.next(); - return new Subscription(jid, nodeId, subId, (state == null ? null : Subscription.State.valueOf(state)), isRequired); - } - } -- -
Provider file format
- -This is the format for a provider file which can be parsed by the ProviderFileLoader. -- <?xml version="1.0"?> - <smackProviders> - <iqProvider> - <elementName>query</elementName> - <namespace>jabber:iq:time</namespace> - <className>org.jivesoftware.smack.packet.Time</className> - </iqProvider> - - <iqProvider> - <elementName>query</elementName> - <namespace>http://jabber.org/protocol/disco#items</namespace> - <className>org.jivesoftware.smackx.provider.DiscoverItemsProvider</className> - </iqProvider> - - <extensionProvider> - <elementName>subscription</elementName> - <namespace>http://jabber.org/protocol/pubsub</namespace> - <className>org.jivesoftware.smackx.pubsub.provider.SubscriptionProvider</className> - </extensionProvider> - </smackProviders>- -Each provider is associated with an element name and a namespace. If multiple provider entries attempt to register to -handle the same namespace, the last entry added to the ProviderManager will overwrite any other that was loaded -before it. -
-
-
-
-
-
-
- -The roster lets you keep track of the availability ("presence") of other users. -A roster also allows you to organize users into groups such as "Friends" and -"Co-workers". Other IM systems refer to the roster as the buddy list, contact list, -etc.
- -A Roster instance is obtained using the XMPPConnection.getRoster() -method. - -
Roster Entries
- --Every user in a roster is represented by a RosterEntry, which consists of:
-Roster roster = connection.getRoster(); -Collection<RosterEntry> entries = roster.getEntries(); -for (RosterEntry entry : entries) { - System.out.println(entry); -} -- -Methods also exist to get individual entries, the list of unfiled entries, or to get one or -all roster groups. - -
Presence
- - - -Every entry in the roster has presence associated with it. The -Roster.getPresence(String user) method will return a Presence object with -the user's presence or null if the user is not online or you are not -subscribed to the user's presence. Note: typically, presence -subscription is always tied to the user being on the roster, but this is not -true in all cases.
- -A user either has a presence of online or offline. When a user is online, their -presence may contain extended information such as what they are currently doing, whether -they wish to be disturbed, etc. See the Presence class for further details.
- -Listening for Roster and Presence Changes
- -The typical use of the roster class is to display a tree view of groups and entries -along with the current presence value of each entry. As an example, see the image showing -a Roster in the Exodus XMPP client to the right.
- -The presence information will likely
-change often, and it's also possible for the roster entries to change or be deleted.
-To listen for changing roster and presence data, a RosterListener should be used.
-To be informed about all changes to the roster the RosterListener should be registered
-before logging into the XMPP server.
-The following code snippet registers a RosterListener with the Roster that prints
-any presence changes in the roster to standard out. A normal client would use
-similar code to update the roster UI with the changing information.
-
-
-
-
-Roster roster = con.getRoster(); -roster.addRosterListener(new RosterListener() { - // Ignored events public void entriesAdded(Collection<String> addresses) {} - public void entriesDeleted(Collection<String> addresses) {} - public void entriesUpdated(Collection<String> addresses) {} - public void presenceChanged(Presence presence) { - System.out.println("Presence changed: " + presence.getFrom() + " " + presence); - } -}); -- -
Adding Entries to the Roster
- -Rosters and presence use a permissions-based model where users must give permission before -they are added to someone else's roster. This protects a user's privacy by -making sure that only approved users are able to view their presence information. -Therefore, when you add a new roster entry it will be in a pending state until -the other user accepts your request.
- -If another user requests a presence subscription so they can add you to their roster, -you must accept or reject that request. Smack handles presence subscription requests -in one of three ways: