1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-26 00:02:06 +01:00

Merge branch '4.0'

Conflicts:
	build.gradle
	documentation/connections.html
	documentation/debugging.html
	documentation/extensions/filetransfer.html
	documentation/extensions/rosterexchange.html
	documentation/gettingstarted.html
	documentation/index.html
	documentation/legacy/messageevents.html
	smack-extensions/src/main/java/org/jivesoftware/smackx/address/MultipleRecipientManager.java
This commit is contained in:
Florian Schmaus 2014-08-16 00:29:59 +02:00
commit 397eb88468
57 changed files with 3571 additions and 3976 deletions

View file

@ -1,5 +1,16 @@
import org.gradle.plugins.signing.Sign 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 { allprojects {
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'eclipse' apply plugin: 'eclipse'
@ -9,7 +20,7 @@ allprojects {
isSnapshot = true isSnapshot = true
gitCommit = getGitCommit() gitCommit = getGitCommit()
javadocAllDir = new File(buildDir, 'javadoc') javadocAllDir = new File(buildDir, 'javadoc')
documentationDir = new File(projectDir, 'documentation') documentationDir = new File(buildDir, 'documentation')
releasedocsDir = new File(buildDir, 'releasedocs') releasedocsDir = new File(buildDir, 'releasedocs')
rootConfigDir = new File(rootDir, 'config') rootConfigDir = new File(rootDir, 'config')
sonatypeCredentialsAvailable = project.hasProperty('sonatypeUsername') && project.hasProperty('sonatypePassword') 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()]) 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 classifier builtDate
into ('javadoc') { into ('javadoc') {
from(javadocAllDir) from(javadocAllDir)

View file

@ -1,94 +0,0 @@
<html>
<head>
<title>Smack: XMPPConnection Management - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<div class="header">
Smack: XMPPConnection Management
</div>
<div class="nav">
&laquo; <a href="index.html">Table of Contents</a>
</div>
<p class="subheader">
Creating a Connection
</p>
<p>
The <tt>org.jivesoftware.smack.XMPPConnection</tt> class manages your connection to an XMPP
server. A default implementation is the <tt>org.jivesoftware.smack.XMPPTCPConnection</tt>
class. Two constructors are mainly used. The first, <tt>XMPPTCPConnection(String)</tt> takes
the server name you'd like to connect to as an argument. All default connection settings will
be used:
<ul>
<li>A DNS SRV lookup will be performed to find the exact address and port (typically 5222)
that the server resides at.</li>
<li>The maximum security possible will be negotiated with the server, including TLS encryption,
but the connection will fall back to lower security settings if necessary.
</li>
<li>The XMPP resource name "Smack" will be used for the connection.</li>
</ul>
Alternatively, you can use the <tt>XMPPTCPConnection(ConnectionConfiguration)</tt> constructor to
specify advanced connection settings. Some of these settings include:
<ul>
<li>Manually specify the server address and port of the server rather than using a DNS SRV
lookup.</li>
<li>Enable connection compression.</li>
<li>Customize security settings, such as flagging the connection to require TLS encryption
in order to connect.</li>
<li>Specify a custom connection resource name such as "Work" or "Home". Every connection
by a user to a server must have a unique resource name. For the user "jsmith@example.com", the
full address with resource might be "jsmith@example.com/Smack". With unique resource names, a user
can be logged into the server from multiple locations at once, or using multiple devices. The
presence priority value used with each resource will determine which particular connection
receives messages to the bare address ("jsmith@example.com" in our example).</li>
</ul>
</p>
<p class="subheader">
Connect and Disconnect
</p>
<div class="code">
<pre>
<font color="gray"><i>// Create the configuration for this new connection</i></font>
ConnectionConfiguration config = new ConnectionConfiguration(<font color="green">"jabber.org"</font>, 5222);
config.setCompressionEnabled(true);
AbstractXMPPConnection connection = new XMPPTCPConnection(config);
<font color="gray"><i>// Connect to the server</i></font>
connection.connect();
<font color="gray"><i>// Log into the server</i></font>
connection.login(<font color="green">"username"</font>, <font color="green">"password"</font>, <font color="green">"SomeResource"</font>);
....
<font color="gray"><i>// Disconnect from the server</i></font>
connection.disconnect();
</pre></div>
<p>
By default Smack will try to reconnect the connection in case it was abruptly disconnected. Use
<i>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.</i>
<br>
In case you want to force a reconnection while the reconnetion manager is waiting for the next
reconnection, you can just use <i>AbstractXMPPConnection#connect()</i> and a new attempt will be made.
If the manual attempt also failed then the reconnection manager will still continue the
reconnection job.
</p>
<br clear="all"/><br><br>
<div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

View file

@ -0,0 +1,57 @@
Smack: XMPPConnection Management
================================
[Back](index.html)
Creating a Connection
---------------------
The `org.jivesoftware.smack.XMPPConnection` class manages your connection to
an XMPP server. The 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:
* A DNS SRV lookup will be performed to find the exact address and port (typically 5222) that the server resides at.
* The maximum security possible will be negotiated with the server, including TLS encryption, but the connection will fall back to lower security settings if necessary.
* The XMPP resource name "Smack" will be used for the connection.
Alternatively, you can use the `XMPPTCPConnection(ConnectionConfiguration)`
constructor to specify advanced connection settings. Some of these settings
include:
* Manually specify the server address and port of the server rather than using a DNS SRV lookup.
* Enable connection compression.
* Customize security settings, such as flagging the connection to require TLS encryption in order to connect.
* Specify a custom connection resource name such as "Work" or "Home". Every connection by a user to a server must have a unique resource name. For the user "jsmith@example.com", the full address with resource might be "jsmith@example.com/Smack". With unique resource names, a user can be logged into the server from multiple locations at once, or using multiple devices. The presence priority value used with each resource will determine which particular connection receives messages to the bare address ("jsmith@example.com" in our example).
Connect and Disconnect
----------------------
```
// Create the configuration for this new connection_
ConnectionConfiguration config = new ConnectionConfiguration("jabber.org", 5222);
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.
Copyright (C) Jive Software 2002-2008

View file

@ -1,116 +0,0 @@
<html>
<head>
<title>Smack: Debugging - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">
Debugging with Smack
</div>
<div class="nav">
&laquo; <a href="index.html">Table of Contents</a>
</div>
<p>
Smack includes two built-in debugging consoles that will let you track all XML traffic between
the client and server. A <a href="#lite">lite debugger</a> which is part of the <tt>smack-core.jar</tt>
and an <a href="#enhanced">enhanced debugger</a> contained in <tt>smack-debug.jar</tt>.
</p>
<p>
Debugging mode can be enabled in two different ways:
</p>
<ol>
<li>Add the following line of code <b>before</b> creating new connections:<p>
<tt>SmackConfiguration.DEBUG_ENABLED = true;</tt><p>
<li>Set the Java system property <tt>smack.debugEnabled</tt> to true. The
system property can be set on the command line such as:<p>
<tt>java -Dsmack.debugEnabled=true SomeApp </tt>
</ol>
<p>
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:
</p>
<p>
<tt>SmackConfiguration.DEBUG_ENABLED = false;</tt>
</p>
<p>
Smack uses the following logic to decide the debugger console to use:
</p>
<ol>
<li>It will first try use the debugger class specified in the Java system property
<tt>smack.debuggerClass</tt>. If you need to develop your own debugger,
implement the <tt>SmackDebugger</tt> interface and then set the system property
on the command line such as:<p>
<tt>java -Dsmack.debuggerClass=my.company.com.MyDebugger SomeApp </tt><p>
<li>If step 1 fails then Smack will try to use the enhanced debugger. The
file <tt>smackx-debug.jar</tt> contains the enhanced debugger. Therefore you will need
to place the jar file in the classpath. For situations where space is an issue you
may want to only deploy <tt>smack-core.jar</tt> in which case the enhanced debugger won't be
available.<p>
<li>The last option if the previous two steps fail is to use the lite debugger. The lite
debugger is a very good option for situations where you need to have low memory footprint.
</ol>
<p class="subheader">
<a name="enhanced">Enhanced Debugger</a>
</p>
<img src="images/enhanceddebugger.png" width="479" height="400" alt="Full Debug Window" border="0" align="right">
When debugging mode is enabled, a debug window will appear containing tabs for each new created connection.
The window will contain the following information:
<ul>
<li>XMPPConnection tabs -- each tab shows debugging information related to the connection.
<li>Smack info tab -- shows information about Smack (e.g. Smack version, installed components, etc.).
</ul>
The connection tab will contain the following information:
<ul>
<li>All Packets -- shows sent and received packets information parsed by Smack.
<li>Raw Sent Packets -- raw XML traffic generated by Smack and sent to the server.
<li>Raw Received Packets -- raw XML traffic sent by the server to the client.
<li>Ad-hoc message -- allows to send ad-hoc packets of any type.
<li>Information -- shows connection state and statistics.
</ul>
<br clear="right">
<p class="subheader">
<a name="lite">Lite Debugger</a>
</p>
<img src="images/debugwindow.gif" width="359" height="399" alt="Lite Debug Window" border="0" align="right">
When debugging mode is enabled, a debug window will appear when each new connection is created.
The window will contain the following information:
<ul>
<li>Client Traffic (red text) -- raw XML traffic generated by Smack and sent to the server.
<li>Server Traffic (blue text) -- raw XML traffic sent by the server to the client.
<li>Interpreted Packets (green text) -- shows XML packets from the server as parsed by Smack.
</ul>
Right click on any of the panes to bring up a menu with the choices to copy of the contents
to the system clipboard or to clear the contents of the pane.
<br clear="all" /><br><br>
<div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

View file

@ -0,0 +1,62 @@
Debugging with Smack
====================
[Back](index.html)
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:
1. Add the following line of code **before** creating new connections:
`XMPPConnection.DEBUG_ENABLED = true;`
2. Set the Java system property `smack.debugEnabled` to true. The system property can be set on the command line such as:
`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:
`XMPPConnection.DEBUG_ENABLED = false;`
Smack uses the following logic to decide the debugger console to use:
1. It will first try use the debugger class specified in the Java system property `smack.debuggerClass`. If you need to develop your own debugger, implement the `SmackDebugger` interface and then set the system property on the command line such as:
`java -Dsmack.debuggerClass=my.company.com.MyDebugger SomeApp `
2. If step 1 fails then Smack will try to use the enhanced debugger. The file `smackx-debug.jar` contains the enhanced debugger. Therefore you will need to place the jar file in the classpath. For situations where space is an issue you may want to only deploy `smack-core.jar` in which case the enhanced debugger won't be available.
3. The last option if the previous two steps fail is to use the lite debugger. The lite debugger is a very good option for situations where you need to have low memory footprint.
Enhanced Debugger
-----------------
![Full Debug Window](images/enhanceddebugger.png) When debugging mode is
enabled, a debug window will appear containing tabs for each new created
connection. The window will contain the following information:
* XMPPConnection tabs -- each tab shows debugging information related to the connection.
* Smack info tab -- shows information about Smack (e.g. Smack version, installed components, etc.). The connection tab will contain the following information:
* All Packets -- shows sent and received packets information parsed by Smack.
* Raw Sent Packets -- raw XML traffic generated by Smack and sent to the server.
* Raw Received Packets -- raw XML traffic sent by the server to the client.
* Ad-hoc message -- allows to send ad-hoc packets of any type.
* Information -- shows connection state and statistics.
Lite Debugger
-------------
![Lite Debug Window](images/debugwindow.gif) When debugging mode is enabled, a
debug window will appear when each new connection is created. The window will
contain the following information:
* Client Traffic (red text) -- raw XML traffic generated by Smack and sent to the server.
* Server Traffic (blue text) -- raw XML traffic sent by the server to the client.
* Interpreted Packets (green text) -- shows XML packets from the server as parsed by Smack. Right click on any of the panes to bring up a menu with the choices to copy of the contents to the system clipboard or to clear the contents of the pane.
Copyright (C) Jive Software 2002-2008

View file

@ -1,63 +0,0 @@
<html>
<head>
<title>Entity Capabilities</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">Entity Capabilities</div><p>
This section details the usage of Smacks implementation of Entity Capabilities.
</p>
<b>XEP related:</b> <a href="http://xmpp.org/extensions/xep-0115.html">XEP-0115: Entity Capabilities</a>
<hr>
<b>Description</b><p>
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 (<a href="http://xmpp.org/extensions/xep-0030.html">XEP-0030</a>).
</p>
<b>Usage</b><p>
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 <i><b>EntityCapsManager</b></i>.<br>
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.
</p>
<b>Examples</b><p>
Enable Entity Capabilities
<br>
<blockquote>
<pre>
<font color="#3f7f5f">// Get an instance of entity caps manager for the specified connection</font>
EntityCapsManager mgr = EntityCapsManager.getInstanceFor(connection);
<font color="#3f7f5f">// Enable entity capabilities</font>
mgr.enableEntityCaps();
</pre>
</blockquote>
Configure a persistent cache for Entity Capabilities
<br>
<blockquote>
<pre>
<font color="#3f7f5f">// Get an instance of entity caps manager for the specified connection</font>
EntityCapsManager mgr = EntityCapsManager.getInstanceFor(connection);
<font color="#3f7f5f">// Create an cache, see smackx.entitycaps.cache for pre-defined cache implementations</font>
EntityCapsPersistentCache cache = new SimpleDirectoryPersistentCache(new File("/foo/cachedir"));
<font color="#3f7f5f">// Set the cache</font>
mgr.setPersistentCache(cache);
</pre>
</blockquote>
</p>
<hr>
</body>
</html>

View file

@ -0,0 +1,47 @@
Entity Capabilities
===================
This section details the usage of Smacks implementation of Entity
Capabilities.
**XEP related:** [XEP-0115: Entity Capabilities](http://xmpp.org/extensions/xep-0115.html)
**Description**
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](http://xmpp.org/extensions/xep-0030.html)).
**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.
**Examples**
Enable Entity Capabilities
```
// Get an instance of entity caps manager for the specified connection
EntityCapsManager mgr = EntityCapsManager.getInstanceFor(connection);
// Enable entity capabilities
mgr.enableEntityCaps();
```
Configure a persistent cache for Entity Capabilities
```
// 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);
```

View file

@ -1,137 +0,0 @@
<html>
<head>
<title>Data Forms</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">Data Forms</div><p>
Allows to exchange structured data between users and applications for common
tasks such as registration and searching using Forms.
<ul>
<li><a href="#gather">Create a Form to fill out</a></li>
<li><a href="#fillout">Answer a Form</a></li>
</ul>
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0004.html">XEP-4</a>
<hr>
<div class="subheader"><a name="gather">Create a Form to fill out</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
In order to create a Form to fill out use the <i><b>Form</b></i>'s constructor passing the constant
<b>Form.TYPE_FORM</b> 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 <i><b>FormField</b></i> use the <i><b>FormField</b></i>'s
constructor specifying the variable name of the field as the parameter. Then use <b>setType(String type)</b>
to set the field's type (e.g. FormField.TYPE_HIDDEN, FormField.TYPE_TEXT_SINGLE). Once we have the
<i><b>Form</b></i> instance and the <i><b>FormFields</b></i> the last step is to send <b>addField(FormField field)</b>
for each field that we want to add to the form.</p><p>
Once the form to fill out is finished we will want to send it in a message. Send <b>getDataFormToSend()</b> to
the form and add the answer as an extension to the message to send.</p>
<b>Examples</b><p>
In this example we can see how to create and send a form to fill out: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Create a new form to gather data</font>
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");
<font color="#3f7f5f">// Add a hidden variable to the form</font>
FormField field = new FormField("hidden_var");
field.setType(FormField.TYPE_HIDDEN);
field.addValue("Some value for the hidden variable");
formToSend.addField(field);
<font color="#3f7f5f">// Add a fixed variable to the form</font>
field = new FormField();
field.addValue("Section 1: Case description");
formToSend.addField(field);
<font color="#3f7f5f">// Add a text-single variable to the form</font>
field = new FormField("name");
field.setLabel("Enter a name for the case");
field.setType(FormField.TYPE_TEXT_SINGLE);
formToSend.addField(field);
<font color="#3f7f5f">// Add a text-multi variable to the form</font>
field = new FormField("description");
field.setLabel("Enter a description");
field.setType(FormField.TYPE_TEXT_MULTI);
formToSend.addField(field);
<font color="#3f7f5f">// Create a chat with "user2@host.com"</font>
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");
<font color="#3f7f5f">// Add the form to fill out to the message to send</font>
msg.addExtension(formToSend.getDataFormToSend());
<font color="#3f7f5f">// Send the message with the form to fill out</font>
chat.sendMessage(msg);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="fillout">Answer a Form</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
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.</p><p>
In order to create a new <i><b>Form</b></i> to complete based on the original <i><b>Form</b></i> just send
<b>createAnswerForm()</b> to the original <i><b>Form</b></i>. Once you have a valid form that could be actually
completed all you have to do is send <b>setAnswer(String variable, String value)</b> to the form where variable
is the variable of the <i><b>FormField</b></i> 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 <b>setAnswer(String variable, List values)</b>
where values is a List of Strings.</p><p>
Once the form has been completed we will want to send it back in a message. Send <b>getDataFormToSend()</b> to
the form and add the answer as an extension to the message to send back.</p>
<b>Examples</b><p>
In this example we can see how to retrieve a form to fill out, complete the form and send it back: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Get the message with the form to fill out</font>
Message msg2 = chat2.nextMessage();
<font color="#3f7f5f">// Retrieve the form to fill out from the message</font>
Form formToRespond = Form.getFormFrom(msg2);
<font color="#3f7f5f">// Obtain the form to send with the replies</font>
Form completedForm = formToRespond.createAnswerForm();
<font color="#3f7f5f">// Add the answers to the form</font>
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");
<font color="#3f7f5f">// Add the completed form to the message to send back</font>
msg2.addExtension(completedForm.getDataFormToSend());
<font color="#3f7f5f">// Send the message with the completed form</font>
chat2.sendMessage(msg2);
</pre>
</blockquote>
</body>
</html>

View file

@ -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);
```

View file

@ -1,236 +0,0 @@
<html>
<head>
<title>Service Discovery</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">Service Discovery</div><p>
The service discovery extension allows to discover items and information about XMPP
entities. Follow these links to learn how to use this extension.
<ul>
<li><a href="#discoregister">Manage XMPP entity features</a></li>
<li><a href="#disconodeinfo">Provide node information</a></li>
<li><a href="#discoitems">Discover items associated with an XMPP entity</a></li>
<li><a href="#discoinfo">Discover information about an XMPP entity</a></li>
<li><a href="#discopublish">Publish publicly available items</a></li>
</ul>
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0030.html">XEP-30</a>
<hr>
<div class="subheader"><a name="discoregister">Manage XMPP entity features</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
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 <b>getInstanceFor(connection)</b> to the class <i><b>ServiceDiscoveryManager</b></i> where
connection is your XMPPConnection.<br></p>
<p>Once you have your ServiceDiscoveryManager you will be able to manage the supported features. To
register a new feature send <b>addFeature(feature)</b> to your <i><b>ServiceDiscoveryManager</b></i>
where feature is a String that represents the supported feature. To remove a supported feature send
<b>removeFeature(feature)</b> to your <i><b>ServiceDiscoveryManager</b></i> where feature is a
String that represents the feature to remove.</p>
<b>Examples</b><p>
In this example we can see how to add and remove supported features: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Obtain the ServiceDiscoveryManager associated with my XMPPConnection</font>
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
<font color="#3f7f5f">// Register that a new feature is supported by this XMPP entity</font>
discoManager.addFeature(namespace1);
<font color="#3f7f5f">// Remove the specified feature from the supported features by this XMPP entity</font>
discoManager.removeFeature(namespace2);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="disconodeinfo">Provide node information</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
In order to configure the associated nodes within the Smack client you will need to create a
NodeInformationProvider and register it with the <i><b>ServiceDiscoveryManager</b></i>. To get
your ServiceDiscoveryManager send <b>getInstanceFor(connection)</b> to the class <i><b>ServiceDiscoveryManager</b></i>
where connection is your XMPPConnection.<br></p>
<p>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 <b>setNodeInformationProvider(String node, NodeInformationProvider listener)</b>
to your <i><b>ServiceDiscoveryManager</b></i> where node is the item non-addressable as a JID and
listener is the <i><b>NodeInformationProvider</b></i> to register. To unregister a <i><b>NodeInformationProvider</b></i>
send <b>removeNodeInformationProvider(String node)</b> to your <i><b>ServiceDiscoveryManager</b></i> where
node is the item non-addressable as a JID whose information provider we want to unregister.</p>
<b>Examples</b><p>
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": <br>
<blockquote>
<pre> <font color="#3f7f5f">// Set the NodeInformationProvider that will provide information about the</font>
<font color="#3f7f5f">// joined rooms whenever a disco request is received </font>
ServiceDiscoveryManager.getInstanceFor(connection).setNodeInformationProvider(
<font color="#0000FF">"http://jabber.org/protocol/muc#rooms"</font>,
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;
}
});
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="discoitems">Discover items associated with an XMPP entity</a></div><p>
<b>Description</b><p>
In order to obtain information about a specific item you have to first discover the items available
in an XMPP entity.</p>
<b>Usage</b><p>
<p>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 <b>discoverItems(entityID)</b>
to your <i><b>ServiceDiscoveryManager</b></i> where entityID is the ID of the entity. The message
<b>discoverItems(entityID)</b> will answer an instance of <i><b>DiscoverItems</b></i> that contains
the discovered items.</p>
<b>Examples</b><p>
In this example we can see how to discover the items associated with an online catalog service: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Obtain the ServiceDiscoveryManager associated with my XMPPConnection</font>
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
<font color="#3f7f5f">// Get the items of a given XMPP entity</font>
<font color="#3f7f5f">// This example gets the items associated with online catalog service</font>
DiscoverItems discoItems = discoManager.discoverItems("plays.shakespeare.lit");
<font color="#3f7f5f">// Get the discovered items of the queried XMPP entity</font>
Iterator it = discoItems.getItems();
<font color="#3f7f5f">// Display the items of the remote XMPP entity</font>
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());
}
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="discoinfo">Discover information about an XMPP entity</a></div><p>
<b>Description</b><p>
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.</p>
<p>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).</p>
<b>Usage</b><p>
<p>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 <b>discoverInfo(entityID)</b>
to your <i><b>ServiceDiscoveryManager</b></i> where entityID is the ID of the entity. The message
<b>discoverInfo(entityID)</b> will answer an instance of <i><b>DiscoverInfo</b></i> that contains
the discovered information.</p>
<b>Examples</b><p>
In this example we can see how to discover the information of a conference room: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Obtain the ServiceDiscoveryManager associated with my XMPPConnection</font>
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
<font color="#3f7f5f">// Get the information of a given XMPP entity</font>
<font color="#3f7f5f">// This example gets the information of a conference room</font>
DiscoverInfo discoInfo = discoManager.discoverInfo("balconyscene@plays.shakespeare.lit");
<font color="#3f7f5f">// Get the discovered identities of the remote XMPP entity</font>
Iterator it = discoInfo.getIdentities();
<font color="#3f7f5f">// Display the identities of the remote XMPP entity</font>
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());
}
<font color="#3f7f5f">// Check if room is password protected</font>
discoInfo.containsFeature("muc_passwordprotected");
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="discopublish">Publish publicly available items</a></div><p>
<b>Description</b><p>
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).</p>
<b>Usage</b><p>
<p>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 <i><b>DiscoverItems</b></i> and configure it with the items to publish. Then you will have to
send <b>publishItems(String entityID, DiscoverItems discoverItems)</b> to your <i><b>ServiceDiscoveryManager</b></i>
where entityID is the address of the XMPP entity that will persist the items and discoverItems contains the items
to publish.</p>
<b>Examples</b><p>
In this example we can see how to publish new items: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Obtain the ServiceDiscoveryManager associated with my XMPPConnection</font>
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
<font color="#3f7f5f">// Create a DiscoverItems with the items to publish</font>
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);
<font color="#3f7f5f">// Publish the new items by sending them to the server</font>
discoManager.publishItems("host", itemsToPublish);
</pre>
</blockquote>
</body>
</html>

View file

@ -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);
```

View file

@ -1,176 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>File Transfer</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">File Transfer</div><p>
The file transfer extension allows the user to transmit and receive files.
<ul>
<li><a href="#sendfile">Send a file to another user</a></li>
<li><a href="#recievefile">Recieving a file from another user</a></li>
<li><a href="#monitorprogress">Monitoring the progress of a file transfer</a></li>
</ul>
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0095.html">XEP-95</a>
<a href="http://www.xmpp.org/extensions/xep-0096.html">XEP-96</a>
<a href="http://www.xmpp.org/extensions/xep-0065.html">XEP-65</a>
<a href="http://www.xmpp.org/extensions/xep-0047.html">XEP-47</a>
<hr>
<div class="subheader"><a name="sendfile">Send a file to another user</a></div><p>
<b>Description</b><p>
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.
<b>Usage</b><p>
In order to send a file you must first construct an instance of the <b><i>FileTransferManager</i></b> class.
In order to instantiate the manager you should call <i>FileTransferManager.getInstanceFor(connection)</i>
<p>Once you have your <b><i>FileTransferManager</i></b> you will need to create an outgoing
file transfer to send a file. The method to use on the <b><i>FileTransferManager</i></b>
is the <b>createOutgoingFileTransfer(userID)</b> 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.
<p>Now that you have your <b><i>OutgoingFileTransfer</i></b> instance you will want
to send the file. The method to send a file is <b>sendFile(file, description)</b>. 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.
<p>For information on monitoring the progress of a file transfer see the <a href="#monitorprogress">monitoring progress</a>
section of this document.
<p>Other means to send a file are also provided as part of the <b><i>OutgoingFileTransfer</i></b>. Please
consult the Javadoc for more information.
<b>Examples</b><p>
In this example we can see how to send a file: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create the file transfer manager</font>
FileTransferManager manager = FileTransferManager.getInstanceFor(connection);
<font color="#3f7f5f">// Create the outgoing file transfer</font>
OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(<font color="#0000FF">"romeo@montague.net"</font>);
<font color="#3f7f5f">// Send the file</font>
transfer.sendFile(new File(<font color="#0000FF">"shakespeare_complete_works.txt"</font>), <font color="#0000FF">"You won't believe this!"</font>);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="recievefile">Recieving a file from another user</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
In order to recieve a file you must first construct an instance of the <b><i>FileTransferManager</i></b> class.
In order to instantiate the manager you should call <i>FileTransferManager.getInstanceFor(connection)</i>
<p>Once you have your <b><i>FileTransferManager</i></b> you will need to register a listener
with it. The FileTransferListner interface has one method, <b>fileTransferRequest(request)</b>.
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 <b><i>FileTransferRequest</i></b>
class that return information about the transfer request.
<p>To accept the file transfer, call the <b>accept()</b>,
this method will create an <b><i>IncomingFileTransfer</i></b>. After you have the file transfer you may start
to transfer the file by calling the <b>recieveFile(file)</b> method.
The file provided to this method will be where the data from thefile transfer is saved.</p>
<p>Finally, to reject the file transfer the only method you need to call is <b>reject()</b>
on the <b><i>IncomingFileTransfer</i></b>.
<p>For information on monitoring the progress of a file transfer see the <a href="#monitorprogress">monitoring progress</a>
section of this document.
<p>Other means to recieve a file are also provided as part of the <b><i>IncomingFileTransfer</i></b>. Please
consult the Javadoc for more information.
<b>Examples</b><p>
In this example we can see how to approve or reject a file transfer request: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Create the file transfer manager</font>
FileTransferManager manager = FileTransferManager.getInstanceFor(connection);
<font color="#3f7f5f">// Create the listener</font>
manager.addFileTransferListener(new FileTransferListener() {
public void fileTransferRequest(FileTransferRequest request) {
<font color="#3f7f5f">// Check to see if the request should be accepted</font>
if(shouldAccept(request)) {
<font color="#3f7f5f">// Accept it</font>
IncomingFileTransfer transfer = request.accept();
transfer.recieveFile(new File(<font color="#0000FF">"shakespeare_complete_works.txt"</font>));
} else {
<font color="#3f7f5f">// Reject it</font>
request.reject();
}
}
});
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="monitorprogress">Monitoring the progress of a file transfer</a></div><p>
<b>Description</b><p>
While a file transfer is in progress you may wish to monitor the progress of a file transfer.</p>
<b>Usage</b><p>
<p>Both the <b><i>IncomingFileTransfer</i></b> and the <b><i>OutgoingFileTransfer</i></b>
extend the <b><i>FileTransfer</i></b> class which provides several methods to monitor
how a file transfer is progressing:
<ul>
<li><b>getStatus()</b> - 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.
<li><b>getProgress()</b> - 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.
<li><b>isDone()</b> - Similar to getProgress() except it returns a <i>boolean</i>. If the state is
rejected, canceled, error, or complete then true will be returned and false otherwise.
<li><b>getError()</b> - If there is an error during the file transfer this method will
return the type of error that occured.
</ul>
<b>Examples</b><p>
In this example we can see how to monitor a file transfer: <br>
<blockquote>
<pre> while(!transfer.isDone()) {
if(transfer.getStatus().equals(Status.ERROR)) {
System.out.println(<font color="#0000FF">"ERROR!!! "</font> + transfer.getError());
} else {
System.out.println(transfer.getStatus());
System.out.println(transfer.getProgress());
}
sleep(1000);
}
</pre>
</blockquote>
</body>
</html>

View file

@ -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);
}
```

View file

@ -1,156 +0,0 @@
<html>
<head>
<title>HTTP over XMPP transport</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">HTTP over XMPP transport</div><p>
Allows to transport HTTP communication over XMPP peer-to-peer networks.<p>
<ul>
<li><a href="#disco">Discover HOXT support</a></li>
<li><a href="#iqexchange">IQ exchange</a></li>
</ul>
<hr>
<div class="subheader"><a name="disco">Discover HOXT support</a></div><p>
<b>Description</b><p>
Before using this extension you must ensure that your counterpart supports it also.</p>
<b>Usage</b><p>
<p>Once you have your <i><b>ServiceDiscoveryManager</b></i> you will be able to discover information associated with
an XMPP entity. To discover the information of a given XMPP entity send <b>discoverInfo(entityID)</b>
to your <i><b>ServiceDiscoveryManager</b></i> where entityID is the ID of the entity. The message
<b>discoverInfo(entityID)</b> will answer an instance of <i><b>DiscoverInfo</b></i> that contains
the discovered information.</p>
<b>Examples</b><p>
In this example we can see how to check if the counterpart supports HOXT: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Obtain the ServiceDiscoveryManager associated with my XMPPConnection</font>
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
<font color="#3f7f5f">// Get the information of a given XMPP entity</font>
DiscoverInfo discoInfo = discoManager.discoverInfo("juliet@capulet.com");
<font color="#3f7f5f">// Check if room is HOXT is supported</font>
discoInfo.containsFeature("urn:xmpp:http");
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="iqexchange">IQ exchange</a></div><p>
<b>Description</b><p>
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).</p>
<b>Usage</b><p>
<p>First you need to register a <i><b>PacketListener</b></i> to be able to handle intended IQs.<p>
For the HTTP client you:
<ul>
<li>You create and send <i><b>HttpOverXmppReq</b></i> request.</li>
<li>Then you handle the <i><b>HttpOverXmppResp</b></i> response in your <i><b>PacketListener</b></i>.</li>
</ul>
For the HTTP server you:
<ul>
<li>You handle the <i><b>HttpOverXmppReq</b></i> requests in your <i><b>PacketListener</b></i>.</li>
<li>And create and send <i><b>HttpOverXmppResp</b></i> responses.</li>
</ul>
</p>
<b>Examples</b><p>
In this example we are HTTP client, so we send request (POST) and handle the response: <br>
<blockquote>
<pre> <font color="#3f7f5f">// register listener for IQ packets</font>
connection.addPacketListener(new IqPacketListener(), new PacketTypeFilter(IQ.class));
<font color="#3f7f5f">// create a request body</font>
String urlEncodedMessage = "I_love_you";
<font color="#3f7f5f">// create request</font>
HttpOverXmppReq.Req req = new HttpOverXmppReq.Req(HttpMethod.POST, "/mailbox");
req.setVersion("1.1");
<font color="#3f7f5f">// prepare headers</font>
Set&lt;Header&gt; set = new HashSet&lt;Header&gt;();
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));
<font color="#3f7f5f">// provide body or request (not mandatory, - empty body is used for GET)</font>
AbstractHttpOverXmpp.Text child = new AbstractHttpOverXmpp.Text(urlEncodedMessage);
AbstractHttpOverXmpp.Data data = new AbstractHttpOverXmpp.Data(child);
req.setData(data);
<font color="#3f7f5f">// create IQ packet</font>
HttpOverXmppReq packet = new HttpOverXmppReq();
packet.setReq(req);
packet.setTo("juliet@capulet.com/balcony");
packet.setType(IQ.Type.SET);
packet.setPacketID("42");
<font color="#3f7f5f">// send it</font>
connection.sendPacket(packet);
<font color="#3f7f5f">// then in your PacketListener</font>
private class IqPacketListener implements PacketListener {
@Override
public void processPacket(Packet packet) {
IQ iq = (IQ) packet;
<font color="#3f7f5f">// verify from and packed ID</font>
if (iq.getFrom().equals("juliet@capulet.com/balcony") && (iq.getPacketID().equals("42"))) {
<font color="#3f7f5f">// ensure it's not ERROR</font>
if (iq.getType().equals(IQ.Type.RESULT)) {
<font color="#3f7f5f">// check if correct IQ implementation arrived</font>
if (iq instanceof HttpOverXmppResp) {
HttpOverXmppResp resp = (HttpOverXmppResp) iq;
<font color="#3f7f5f">// check HTTP response code</font>
if (resp.getResp().getStatusCode() == 200) {
<font color="#3f7f5f">// get content of the response</font>
AbstractHttpOverXmpp.DataChild child = resp.getResp().getData().getChild();
<font color="#3f7f5f">// check which type of content of the response arrived</font>
if (child instanceof AbstractHttpOverXmpp.Xml) {
<font color="#3f7f5f">// print the message and anxiously read if from console ;)</font>
System.out.println(((AbstractHttpOverXmpp.Xml) child).getText());
} else {
<font color="#3f7f5f">// process other AbstractHttpOverXmpp.DataChild subtypes</font>
}
}
}
}
}
}
}
</pre>
</blockquote>
<hr>
</body>
</html>

View file

@ -0,0 +1,137 @@
HTTP over XMPP transport
========================
Allows to transport HTTP communication over XMPP peer-to-peer networks.
* Discover HOXT support
* IQ exchange
Discover HOXT support
---------------------
**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");
```
IQ exchange
-----------
**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:
* You create and send _**HttpOverXmppReq**_ request.
* Then you handle the _**HttpOverXmppResp**_ response in your _**PacketListener**_.
For the HTTP server you:
* You handle the _**HttpOverXmppReq**_ requests in your _**PacketListener**_.
* And create and send _**HttpOverXmppResp**_ responses.
**Examples**
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
}
}
}
}
}
}
}
```

View file

@ -1,15 +0,0 @@
<html>
<head>
<title>Smack Extensions User Manual</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<frameset cols="200,*">
<frame src="toc.html" name="navFrame" target="mainFrame">
<frame src="intro.html" name="mainFrame">
</frameset>
<noframes>
<H2>Smack Extensions User Manual</H2>
<a href="toc.html">Smack Extensions User Manual</a></noframes></html>

View file

@ -0,0 +1,70 @@
Smack Extensions User Manual
============================
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.
Smack Extensions and currently supported XEPs by Smack (smack-extensions)
-------------------------------------------------------------------------
| Name | XEP | Description |
|---------------------------------------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| [Data Forms](dataforms.html) | [XEP-0004](http://xmpp.org/extensions/xep-0004.html) | Allows to gather data using Forms. |
| Last Activity | [XEP-0012](http://xmpp.org/extensions/xep-0012.html) | Communicating information about the last activity associated with an XMPP entity. |
| Flexible Offline Message Retrieval | [XEP-0013](http://xmpp.org/extensions/xep-0013.html) | Extension for flexible, POP3-like handling of offline messages. |
| [Privacy Lists](privacy.html) | [XEP-0016](http://xmpp.org/extensions/xep-0016.html) | Enabling or disabling communication with other entities. |
| [Message Events](messageevents.html) | [XEP-0022](http://xmpp.org/extensions/xep-0022.html) | Requests and responds to message events. |
| [Service Discovery](disco.html) | [XEP-0030](http://xmpp.org/extensions/xep-0030.html) | Allows to discover services in XMPP entities. |
| Extended Stanza Addressing | [XEP-0033](http://xmpp.org/extensions/xep-0033.html) | Allows to include headers in stanzas in order to specifiy multiple recipients or sub-addresses. |
| [Multi User Chat](muc.html) | [XEP-0045](http://xmpp.org/extensions/xep-0045.html) | Allows configuration of, participation in, and administration of individual text-based conference rooms. |
| In-Band Bytestreams | [XEP-0047](http://xmpp.org/extensions/xep-0047.html) | Enables any two entities to establish a one-to-one bytestream between themselves using plain XMPP. |
| Bookmarks | [XEP-0048](http://xmpp.org/extensions/xep-0048.html) | Bookmarks, for e.g. MUC and web pages. |
| [Private Data](privatedata.html) | [XEP-0049](http://xmpp.org/extensions/xep-0049.html) | Manages private data. |
| Ad-Hoc Commands | [XEP-0050](http://xmpp.org/extensions/xep-0049.html) | Advertising and executing application-specific commands. |
| vcard-temp | [XEP-0054](http://xmpp.org/extensions/xep-0049.html) | The vCard-XML format currently in use. |
| Jabber Search | [XEP-0055](http://xmpp.org/extensions/xep-0055.html) | Search information repositories on the XMPP network. |
| [PubSub](pubsub.html) | [XEP-0060](http://xmpp.org/extensions/xep-0060.html) | Generic publish and subscribe functionality. |
| SOCKS5 Bytestrams | [XEP-0065](http://xmpp.org/extensions/xep-0065.html) | Out-of-band bytestream between any two XMPP entities. |
| [XHTML-IM](xhtml.html) | [XEP-0071](http://xmpp.org/extensions/xep-0071.html) | Allows send and receiving formatted messages using XHTML. |
| In-Band Registration | [XEP-0077](http://xmpp.org/extensions/xep-0077.html) | In-band registration with XMPP services. |
| Advanced Message Processing | [XEP-0079](http://xmpp.org/extensions/xep-0079.html) | Enables entities to request, and servers to perform, advanced processing of XMPP message stanzas. |
| XMPP Date Time Profiles | [XEP-0082](http://xmpp.org/extensions/xep-0082.html) | Standardization of Date and Time representation in XMPP. |
| Chat State Notifications | [XEP-0085](http://xmpp.org/extensions/xep-0085.html) | Communicating the status of a user in a chat session. |
| [Time Exchange](time.html) | [XEP-0090](http://xmpp.org/extensions/xep-0090.html) | Allows local time information to be shared between users. |
| Software Version | [XEP-0092](http://xmpp.org/extensions/xep-0092.html) | Retrieve and announce the software application of an XMPP entity. |
| Stream Initation | [XEP-0095](http://xmpp.org/extensions/xep-0095.html) | Initiating a data stream between any two XMPP entities. |
| [SI File Transfer](filetransfer.html) | [XEP-0096](http://xmpp.org/extensions/xep-0096.html) | Transfer files between two users over XMPP. |
| [Entity Capabilities](caps.html) | [XEP-0115](http://xmpp.org/extensions/xep-0115.html) | Broadcasting and dynamic discovery of entity capabilities. |
| Stream Compression | [XEP-0138](http://xmpp.org/extensions/xep-0138.html) | Support for optional compression of the XMPP stream.
| Personal Eventing Protocol | [XEP-0163](http://xmpp.org/extensions/xep-0163.html) | Using the XMPP publish-subscribe protocol to broadcast state change events associated with a XMPP account. |
| Message Delivery Receipts | [XEP-0184](http://xmpp.org/extensions/xep-0184.html) | Extension for message delivery receipts. The sender can request notification that the message has been delivered. |
| XMPP Ping | [XEP-0199](http://xmpp.org/extensions/xep-0199.html) | Sending application-level pings over XML streams.
| Entity Time | [XEP-0202](http://xmpp.org/extensions/xep-0202.html) | Allows entities to communicate their local time |
| Delayed Delivery | [XEP-0203](http://xmpp.org/extensions/xep-0203.html) | Extension for communicating the fact that an XML stanza has been delivered with a delay. |
| XMPP Over BOSH | [XEP-0206](http://xmpp.org/extensions/xep-0206.html) | Use Bidirectional-streams Over Synchronous HTTP (BOSH) to transport XMPP stanzas. |
| [Group Chat Invitations](invitation.html) | n/a | Send invitations to other users to join a group chat room. |
| [Jive Properties](properties.html) | n/a | TODO |
Experimental Smack Extensions and currently supported XEPs by Smack (smack-experimental)
----------------------------------------------------------------------------------------
| Name | XEP | Description |
|---------------------------------------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| Message Carbons | [XEP-0280](http://xmpp.org/extensions/xep-0280.html) | Keep all IM clients for a user engaged in a conversation, by carbon-copy outbound messages to all interested resources.
| [HTTP over XMPP transport](hoxt.html) | [XEP-0332](http://xmpp.org/extensions/xep-0332.html) | Allows to transport HTTP communication over XMPP peer-to-peer networks. |
Legacy Smack Extensions and currently supported XEPs by Smack (smack-legacy)
----------------------------------------------------------------------------
If a XEP becomes 'Deprecated' or 'Obsolete' the code will be moved to the *smack-legacy* subproject.
| Name | XEP | Description |
|---------------------------------------------|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| [Roster Item Exchange](rosterexchange.html) | [XEP-0093](http://xmpp.org/extensions/xep-0093.html) | Allows roster data to be shared between users. |

View file

@ -1,100 +0,0 @@
<html>
<head>
<title>Smack Extensions User Manual</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">Smack Extensions Manual</div>
<p>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.</p>
<p>This manual provides details about each of the "smackx" extensions, including what
it is, how to use it, and some simple example code.<p>
<div class="subheader">Current Extensions</div><p>
<table border="0" width="85%" cellspacing="0" cellpadding="3" style="border:1px #bbb solid;">
<tr bgcolor="#ddeeff">
<td><b>Name</b></td><td><b>XEP #</b></td><td><b>Description</b></td>
</tr>
<tr>
<td><a href="privatedata.html">Private Data</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0049.html">XEP-0049</a></td>
<td>Manages private data.</td>
</tr>
<tr>
<td><a href="xhtml.html">XHTML Messages</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0071.html">XEP-0071</a></td>
<td>Allows send and receiving formatted messages using XHTML.</td>
</tr>
<tr>
<td><a href="messageevents.html">Message Events</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0022.html">XEP-0022</a></td>
<td>Requests and responds to message events.</td>
</tr>
<tr>
<td><a href="dataforms.html">Data Forms</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0004.html">XEP-0004</a></td>
<td>Allows to gather data using Forms.</td>
</tr>
<tr>
<td><a href="muc.html">Multi User Chat</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0045.html">XEP-0045</a></td>
<td>Allows configuration of, participation in, and administration of individual text-based conference rooms.</td>
</tr>
<tr>
<td><a href="rosterexchange.html">Roster Item Exchange</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0093.html">XEP-0093</a></td>
<td>Allows roster data to be shared between users.</td>
</tr>
<tr>
<td><a href="time.html">Time Exchange</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0090.html">XEP-0090</a></td>
<td>Allows local time information to be shared between users.</td>
</tr>
<tr>
<td><a href="invitation.html">Group Chat Invitations</a></td>
<td>N/A</td>
<td>Send invitations to other users to join a group chat room.</td>
</tr>
<tr>
<td><a href="disco.html">Service Discovery</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0030.html">XEP-0030</a></td>
<td>Allows to discover services in XMPP entities.</td>
</tr>
<tr>
<td><a href="disco.html">File Transfer</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0096.html">XEP-0096</a></td>
<td>Transfer files between two users over XMPP.</td>
</tr>
<tr>
<td><a href="pubsub.html">PubSub</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0060.html">XEP-0060</a></td>
<td>Generic publish and subscribe functionality.</td>
</tr>
<tr>
<td><a href="caps.html">Entity Capabilities</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0115.html">XEP-0115</a></td>
<td>Broadcasting and dynamic discovery of entity capabilities.</td>
</tr>
<tr>
<td><a href="privacy.html">Privacy Lists</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0016.html">XEP-0016</a></td>
<td>Enabling or disabling communication with other entities.</td>
</tr>
<tr>
<td><a href="hoxt.html">HTTP over XMPP transport</a></td>
<td><a href="http://www.xmpp.org/extensions/xep-0332.html">XEP-0332</a></td>
<td>Allows to transport HTTP communication over XMPP peer-to-peer networks.</td>
</tr>
<tr>
<td><a href="properties.html">Jive Properties</a></td>
<td>N/A</td>
<td>TODO</td>
</tr>
</table>
</body>
</html>

View file

@ -0,0 +1,99 @@
Smack Extensions Manual
Current Extensions
**Name**
**XEP #**
**Description**
[Private Data](privatedata.html)
[XEP-0049](http://www.xmpp.org/extensions/xep-0049.html)
Manages private data.
[XHTML Messages](xhtml.html)
[XEP-0071](http://www.xmpp.org/extensions/xep-0071.html)
Allows send and receiving formatted messages using XHTML.
[Message Events](messageevents.html)
[XEP-0022](http://www.xmpp.org/extensions/xep-0022.html)
Requests and responds to message events.
[Data Forms](dataforms.html)
[XEP-0004](http://www.xmpp.org/extensions/xep-0004.html)
Allows to gather data using Forms.
[Multi User Chat](muc.html)
[XEP-0045](http://www.xmpp.org/extensions/xep-0045.html)
Allows configuration of, participation in, and administration of individual
text-based conference rooms.
[Roster Item Exchange](rosterexchange.html)
[XEP-0093](http://www.xmpp.org/extensions/xep-0093.html)
Allows roster data to be shared between users.
[Time Exchange](time.html)
[XEP-0090](http://www.xmpp.org/extensions/xep-0090.html)
Allows local time information to be shared between users.
[Group Chat Invitations](invitation.html)
N/A
Send invitations to other users to join a group chat room.
[Service Discovery](disco.html)
[XEP-0030](http://www.xmpp.org/extensions/xep-0030.html)
Allows to discover services in XMPP entities.
[File Transfer](filetransfer.html)
[XEP-0096](http://www.xmpp.org/extensions/xep-0096.html)
Transfer files between two users over XMPP.
[PubSub](pubsub.html)
[XEP-0060](http://www.xmpp.org/extensions/xep-0060.html)
Generic publish and subscribe functionality.
[Entity Capabilities](caps.html)
[XEP-0115](http://www.xmpp.org/extensions/xep-0115.html)
Broadcasting and dynamic discovery of entity capabilities.
[Privacy Lists](privacy.html)
[XEP-0016](http://www.xmpp.org/extensions/xep-0016.html)
Enabling or disabling communication with other entities.
[HTTP over XMPP transport](hoxt.html)
[XEP-0332](http://www.xmpp.org/extensions/xep-0332.html)
Allows to transport HTTP communication over XMPP peer-to-peer networks.
[Jive Properties](properties.html)
N/A
TODO

View file

@ -1,60 +0,0 @@
<html>
<head>
<title>Group Chat Invitations</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">Group Chat Invitations</div><p>
The group chat invitation packet extension is used to invite other
users to a group chat room.
<ul>
<li><a href="#send">Inviting Other Users</a></li>
<li><a href="#listen">Listen for Invitations</a></li>
</ul>
<p>
<b>XEP related:</b> N/A -- this protocol is outdated now that the Multi-User Chat (MUC) XEP is available
(<a href="http://www.xmpp.org/extensions/xep-0045.html">XEP-45</a>). However, most
existing clients still use this older protocol. Once MUC support becomes more
widespread, this API may be deprecated.
<hr>
<p><div class="subheader"><a name="send">Inviting Other Users</a></div><p>
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:
<pre>
Message message = new Message(<font color="#0000FF">"user@chat.example.com"</font>);
message.setBody(<font color="#0000FF">"Join me for a group chat!"</font>);
message.addExtension(new GroupChatInvitation(<font color="#0000FF">"room@chat.example.com"</font>));
con.sendPacket(message);
</pre>
The XML generated for the invitation portion of the code above would be:
<pre>
&lt;x xmlns="jabber:x:conference" jid="room@chat.example.com"/&gt;
</pre><p>
<hr>
<div class="subheader"><a name="listen">Listening for Invitations</a></div><p>
To listen for group chat invitations, use a PacketExtensionFilter for the
<tt>x</tt> element name and <tt>jabber:x:conference</tt> namespace, as in the
following code example:
<pre>
PacketFilter filter = new PacketExtensionFilter(<font color="#0000FF">"x"</font>, <font color="#0000FF">"jabber:x:conference"</font>);
<font color="#3f7f5f">// Create a packet collector or packet listeners using the filter...</font>
</pre>
</body>
</html>

View file

@ -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:
```
<x xmlns="jabber:x:conference" jid="room@chat.example.com"/>
```
Listening for Invitations
-------------------------
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...
```

View file

@ -0,0 +1,205 @@
Message Events
==============
This extension is used to request and respond to events relating to the
delivery, display, and composition of messages. There are three stages in this
extension:
1. Request for event notifications,
2. Receive the event notification requests and send event notifications, and
3. Receive the event notifications.
**XEP related:** [XEP-22](http://www.xmpp.org/extensions/xep-0022.html)
Requesting Event Notifications
------------------------------
**Description**
In order to receive event notifications for a given message you first have to
specify which events are you interested in. Each message that you send has to
request its own event notifications. Therefore, every message that you send as
part of a chat should request its own event notifications.
**Usage**
The class _MessageEventManager_ provides an easy way for requesting event
notifications. All you have to do is specify the message that requires the
event notifications and the events that you are interested in.
Use the static method _**MessageEventManager.addNotificationsRequests(Message
message, boolean offline, boolean delivered, boolean displayed, boolean
composing)**_ for requesting event notifications.
**Example**
Below you can find an example that logs in a user to the server, creates a
message, adds the requests for notifications and sends the message.
```
// Connect to the server and log in
conn1 = new XMPPConnection(host);
conn1.login(server_user1, pass1);
// Create a chat with user2
Chat chat1 = conn1.createChat(user2);
// Create a message to send
Message msg = chat1.createMessage();
msg.setSubject("Any subject you want");
msg.setBody("An interesting body comes here...");
// Add to the message all the notifications requests (offline,
// composing)
MessageEventManager.addNotificationsRequests(msg, **true**, **true**, **true**, **true**);
// Send the message that contains the notifications request
chat1.sendMessage(msg);
```
Reacting to Event Notification Requests
---------------------------------------
**Description**
You can receive notification requests for the following events: delivered,
displayed, composing and offline. You **must** listen for these requests and
react accordingly.
**Usage**
The general idea is to create a new _DefaultMessageEventRequestListener_ that
will listen to the event notifications requests and react with custom logic.
Then you will have to add the listener to the _MessageEventManager_ that works
on the desired _XMPPConnection_.
Note that _DefaultMessageEventRequestListener_ is a default implementation of
the _MessageEventRequestListener_ interface. The class
_DefaultMessageEventRequestListener_ automatically sends a delivered
notification to the sender of the message if the sender has requested to be
notified when the message is delivered. If you decide to create a new class
that implements the _MessageEventRequestListener_ interface, please remember
to send the delivered notification.
* To create a new _MessageEventManager_ use the _**MessageEventManager(XMPPConnection)**_ constructor.
* To create an event notification requests listener create a subclass of _**DefaultMessageEventRequestListener**_ or create a class that implements the _**MessageEventRequestListener**_ interface.
* To add a listener to the messageEventManager use the MessageEventManager's message _**addMessageEventRequestListener(MessageEventRequestListener)**_.
**Example**
Below you can find an example that connects two users to the server. One user
will create a message, add the requests for notifications and will send the
message to the other user. The other user will add a
_DefaultMessageEventRequestListener_ to a _MessageEventManager_ that will
listen and react to the event notification requested by the other user.
```
// 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);
// User2 creates a MessageEventManager
MessageEventManager messageEventManager = new MessageEventManager(conn2);
// User2 adds the listener that will react to the event notifications requests
messageEventManager.addMessageEventRequestListener(new DefaultMessageEventRequestListener() {
public void deliveredNotificationRequested(
String from,
String packetID,
MessageEventManager messageEventManager) {
super.deliveredNotificationRequested(from, packetID, messageEventManager);
// DefaultMessageEventRequestListener automatically responds that the message was delivered when receives this r
System.out.println("Delivered Notification Requested (" + from + ", " + packetID + ")");
}
public void displayedNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.displayedNotificationRequested(from, packetID,
// Send to the message's sender that the message was
messageEventManager.sendDisplayedNotification(from, packetID);
}
public void composingNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.composingNotificationRequested(from, packetID, messageEventManager);
// Send to the message's sender that the message's receiver is composing a reply
messageEventManager.sendComposingNotification(from, packetID);
}
public void offlineNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.offlineNotificationRequested(from, packetID, messageEventManager);
// The XMPP server should take care of this request. Do nothing.
System.out.println("Offline Notification Requested (" + from + ", " + packetID + ")");
}
});
// User1 creates a chat with user2
Chat chat1 = conn1.createChat(user2);
// User1 creates a message to send to user2
Message msg = chat1.createMessage();
msg.setSubject("Any subject you want");
msg.setBody("An interesting body comes here...");
// User1 adds to the message all the notifications requests (offline, delivered, displayed,
// composing)
MessageEventManager.addNotificationsRequests(msg, true, true, true, true);
// User1 sends the message that contains the notifications request
chat1.sendMessage(msg);
Thread.sleep(500);
// User2 sends to the message's sender that the message's receiver cancelled composing a reply
messageEventManager.sendCancelledNotification(user1, msg.getPacketID());
```
Reacting to Event Notifications
-------------------------------
**Description**
Once you have requested for event notifications you will start to receive
notifications of events. You can receive notifications of the following
events: delivered, displayed, composing, offline and cancelled. You will
probably want to react to some or all of these events.
**Usage**
The general idea is to create a new _MessageEventNotificationListener_ that
will listen to the event notifications and react with custom logic. Then you
will have to add the listener to the _MessageEventManager_ that works on the
desired _XMPPConnection_.
* To create a new _MessageEventManager_ use the _**MessageEventManager(XMPPConnection)**_ constructor.
* To create an event notifications listener create a class that implements the _**MessageEventNotificationListener**_ interface.
* To add a listener to the messageEventManager use the MessageEventManager's message _**addMessageEventNotificationListener(MessageEventNotificationListener)**_.
**Example**
Below you can find an example that logs in a user to the server, adds a
_MessageEventNotificationListener_ to a _MessageEventManager_ that will listen
and react to the event notifications, creates a message, adds the requests for
notifications and sends the message.
```
// Connect to the server and log in
conn1 = new XMPPConnection(host);
conn1.login(server_user1, pass1);
// Create a MessageEventManager
MessageEventManager messageEventManager = new MessageEventManager(conn1);
// Add the listener that will react to the event notifications
messageEventManager.addMessageEventNotificationListener(new MessageEventNotificationListener() {
public void deliveredNotification(String from, String packetID) {
System.out.println("The message has been delivered (" + from + ", " + packetID + ")");
}
public void displayedNotification(String from, String packetID) {
System.out.println("The message has been displayed (" + from + ", " + packetID + ")");
}
public void composingNotification(String from, String packetID) {
System.out.println("The message's receiver is composing a reply (" + from + ", " + packetID + ")");
}
public void offlineNotification(String from, String packetID) {
System.out.println("The message's receiver is offline (" + from + ", " + packetID + ")");
}
public void cancelledNotification(String from, String packetID) {
System.out.println("The message's receiver cancelled composing a reply (" + from + ", " + packetID + ")");
}
});
// Create a chat with user2
Chat chat1 = conn1.createChat(user2);
// Create a message to send
Message msg = chat1.createMessage();
msg.setSubject("Any subject you want");
msg.setBody("An interesting body comes here...");
// Add to the message all the notifications requests (offline, delivered, displayed,
// composing)
MessageEventManager.addNotificationsRequests(msg, **true**, **true**, **true**, **true**);
// Send the message that contains the notifications request
chat1.sendMessage(msg);
```

View file

@ -1,619 +0,0 @@
<html>
<head>
<title>Multi User Chat</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">Multi User Chat</div><p>
Allows configuration of, participation in, and administration of individual text-based conference rooms.<p>
<ul>
<li><a href="#create">Create a new Room</a></li>
<li><a href="#join">Join a room</a></li>
<li><a href="#invite">Manage room invitations</a></li>
<li><a href="#discomuc">Discover MUC support</a></li>
<li><a href="#discojoin">Discover joined rooms</a></li>
<li><a href="#discoroom">Discover room information</a></li>
<li><a href="#privchat">Start a private chat</a></li>
<li><a href="#subject">Manage changes on room subject</a></li>
<li><a href="#role">Manage role modifications</a></li>
<li><a href="#afiliation">Manage affiliation modifications</a></li>
</ul>
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0045.html">XEP-45</a>
<hr>
<div class="subheader"><a name="create">Create a new Room</a></div><p>
<b>Description</b><p>
Allowed users may create new rooms. There are two types of rooms that you can create. <b>Instant rooms</b>
which are available for immediate access and are automatically created based on some default
configuration and <b>Reserved rooms</b> which are manually configured by the room creator before
anyone is allowed to enter.</p>
<b>Usage</b><p>
In order to create a room you will need to first create an instance of <i><b>MultiUserChat</b></i>. The
room name passed to the constructor will be the name of the room to create. The next step is to send
<b>create(String nickname)</b> to the <i><b>MultiUserChat</b></i> instance where nickname is the nickname
to use when joining the room.</p><p>
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 <b>sendConfigurationForm(Form form)</b> 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.</p>
<b>Examples</b><p>
In this example we can see how to create an instant room: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Create a MultiUserChat using a XMPPConnection for a room</font>
MultiUserChat muc = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
<font color="#3f7f5f">// Create the room</font>
muc.create(<font color="#0000FF">"testbot"</font>);
<font color="#3f7f5f">// Send an empty room configuration form which indicates that we want</font>
<font color="#3f7f5f">// an instant room</font>
muc.sendConfigurationForm(new Form(Form.TYPE_SUBMIT));
</pre>
</blockquote>
In this example we can see how to create a reserved room. The form is completed with default values: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Create a MultiUserChat using a XMPPConnection for a room</font>
MultiUserChat muc = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
<font color="#3f7f5f">// Create the room</font>
muc.create(<font color="#0000FF">"testbot"</font>);
<font color="#3f7f5f">// Get the the room's configuration form</font>
Form form = muc.getConfigurationForm();
<font color="#3f7f5f">// Create a new form to submit based on the original form</font>
Form submitForm = form.createAnswerForm();
<font color="#3f7f5f">// Add default answers to the form to submit</font>
for (Iterator fields = form.getFields(); fields.hasNext();) {
FormField field = (FormField) fields.next();
if (!FormField.TYPE_HIDDEN.equals(field.getType()) && field.getVariable() != null) {
<font color="#3f7f5f">// Sets the default value as the answer</font>
submitForm.setDefaultAnswer(field.getVariable());
}
}
<font color="#3f7f5f">// Sets the new owner of the room</font>
List owners = new ArrayList();
owners.add(<font color="#0000FF">"johndoe@jabber.org"</font>);
submitForm.setAnswer(<font color="#0000FF">"muc#roomconfig_roomowners"</font>, owners);
<font color="#3f7f5f">// Send the completed form (with default values) to the server to configure the room</font>
muc.sendConfigurationForm(submitForm);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="join">Join a room</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
In order to join a room you will need to first create an instance of <i><b>MultiUserChat</b></i>. The
room name passed to the constructor will be the name of the room to join. The next step is to send
<b>join(...)</b> to the <i><b>MultiUserChat</b></i> 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 <b>join(String nickname)</b> where nickname if your nickname in
the room. In case the room requires a password in order to join you could then use
<b>join(String nickname, String password)</b>. And finally, the most complete way to join a room is to send
<b>join(String nickname, String password, DiscussionHistory history, long timeout)</b>
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.</p>
<b>Examples</b><p>
In this example we can see how to join a room with a given nickname: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Create a MultiUserChat using a XMPPConnection for a room</font>
MultiUserChat muc2 = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
<font color="#3f7f5f">// User2 joins the new room</font>
<font color="#3f7f5f">// The room service will decide the amount of history to send</font>
muc2.join(<font color="#0000FF">"testbot2"</font>);
</pre>
</blockquote>
In this example we can see how to join a room with a given nickname and password: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Create a MultiUserChat using a XMPPConnection for a room</font>
MultiUserChat muc2 = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
<font color="#3f7f5f">// User2 joins the new room using a password</font>
<font color="#3f7f5f">// The room service will decide the amount of history to send</font>
muc2.join(<font color="#0000FF">"testbot2"</font>, <font color="#0000FF">"password"</font>);
</pre>
</blockquote>
In this example we can see how to join a room with a given nickname specifying the amount of history
to receive: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Create a MultiUserChat using a XMPPConnection for a room</font>
MultiUserChat muc2 = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
<font color="#3f7f5f">// User2 joins the new room using a password and specifying</font>
<font color="#3f7f5f">// the amount of history to receive. In this example we are requesting the last 5 messages.</font>
DiscussionHistory history = new DiscussionHistory();
history.setMaxStanzas(5);
muc2.join(<font color="#0000FF">"testbot2"</font>, <font color="#0000FF">"password"</font>, history, SmackConfiguration.getPacketReplyTimeout());
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="invite">Manage room invitations</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
In order to invite another user to a room you must be already joined to the room. Once you are
joined just send <b>invite(String participant, String reason)</b> to the <i><b>MultiUserChat</b></i>
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.</p><p>
If potential invitees want to listen for room invitations then the invitee must add an <i><b>InvitationListener</b></i>
to the <i><b>MultiUserChat</b></i> class. Since the <i><b>InvitationListener</b></i> is an <i>interface</i>,
it is necessary to create a class that implements this <i>interface</i>. If an inviter wants to
listen for room invitation rejections, just add an <i><b>InvitationRejectionListener</b></i>
to the <i><b>MultiUserChat</b></i>. <i><b>InvitationRejectionListener</b></i> is also an
interface so you will need to create a class that implements this interface.</p>
<b>Examples</b><p>
In this example we can see how to invite another user to the room and lister for possible rejections: <br>
<blockquote>
<pre> <font color="#3f7f5f">// User2 joins the room</font>
MultiUserChat muc2 = new MultiUserChat(conn2, room);
muc2.join(<font color="#0000FF">"testbot2"</font>);
<font color="#3f7f5f">// User2 listens for invitation rejections</font>
muc2.addInvitationRejectionListener(new InvitationRejectionListener() {
public void invitationDeclined(String invitee, String reason) {
<font color="#3f7f5f">// Do whatever you need here...</font>
}
});
<font color="#3f7f5f">// User2 invites user3 to join to the room</font>
muc2.invite(<font color="#0000FF">"user3@host.org/Smack"</font>, <font color="#0000FF">"Meet me in this excellent room"</font>);
</pre>
</blockquote>
In this example we can see how to listen for room invitations and decline invitations: <br>
<blockquote>
<pre> <font color="#3f7f5f">// User3 listens for MUC invitations</font>
MultiUserChat.addInvitationListener(conn3, new InvitationListener() {
public void invitationReceived(XMPPConnection conn, String room, String inviter, String reason, String password) {
<font color="#3f7f5f">// Reject the invitation</font>
MultiUserChat.decline(conn, room, inviter, <font color="#0000FF">"I'm busy right now"</font>);
}
});
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="discomuc">Discover MUC support</a></div><p>
<b>Description</b><p>
A user may want to discover if one of the user's contacts supports the Multi-User Chat protocol.</p>
<b>Usage</b><p>
In order to discover if one of the user's contacts supports MUC just send
<b>isServiceEnabled(XMPPConnection connection, String user)</b> to the <i><b>MultiUserChat</b></i>
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.</p>
<b>Examples</b><p>
In this example we can see how to discover support of MUC: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Discover whether user3@host.org supports MUC or not</font>
boolean supports = MultiUserChat.isServiceEnabled(conn, <font color="#0000FF">"user3@host.org/Smack"</font>);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="discojoin">Discover joined rooms</a></div><p>
<b>Description</b><p>
A user may also want to query a contact regarding which rooms the contact is in.</p>
<b>Usage</b><p>
In order to get the rooms where a user is in just send
<b>getJoinedRooms(XMPPConnection connection, String user)</b> to the <i><b>MultiUserChat</b></i>
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.</p>
<b>Examples</b><p>
In this example we can see how to get the rooms where a user is in: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Get the rooms where user3@host.org has joined</font>
Iterator joinedRooms = MultiUserChat.getJoinedRooms(conn, <font color="#0000FF">"user3@host.org/Smack"</font>);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="discoroom">Discover room information</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
In order to discover information about a room just send <b>getRoomInfo(XMPPConnection connection, String room)</b>
to the <i><b>MultiUserChat</b></i> 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.</p>
<b>Examples</b><p>
In this example we can see how to discover information about a room: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Discover information about the room roomName@conference.myserver</font>
RoomInfo info = MultiUserChat.getRoomInfo(conn, <font color="#0000FF">"roomName@conference.myserver"</font>);
System.out.println("Number of occupants:" + info.getOccupantsCount());
System.out.println("Room Subject:" + info.getSubject());
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="privchat">Start a private chat</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
To create a private chat with another room occupant just send <b>createPrivateChat(String participant)</b>
to the <i><b>MultiUserChat</b></i> 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 <i><b>Chat</b></i> object that you can use to chat with the other room occupant.</p>
<b>Examples</b><p>
In this example we can see how to start a private chat with another room occupant: <br>
<blockquote>
<pre> <font color="#3f7f5f">// Start a private chat with another participant</font>
Chat chat = muc2.createPrivateChat(<font color="#0000FF">"myroom@conference.jabber.org/johndoe"</font>);
chat.sendMessage(<font color="#0000FF">"Hello there"</font>);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="subject">Manage changes on room subject</a></div><p>
<b>Description</b><p>
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.</p><p>
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.</p>
<b>Usage</b><p>
In order to modify the room's subject just send <b>changeSubject(String subject)</b> to the
<i><b>MultiUserChat</b></i> 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
<i><b>SubjectUpdatedListener</b></i> to the <i><b>MultiUserChat</b></i> by sending
<b>addSubjectUpdatedListener(SubjectUpdatedListener listener)</b> to the <i><b>MultiUserChat</b></i>.
Since the <i><b>SubjectUpdatedListener</b></i> is an <i>interface</i>, it is necessary to create a class
that implements this <i>interface</i>.</p>
<b>Examples</b><p>
In this example we can see how to change the room's subject and react whenever the room's subject is
modified: <br>
<blockquote>
<pre> <font color="#3f7f5f">// An occupant wants to be notified every time the room's subject is changed</font>
muc3.addSubjectUpdatedListener(new SubjectUpdatedListener() {
public void subjectUpdated(String subject, String from) {
....
}
});
<font color="#3f7f5f">// A room's owner changes the room's subject</font>
muc2.changeSubject(<font color="#0000FF">"New Subject"</font>);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="role">Manage role modifications</a></div><p>
<b>Description</b><p>
There are four defined roles that an occupant can have:</p>
<ol start="" type="">
<li>Moderator</li>
<li>Participant</li>
<li>Visitor</li>
<li>None (the absence of a role)</li>
</ol><p>
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.</p><p>
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.</p><p>
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.</p>
<b>Usage</b><p>
In order to grant voice (i.e. make someone a <i>participant</i>) just send the message
<b>grantVoice(String nickname)</b> to <i><b>MultiUserChat</b></i>. Use <b>revokeVoice(String nickname)</b>
to revoke the occupant's voice (i.e. make the occupant a <i>visitor</i>).</p><p>
In order to grant moderator privileges to a participant or visitor just send the message
<b>grantModerator(String nickname)</b> to <i><b>MultiUserChat</b></i>. Use <b>revokeModerator(String nickname)</b>
to revoke the moderator privilege from the occupant thus making the occupant a participant.</p><p>
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 <b><i>ParticipantStatusListener</i></b>. But if you are interested
in listening for your own role modification events, use the listener <b><i>UserStatusListener</i></b>. Both listeners
should be added to the <i><b>MultiUserChat</b></i> by using
<b>addParticipantStatusListener(ParticipantStatusListener listener)</b> or
<b>addUserStatusListener(UserStatusListener listener)</b> 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 <b><i>DefaultUserStatusListener</i></b>
and <b><i>DefaultParticipantStatusListener</i></b>. Below you will find the sent messages to the listeners whenever
an occupant's role has changed.</p><p>
These are the triggered events when the role has been upgraded:
</p>
<table border="1">
<tr><td><b>Old</b></td><td><b>New</b></td><td><b>Events</b></td></tr>
<tr><td>None</td><td>Visitor</td><td>--</td></tr>
<tr><td>Visitor</td><td>Participant</td><td>voiceGranted</td></tr>
<tr><td>Participant</td><td>Moderator</td><td>moderatorGranted</td></tr>
<tr><td>None</td><td>Participant</td><td>voiceGranted</td></tr>
<tr><td>None</td><td>Moderator</td><td>voiceGranted + moderatorGranted</td></tr>
<tr><td>Visitor</td><td>Moderator</td><td>voiceGranted + moderatorGranted</td></tr>
</table><p>
These are the triggered events when the role has been downgraded:
</p>
<table border="1">
<tr><td><b>Old</b></td><td><b>New</b></td><td><b>Events</b></td></tr>
<tr><td>Moderator</td><td>Participant</td><td>moderatorRevoked</td></tr>
<tr><td>Participant</td><td>Visitor</td><td>voiceRevoked</td></tr>
<tr><td>Visitor</td><td>None</td><td>kicked</td></tr>
<tr><td>Moderator</td><td>Visitor</td><td>voiceRevoked + moderatorRevoked</td></tr>
<tr><td>Moderator</td><td>None</td><td>kicked</td></tr>
<tr><td>Participant</td><td>None</td><td>kicked</td></tr>
</table></p>
<b>Examples</b><p>
In this example we can see how to grant voice to a visitor and listen for the notification events: <br>
<blockquote>
<pre> <font color="#3f7f5f">// User1 creates a room</font>
muc = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
muc.create(<font color="#0000FF">"testbot"</font>);
<font color="#3f7f5f">// User1 (which is the room owner) configures the room as a moderated room</font>
Form form = muc.getConfigurationForm();
Form answerForm = form.createAnswerForm();
answerForm.setAnswer(<font color="#0000FF">"muc#roomconfig_moderatedroom"</font>, <font color="#0000FF">"1"</font>);
muc.sendConfigurationForm(answerForm);
<font color="#3f7f5f">// User2 joins the new room (as a visitor)</font>
MultiUserChat muc2 = new MultiUserChat(conn2, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
muc2.join(<font color="#0000FF">"testbot2"</font>);
<font color="#3f7f5f">// User2 will listen for his own "voice" notification events</font>
muc2.addUserStatusListener(new DefaultUserStatusListener() {
public void voiceGranted() {
super.voiceGranted();
...
}
public void voiceRevoked() {
super.voiceRevoked();
...
}
});
<font color="#3f7f5f">// User3 joins the new room (as a visitor)</font>
MultiUserChat muc3 = new MultiUserChat(conn3, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
muc3.join(<font color="#0000FF">"testbot3"</font>);
<font color="#3f7f5f">// User3 will lister for other occupants "voice" notification events</font>
muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() {
public void voiceGranted(String participant) {
super.voiceGranted(participant);
...
}
public void voiceRevoked(String participant) {
super.voiceRevoked(participant);
...
}
});
<font color="#3f7f5f">// The room's owner grants voice to user2</font>
muc.grantVoice(<font color="#0000FF">"testbot2"</font>);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="afiliation">Manage affiliation modifications</a></div><p>
<b>Description</b><p>
There are five defined affiliations that a user can have in relation to a room:</p>
<ol start="" type="">
<li>Owner</li>
<li>Admin</li>
<li>Member</li>
<li>Outcast</li>
<li>None (the absence of an affiliation)</li>
</ol><p>
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.</p><p>
If a user without a defined affiliation enters a room, the user's affiliation is defined as &quot;none&quot;;
however, this affiliation does not persist across visits.</p><p>
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 &quot;none&quot; or &quot;member&quot;) before such actions could be performed
on them.</p><p>
The member affiliation provides a way for a room owner or admin to specify a &quot;whitelist&quot; 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).</p><p>
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.</p>
<b>Usage</b><p>
In order to grant membership to a room, administrator privileges or owner priveliges just send
<b>grantMembership(String jid)</b>, <b>grantAdmin(String jid)</b> or <b>grantOwnership(String jid)</b>
to <i><b>MultiUserChat</b></i> respectively. Use <b>revokeMembership(String jid)</b>, <b>revokeAdmin(String jid)</b>
or <b>revokeOwnership(String jid)</b> to revoke the membership to a room, administrator privileges or
owner priveliges respectively.</p><p>
In order to ban a user from the room just send the message <b>banUser(String jid, String reason)</b> to
<i><b>MultiUserChat</b></i>.</p><p>
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 <b><i>ParticipantStatusListener</i></b>. But if you are interested
in listening for your own affiliation modification events, use the listener <b><i>UserStatusListener</i></b>. Both listeners
should be added to the <i><b>MultiUserChat</b></i> by using
<b>addParticipantStatusListener(ParticipantStatusListener listener)</b> or
<b>addUserStatusListener(UserStatusListener listener)</b> 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 <b><i>DefaultUserStatusListener</i></b>
and <b><i>DefaultParticipantStatusListener</i></b>. Below you will find the sent messages to the listeners whenever
a user's affiliation has changed.</p><p>
These are the triggered events when the affiliation has been upgraded:
</p>
<table border="1">
<tr><td><b>Old</b></td><td><b>New</b></td><td><b>Events</b></td></tr>
<tr><td>None</td><td>Member</td><td>membershipGranted</td></tr>
<tr><td>Member</td><td>Admin</td><td>membershipRevoked + adminGranted</td></tr>
<tr><td>Admin</td><td>Owner</td><td>adminRevoked + ownershipGranted</td></tr>
<tr><td>None</td><td>Admin</td><td>adminGranted</td></tr>
<tr><td>None</td><td>Owner</td><td>ownershipGranted</td></tr>
<tr><td>Member</td><td>Owner</td><td>membershipRevoked + ownershipGranted</td></tr>
</table><p>
These are the triggered events when the affiliation has been downgraded:
</p>
<table border="1">
<tr><td><b>Old</b></td><td><b>New</b></td><td><b>Events</b></td></tr>
<tr><td>Owner</td><td>Admin</td><td>ownershipRevoked + adminGranted</td></tr>
<tr><td>Admin</td><td>Member</td><td>adminRevoked + membershipGranted</td></tr>
<tr><td>Member</td><td>None</td><td>membershipRevoked</td></tr>
<tr><td>Owner</td><td>Member</td><td>ownershipRevoked + membershipGranted</td></tr>
<tr><td>Owner</td><td>None</td><td>ownershipRevoked</td></tr>
<tr><td>Admin</td><td>None</td><td>adminRevoked</td></tr>
<tr><td><i>Anyone</i></td><td>Outcast</td><td>banned</td></tr>
</table></p>
<b>Examples</b><p>
In this example we can see how to grant admin privileges to a user and listen for the notification events: <br>
<blockquote>
<pre> <font color="#3f7f5f">// User1 creates a room</font>
muc = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
muc.create(<font color="#0000FF">"testbot"</font>);
<font color="#3f7f5f">// User1 (which is the room owner) configures the room as a moderated room</font>
Form form = muc.getConfigurationForm();
Form answerForm = form.createAnswerForm();
answerForm.setAnswer(<font color="#0000FF">"muc#roomconfig_moderatedroom"</font>, <font color="#0000FF">"1"</font>);
muc.sendConfigurationForm(answerForm);
<font color="#3f7f5f">// User2 joins the new room (as a visitor)</font>
MultiUserChat muc2 = new MultiUserChat(conn2, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
muc2.join(<font color="#0000FF">"testbot2"</font>);
<font color="#3f7f5f">// User2 will listen for his own admin privileges</font>
muc2.addUserStatusListener(new DefaultUserStatusListener() {
public void membershipRevoked() {
super.membershipRevoked();
...
}
public void adminGranted() {
super.adminGranted();
...
}
});
<font color="#3f7f5f">// User3 joins the new room (as a visitor)</font>
MultiUserChat muc3 = new MultiUserChat(conn3, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
muc3.join(<font color="#0000FF">"testbot3"</font>);
<font color="#3f7f5f">// User3 will lister for other users admin privileges</font>
muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() {
public void membershipRevoked(String participant) {
super.membershipRevoked(participant);
...
}
public void adminGranted(String participant) {
super.adminGranted(participant);
...
}
});
<font color="#3f7f5f">// The room's owner grants admin privileges to user2</font>
muc.grantAdmin(<font color="#0000FF">"user2@jabber.org"</font>);
</pre>
</blockquote>
</body>
</html>

View file

@ -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");
```

View file

@ -1,164 +0,0 @@
<html>
<head>
<title>Smack: Privacy - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">
Privacy
</div>
<div class="nav">
&laquo; <a href="index.html">Table of Contents</a>
</div>
<p class="subheader">What is?</p>
<p>
<tt>Privacy</tt> is a method for users to block communications from particular other users. In XMPP this is done by managing one's privacy lists.<br />
Server-side privacy lists enable successful completion of the following use cases:
<ul>
<li>Retrieving one's privacy lists.
<li>Adding, removing, and editing one's privacy lists.
<li>Setting, changing, or declining active lists.
<li>Setting, changing, or declining the default list (i.e., the list that is active by default).
<li>Allowing or blocking messages based on JID, group, or subscription type (or globally).
<li>Allowing or blocking inbound presence notifications based on JID, group, or subscription type (or globally).
<li>Allowing or blocking outbound presence notifications based on JID, group, or subscription type (or globally).
<li>Allowing or blocking IQ stanzas based on JID, group, or subscription type (or globally).
<li>Allowing or blocking all communications based on JID, group, or subscription type (or globally).
</ul>
<p>
<p class="subheader">How can I use it?</p>
<p>
The API implementation releases three main public classes:
<ul>
<li><tt>PrivacyListManager</tt>: this is the main API class to retrieve and handle server privacy lists.
<li><tt>PrivacyList</tt>: witch represents one privacy list, with a name, a set of privacy items. For example, the list with visible or invisible.
<li><tt>PrivacyItem</tt>: block or allow one aspect of privacy. For example, to allow my friend to see my presence.
</ul>
<ol>
<li> Right from the start, a client MAY <b>get his/her privacy list</b> that is stored in the server:<br />
<div class="code">
<pre>
<font color="gray"><i>// Create a privacy manager for the current connection.</i></font>
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
<font color="gray"><i>// Retrieve server privacy lists</i></font>
PrivacyList[] lists = privacyManager.getPrivacyLists();
</pre>
</div>
Now the client is able to show every <tt>PrivacyItem</tt> of the server and also for every list if it is active, default or none of them. The client is a listener of privacy changes.<br />
<br />
<li> In order to <b>add a new list in the server</b>, the client MAY implement something like:
<div class="code">
<pre>
<font color="gray"><i>// Set the name of the list</i></font>
String listName = <font color="green">"newList"</font>;
<font color="gray"><i>// Create the list of <tt>PrivacyItem</tt> that will allow or deny some privacy aspect</i></font>
String user = <font color="green">"tybalt@example.com"</font>;
String groupName = <font color="green">"enemies"</font>;
ArrayList privacyItems = new ArrayList();
PrivacyItem item = new PrivacyItem(PrivacyItem.Type.jid, user, <font color="navy">true</font>, 1);
privacyItems.add(item);
item = new PrivacyItem(PrivacyItem.Type.subscription, PrivacyItem.SUBSCRIPTION_BOTH, <font color="navy">true</font>, 2);
privacyItems.add(item);
item = new PrivacyItem(PrivacyItem.Type.group, groupName, <font color="navy">false</font>, 3);
item.setFilterMessage(<font color="navy">true</font>);
privacyItems.add(item);
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
<font color="gray"><i>// Create the new list.</i></font>
privacyManager.createPrivacyList(listName, privacyItems);
</pre>
</div>
<li> To <b>modify an existent list</b>, the client code MAY be like:
<div class="code">
<pre>
<font color="gray"><i>// Set the name of the list</i></font>
String listName = <font color="green">"existingList"</font>;
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
<font color="gray"><i>// Sent the new list to the server.</i></font>
privacyManager.updatePrivacyList(listName, items);
</pre>
</div>
Notice <tt>items</tt> was defined at the example 2 and MUST contain all the elements in the list (not the "delta").
<li> In order to <b>delete an existing list</b>, the client MAY perform something like:
<div class="code">
<pre>
<font color="gray"><i>// Set the name of the list</i></font>
String listName = <font color="green">"existingList"</font>;
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
<font color="gray"><i>// Remove the list.</i></font>
privacyManager.deletePrivacyList(listName);
</pre>
</div>
<li> In order to <b>decline the use of an active list</b>, the client MAY perform something like:
<div class="code">
<pre>
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
<font color="gray"><i>// Decline the use of the active list.</i></font>
privacyManager.declineActiveList();
</pre>
</div>
<li> In order to <b>decline the use of a default list</b>, the client MAY perform something like:
<div class="code">
<pre>
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
<font color="gray"><i>// Decline the use of the default list.</i></font>
privacyManager.declineDefaultList();
</pre>
</div>
</ol>
<p class="subheader">Listening for Privacy Changes</p>
<p>
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 <tt>PrivacyListListener</tt> interface.
Clients may need to react when a privacy list is modified. The <tt>PrivacyListManager</tt> lets you add listerners that will be notified when a list has been changed. Listeners should implement the <tt>PrivacyListListener</tt> interface.<br />
The most important notification is <tt>updatedPrivacyList</tt> that is performed when a privacy list changes its privacy items.<br />
The listener becomes notified after performing:
<div class="code">
<pre>
<font color="gray"><i>// Get the privacy manager for the current connection.</i></font>
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
<font color="gray"><i>// Add the listener (this) to get notified</i></font>
privacyManager.addListener(<font color="navy">this</font>);
</pre>
</div>
</p>
<p class="subheader">References</p>
<ul>
<li><a href="http://xmpp.org/extensions/xep-0016.html">XEP-0016: Privacy Lists</a>
</ul>
</p>
<br clear="all" /><br><br>
<div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

View file

@ -0,0 +1,139 @@
Privacy Lists
============
[XEP-0016: Privacy Lists](http://xmpp.org/extensions/xep-0016.html)
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:
* Retrieving one's privacy lists.
* Adding, removing, and editing one's privacy lists.
* Setting, changing, or declining active lists.
* Setting, changing, or declining the default list (i.e., the list that is active by default).
* Allowing or blocking messages based on JID, group, or subscription type (or globally).
* Allowing or blocking inbound presence notifications based on JID, group, or subscription type (or globally).
* Allowing or blocking outbound presence notifications based on JID, group, or subscription type (or globally).
* Allowing or blocking IQ stanzas based on JID, group, or subscription type (or globally).
* Allowing or blocking all communications based on JID, group, or subscription type (or globally).
How can I use it?
-----------------
The API implementation releases three main public classes:
* `PrivacyListManager`: this is the main API class to retrieve and handle server privacy lists.
* `PrivacyList`: witch represents one privacy list, with a name, a set of privacy items. For example, the list with visible or invisible.
* `PrivacyItem`: block or allow one aspect of privacy. For example, to allow my friend to see my presence.
1. Right from the start, a client MAY **get his/her privacy list** that is stored in the server:
```
// Create a privacy manager for the current connection._
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
// Retrieve server privacy lists_
PrivacyList[] lists = privacyManager.getPrivacyLists();
```
Now the client is able to show every `PrivacyItem` of the server and also for
every list if it is active, default or none of them. The client is a listener
of privacy changes.
2. In order to **add a new list in the server**, the client MAY implement something like:
```
// 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);
```
3. To **modify an existent list**, the client code MAY be like:
```
// 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);
```
Notice `items` was defined at the example 2 and MUST contain all the elements
in the list (not the "delta").
4. In order to **delete an existing list**, the client MAY perform something like:
```
// 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);
```
5. In order to **decline the use of an active list**, the client MAY perform something like:
```
// Get the privacy manager for the current connection._
PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(myConnection);
// Decline the use of the active list._
privacyManager.declineActiveList();
```
6. In order to **decline the use of a default list**, the client MAY perform something like:
```
// 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);
```
Copyright (C) Jive Software 2002-2008

View file

@ -1,30 +0,0 @@
<html>
<head>
<title>Private Data</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">Private Data</div><p>
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:
<pre>
&lt;color xmlns="http://example.com/xmpp/color"&gt;
&lt;favorite&gt;blue&lt;/blue&gt;
&lt;leastFavorite&gt;puce&lt;/leastFavorite&gt;
&lt;/color&gt;
</pre><p>
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0049.html">XEP-49</a>
<hr>
<em>More coming soon.</em>
</body>
</html>

View file

@ -0,0 +1,17 @@
Private Data
============
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](http://www.xmpp.org/extensions/xep-0049.html)
_More coming soon._

View file

@ -1,123 +0,0 @@
<html>
<head>
<title>Smack: Packet Properties - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">
Packet Properties
</div>
<p>
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).
</p>
<p class="subheader">
Using the API
</p>
<p>
All major objects have property support, such as Message objects. The following code
demonstrates how to set properties:
</p>
<div class="code"><pre>
Message message = chat.createMessage();
JivePropertiesExtension jpe = new JivePropertiesExtension();
<font color="gray"><i>// Add a Color object as a property.</i></font>
jpe.setProperty(<font color="blue">"favoriteColor"</font>, new Color(0, 0, 255));
<font color="gray"><i>// Add an int as a property.</i></font>
jpe.setProperty(<font color="blue">"favoriteNumber"</font>, 4);
<font color="gray"><i>// Add the JivePropertiesExtension to the message packet</i></font>
message.addPacketExtension(jpe);
chat.sendMessage(message);
</pre></div>
<p>
Getting those same properties would use the following code:
</p>
<div class="code"><pre>
Message message = chat.nextMessage();
<font color="gray"><i>// Get the JivePropertiesExtension</i></font>
JivePropertiesExtension jpe = message.getExtension(JivePropertiesExtension.NAMESPACE);
<font color="gray"><i>// Get a Color object property.</i></font>
Color favoriteColor = (Color)jpe.getProperty(<font color="blue">"favoriteColor"</font>);
<font color="gray"><i>// 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.</i></font>
int favoriteNumber = ((Integer)jpe.getProperty(<font color="blue">"favoriteNumber"</font>)).intValue();
</pre></div>
<p>
For convenience <code>JivePropertiesManager</code> contains two helper
methods namely <code>addProperty(Packet packet, String name, Object
value)</code> and
<code>getProperty(Packet packet, String name)</code>.
</p>
<p class="subheader">
Objects as Properties
</p>
<p>
Using objects as property values is a very powerful and easy way to exchange data. However,
you should keep the following in mind:
</p>
<ul>
<li>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.
<li>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.
<li>Serialized objects can potentially be quite large, which will use more bandwidth and
server resources.
</ul>
<p class="subheader">
XML Format
</p>
<p>
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):
</p>
<div class="code"><pre>
<font color="gray"><i>&lt;!-- All properties are in a x block. --&gt;</i></font>
&lt;properties xmlns="http://www.jivesoftware.com/xmlns/xmpp/properties"&gt;
<font color="gray"><i>&lt;!-- First, a property named "prop1" that's an integer. --&gt;</i></font>
&lt;property&gt;
&lt;name&gt;prop1&lt;/name&gt;
&lt;value type="integer"&gt;123&lt;/value&gt;
&lt;property&gt;
<font color="gray"><i>&lt;!-- Next, a Java object that's been serialized and then converted
from binary data to base-64 encoded text. --&gt;</i></font>
&lt;property&gt;
&lt;name&gt;blah2&lt;/name&gt;
&lt;value type="java-object"&gt;adf612fna9nab&lt;/value&gt;
&lt;property&gt;
&lt;/properties&gt;
</pre></div>
<p>
The currently supported types are: <tt>integer</tt>, <tt>long</tt>, <tt>float</tt>,
<tt>double</tt>, <tt>boolean</tt>, <tt>string</tt>, and <tt>java-object</tt>.
</p>
<div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

View file

@ -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):
<!-- 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`.
Copyright (C) Jive Software 2002-2008

View file

@ -1,448 +0,0 @@
<html>
<head>
<title>PubSub</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">Pubsub</div><p>
This section details the usage of an API designed for accessing an XMPP based
implementation of a <a href="http://en.wikipedia.org/wiki/Publish/subscribe">publish and subscribe</a>
based messaging system. It has functionality for creation, configuration of,
subscription and publishing to pubsub nodes.<p>
<ul>
<li><a href="#create">Node creation and configuration</a></li>
<li><a href="#publish">Publishing to a node</a></li>
<li><a href="#subscribe">Receiving pubsub messages</a></li>
<li><a href="#retrieve">Retrieving persisted pubsub messages</a></li>
<li><a href="#discopubsub">Discover pubsub information</a></li>
</ul>
<b>XEP related:</b> <a href="http://xmpp.org/extensions/xep-0060.html">XEP-0060</a>
<hr>
<div class="subheader"><a name="create">Node creation and configuration</a></div><p>
<b>Description</b><p>
Allowed users may create and configure pubsub nodes. There are two types of nodes that can be created,
leaf nodes and collection nodes.
<li>Leaf Nodes - contains only messages</li>
<li>Collection Nodes - contains only nodes (both Leaf and Collection are allowed), but no messages</li>
The current version of this API only supports Leaf Nodes.
There are many configuration options available for nodes, but the two main options are whether the node
is <b>persistent</b> or not and whether it will deliver payload or not.</p>
<b>Usage</b><p>
In order to create a node you will need to first create an instance of <i><b>PubSubManager</b></i>. There
are several options for node creation which range from creating an instant node, default configuration, or
a fully configured node.</p><p>
<b>Examples</b><p>
Create an instant node: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Create the node</font>
LeafNode leaf = mgr.createNode();
</pre>
</blockquote>
Create a node with default configuration and then configure it: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Create the node</font>
LeafNode leaf = mgr.createNode(<font color="#0000FF">"testNode"</font>);
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);
</pre>
</blockquote>
Create and configure a node: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Create the node</font>
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(<font color="#0000FF">"testNode"</font>, form);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="publish">Publishing to a node</a></div><p>
<b>Description</b><p>
This section deals with the <b>publish</b> 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.
</p>
<b>Usage</b><p>
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.
</p>
<b>Examples</b><p>
In this example we publish an item to a node that does not take payload: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get the node</font>
LeafNode node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
<font color="#3f7f5f">// Publish an Item, let service set the id</font>
node.send(new Item());
<font color="#3f7f5f">// Publish an Item with the specified id</font>
node.send(new Item(<font color="#0000FF">"123abc"</font>));
</pre>
</blockquote>
In this example we publish an item to a node that does take payload: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get the node</font>
LeafNode node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
<font color="#3f7f5f">// Publish an Item with payload</font>
node.send(new PayloadItem<SimplePayload>(<font color="#0000FF">"test"</font> + System.currentTimeMillis(),
new SimplePayload(<font color="#0000FF">"book"</font>, <font color="#0000FF">"pubsub:test:book"</font>, <font color="#0000FF">"<book xmlns='pubsub:test:book'><title>Two Towers</title></book>"</font>)));
</pre>
</blockquote>
<div class="subheader"><a name="subscribe">Receiving pubsub messages</a></div><p>
<b>Description</b><p>
This section deals with the <b>subscribe</b> 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.
</p>
<b>Usage</b><p>
To get messages asynchronously when items are published to a node, you will have to
<li>Get a node.</li>
<li>Create and register a listener.</li>
<li>Subscribe to the node.</li>
<p>
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.
</p></p>
<b>Examples</b><p>
In this example we can see how to create a listener and register it and then subscribe for
messages. <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get the node</font>
LeafNode node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
node.addItemEventListener(new ItemEventCoordinator&ltItem&gt());
node.subscribe(myJid);
</pre>
</blockquote>
Where the listener is defined like so:
<blockquote>
<pre>
class ItemEventCoordinator <T extends Item> implements ItemEventListener<T>
{
@Override
public void handlePublishedItems(ItemPublishEvent<T> items)
{
System.out.println(<font color="#0000FF">"Item count: "</font> + items.getItems().size());
System.out.println(items);
}
}
</pre>
</blockquote>
In addition to receiving published items, there are notifications for several other
events that occur on a node as well.
<li>Deleting items or purging all items from a node</li>
<li>Changing the node configuration</li>
<p>
In this example we can see how to create a listener, register it and then subscribe for
item deletion messages. <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get the node</font>
LeafNode node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
node.addItemDeleteListener(new ItemDeleteCoordinator&ltItem&gt());
node.subscribe(myJid);
node.deleteItem(<font color="#0000FF">"id_one"</font>);
</pre>
</blockquote>
Where the handler is defined like so:
<blockquote>
<pre>
class ItemDeleteCoordinator implements ItemDeleteListener<T>
{
@Override
public void handleDeletedItems(ItemDeleteEvent items)
{
System.out.println(<font color="#0000FF">"Item count: "</font> + items.getItemIds().size());
System.out.println(items);
}
@Override
public void handlePurge()
{
System.out.println(<font color="#0000FF">"All items have been deleted from node"</font>);
}
}
</pre>
</blockquote>
In this example we can see how to create a listener, register it and then subscribe for
node configuration messages. <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get the node</font>
Node node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
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);
</pre>
</blockquote>
Where the handler is defined like so:
<blockquote>
<pre>
class NodeConfigCoordinator implements NodeConfigListener<T>
{
@Override
public void handleNodeConfiguration(ConfigurationEvent config)
{
System.out.println(<font color="#0000FF">"New configuration"</font>);
System.out.println(config.getConfiguration());
}
}
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="retrieve">Retrieving persisted pubsub messages</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
To synchronously retrieve existing items from a persistent node, you will have to get an instance
of a <i><b>LeafNode</b></i> and call one of the retrieve methods.
<p>
<b>Examples</b><p>
In this example we can see how to retrieve the existing items from a node: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get the node</font>
LeafNode node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
Collection&lt? extends Item&gt items = node.getItems();
</pre>
</blockquote>
In this example we can see how to retrieve the last N existing items: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get the node</font>
LeafNode node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
List&lt? extends Item&gt items = node.getItems(100);
</pre>
</blockquote>
In this example we can see how to retrieve the specified existing items: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get the node</font>
LeafNode node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
Collection&ltString&gt ids = new ArrayList&ltString&gt(3);
ids.add("1");
ids.add("3");
ids.add("4");
List&lt? extends Item&gt items = node.getItems(ids);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="discopubsub">Discover pubsub information</a></div><p>
<b>Description</b><p>
A user may want to query a server or node for a variety of pubsub related information.</p>
<b>Usage</b><p>
To retrieve information, a user will simply use either the <i><b>PubSubManager</b></i>
or <i><b>Node</b></i> classes depending on what type of information is required.
<b>Examples</b><p>
In this example we can see how to get pubsub capabilities: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get the pubsub features that are supported</font>
DiscoverInfo supportedFeatures = mgr.getSupportedFeatures();
</pre>
</blockquote>
In this example we can see how to get pubsub subscriptions for all nodes: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get all the subscriptions in the pubsub service</font>
List&ltSubscription&gt subscriptions = mgr.getSubscriptions();
</pre>
</blockquote>
In this example we can see how to get all affiliations for the users bare JID on the pubsub service: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
<font color="#3f7f5f">// Get the affiliations for the users bare JID</font>
List&ltAffiliation&gt affiliations = mgr.getAffiliations();
</pre>
</blockquote>
In this example we can see how to get information about the node: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
Node node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
<font color="#3f7f5f">// Get the node information</font>
DiscoverInfo nodeInfo = node.discoverInfo();
</pre>
</blockquote>
In this example we can see how to discover the node items: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
Node node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
<font color="#3f7f5f">// Discover the node items</font>
DiscoverItems nodeItems = node.discoverItems();
</pre>
</blockquote>
In this example we can see how to get node subscriptions: <br>
<blockquote>
<pre>
<font color="#3f7f5f">// Create a pubsub manager using an existing XMPPConnection</font>
PubSubManager mgr = new PubSubManager(con);
Node node = mgr.getNode(<font color="#0000FF">"testNode"</font>);
<font color="#3f7f5f">// Discover the node subscriptions</font>
List&ltSubscription&gt subscriptions = node.getSubscriptions();
</pre>
</blockquote>
<hr>
</body>
</html>

View file

@ -0,0 +1,402 @@
Pubsub
======
This section details the usage of an API designed for accessing an XMPP based
implementation of a [publish and
subscribe](http://en.wikipedia.org/wiki/Publish/subscribe) based messaging
system. It has functionality for creation, configuration of, subscription and
publishing to pubsub nodes.
* Node creation and configuration
* Publishing to a node
* Receiving pubsub messages
* Retrieving persisted pubsub messages
* Discover pubsub information
**XEP related:** [XEP-0060](http://xmpp.org/extensions/xep-0060.html)
Node creation and configuration
-------------------------------
### Description
Allowed users may create and configure pubsub nodes. There are two types of
nodes that can be created, leaf nodes and collection nodes.
* Leaf Nodes - contains only messages
* Collection Nodes - contains only nodes (both Leaf and Collection are allowed), but no messages
The current version of this API only supports Leaf Nodes. There are many
configuration options available for nodes, but the two main options are
whether the node is **persistent** or not and whether it will deliver payload
or not.
### Usage
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 pubsub manager using an existing XMPPConnection
PubSubManager mgr = new PubSubManager(con);
// Create the node
LeafNode leaf = mgr.createNode();
```
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("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 and configure a node:
```
// 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);
```
Publishing to a node
--------------------
**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:
```
// 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"));
```
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 with payload
node.send(new PayloadItem("test" + System.currentTimeMillis(),
new SimplePayload("book", "pubsub:test:book", "Two Towers")));
```
Receiving pubsub messages
-------------------------
**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
* Get a node.
* Create and register a listener.
* Subscribe to the node.
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.
```
// 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&ltItem;>());
node.subscribe(myJid);
```
Where the listener is defined like so:
```
class ItemEventCoordinator implements ItemEventListener {
@Override
public void handlePublishedItems(ItemPublishEvent items) {
System.out.println("Item count: " + System.out.println(items);
}
}
```
In addition to receiving published items, there are notifications for several
other events that occur on a node as well.
* Deleting items or purging all items from a node
* Changing the node configuration
In this example we can see how to create a listener, register it and then
subscribe for item deletion messages.
```
// 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&ltItem;>());
node.subscribe(myJid);
node.deleteItem("id_one");
```
Where the handler is defined like so:
```
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");
}
}
```
In this example we can see how to create a listener, register it and then
subscribe for node configuration messages.
```
// 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);
```
Where the handler is defined like so:
```
class NodeConfigCoordinator implements NodeConfigListener {
@Override
public void handleNodeConfiguration(ConfigurationEvent config) {
System.out.println("New configuration");
System.out.println(config.getConfiguration());
}
}
```
Retrieving persisted pubsub messages
------------------------------------
**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:
```
// 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 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");
List<? extends Item> items = node.getItems(100);
```
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");
Collection&ltString;> ids = new ArrayList&ltString;>(3);
ids.add("1");
ids.add("3");
ids.add("4");
List<? extends Item> items = node.getItems(ids);
```
Discover pubsub information
---------------------------
**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:
```
// 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 pubsub subscriptions for all nodes:
```
// Create a pubsub manager using an existing XMPPConnection
PubSubManager mgr = new PubSubManager(con);
// Get all the subscriptions in the pubsub service
List&ltSubscription;> subscriptions = mgr.getSubscriptions();
```
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 the affiliations for the users bare JID
List&ltAffiliation;> affiliations = mgr.getAffiliations();
```
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);
Node node = mgr.getNode("testNode");
// Get the node information
DiscoverInfo nodeInfo = node.discoverInfo();
```
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");
// Discover the node items
DiscoverItems nodeItems = node.discoverItems();
```
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 subscriptions
List&ltSubscription;> subscriptions = node.getSubscriptions();
```

View file

@ -1,179 +0,0 @@
<html>
<head>
<title>Roster Item Exchange</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">Roster Item Exchange</div><p>
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.
<p>Follow these links to learn how to send and receive roster items:</p>
<ul>
<li><a href="#riesendroster">Send a complete roster</a></li>
<li><a href="#riesendgroup">Send a roster's group</a></li>
<li><a href="#riesendentry">Send a roster's entry</a></li>
<li><a href="#riercventry">Receive roster entries</a></li>
</ul>
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0093.html">XEP-93</a>
<hr>
<div class="subheader"><a name="riesendroster">Send a entire roster</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
Create an instance of <i><b>RosterExchangeManager</b></i> and use the <b>#send(Roster, String)</b>
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.</p>
<b>Example</b><p>
In this example we can see how user1 sends his roster to user2.
<blockquote>
<pre> <font color="#3f7f5f">// Connect to the server and log in</font>
conn1 = new XMPPTCPConnection(host);
conn1.login(server_user1, pass1);
<font color="#3f7f5f">// Create a new roster exchange manager on conn1</font>
RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1);
<font color="#3f7f5f">// Send user1's roster to user2</font>
rosterExchangeManager.send(conn1.getRoster(), user2);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="riesendgroup">Send a roster group</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
Create an instance of <i><b>RosterExchangeManager</b></i> and use the <b>#send(RosterGroup, String)</b>
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.</p>
<b>Example</b><p>
In this example we can see how user1 sends his roster groups to user2.
<blockquote>
<pre> <font color="#3f7f5f">// Connect to the server and log in</font>
conn1 = new XMPPTCPConnection(host);
conn1.login(server_user1, pass1);
<font color="#3f7f5f">// Create a new roster exchange manager on conn1</font>
RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1);
<font color="#3f7f5f">// Send user1's RosterGroups to user2</font>
for (Iterator it = conn1.getRoster().getGroups(); it.hasNext(); )
rosterExchangeManager.send((RosterGroup)it.next(), user2);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="riesendentry">Send a roster entry</a></div><p>
<b>Description</b><p>
Sometimes you may need to send a single roster entry to another XMPP client. Smack also lets you send
items at this granularity level.</p>
<b>Usage</b><p>
Create an instance of <i><b>RosterExchangeManager</b></i> and use the <b>#send(RosterEntry, String)</b>
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.</p>
<b>Example</b><p>
In this example we can see how user1 sends a roster entry to user2.
<blockquote>
<pre> <font color="#3f7f5f">// Connect to the server and log in</font>
conn1 = new XMPPTCPConnection(host);
conn1.login(server_user1, pass1);
<font color="#3f7f5f">// Create a new roster exchange manager on conn1</font>
RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1);
<font color="#3f7f5f">// Send a roster entry (any) to user2</font>
rosterExchangeManager1.send((RosterEntry)conn1.getRoster().getEntries().next(), user2);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="riercventry">Receive roster entries</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
<ol>
<li>Create a class that implements the <i><b>RosterExchangeListener</b></i> interface.</li>
<li>Implement the method <b>entriesReceived(String, Iterator)</b> that will be called when new entries
are received with custom logic.</li>
<li>Add the listener to the <i>RosterExchangeManager</i> that works on the desired <i>XMPPConnection</i>.</li>
</ol></p>
<b>Example</b><p>
In this example we can see how user1 sends a roster entry to user2 and user2 adds the received
entries to his roster.
<blockquote>
<pre> <font color="#3f7f5f">// Connect to the server and log in the users</font>
conn1 = new XMPPTCPConnection(host);
conn1.login(server_user1, pass1);
conn2 = new XMPPTCPConnection(host);
conn2.login(server_user2, pass2);
final Roster user2_roster = conn2.getRoster();
<font color="#3f7f5f">// Create a RosterExchangeManager that will help user2 to listen and accept
the entries received</font>
RosterExchangeManager rosterExchangeManager2 = new RosterExchangeManager(conn2);
<font color="#3f7f5f">// Create a RosterExchangeListener that will iterate over the received roster entries</font>
RosterExchangeListener rosterExchangeListener = new RosterExchangeListener() {
public void entriesReceived(String from, Iterator remoteRosterEntries) {
while (remoteRosterEntries.hasNext()) {
try {
<font color="#3f7f5f">// Get the received entry</font>
RemoteRosterEntry remoteRosterEntry = (RemoteRosterEntry) remoteRosterEntries.next();
<font color="#3f7f5f">// Display the remote entry on the console</font>
System.out.println(remoteRosterEntry);
<font color="#3f7f5f">// Add the entry to the user2's roster</font>
user2_roster.createEntry(
remoteRosterEntry.getUser(),
remoteRosterEntry.getName(),
remoteRosterEntry.getGroupArrayNames());
}
catch (XMPPException e) {
e.printStackTrace();
}
}
}
};
<font color="#3f7f5f">// Add the RosterExchangeListener to the RosterExchangeManager that user2 is using</font>
rosterExchangeManager2.addRosterListener(rosterExchangeListener);
<font color="#3f7f5f">// Create a RosterExchangeManager that will help user1 to send his roster</font>
RosterExchangeManager rosterExchangeManager1 = new RosterExchangeManager(conn1);
<font color="#3f7f5f">// Send user1's roster to user2</font>
rosterExchangeManager1.send(conn1.getRoster(), user2);
</pre>
</blockquote>
</body>
</html>

View file

@ -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);
```

View file

@ -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;
}

View file

@ -1,22 +0,0 @@
<html>
<head>
<title>Time</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">Entity Time Exchange</div><p>
Supports a protocol that XMPP clients use to exchange their respective local
times and time zones.<p>
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0090.html">XEP-90</a>
<hr>
<em>More coming soon.</em>
</body>
</html>

View file

@ -0,0 +1,10 @@
Entity Time Exchange
====================
Supports a protocol that XMPP clients use to exchange their respective local
times and time zones.
**XEP related:** [XEP-90](http://www.xmpp.org/extensions/xep-0090.html)
_More coming soon._

View file

@ -1,32 +0,0 @@
<html>
<head>
<title>Smack Extensions User Manual</title>
<link rel="stylesheet" type="text/css" href="style.css" />
<base target="mainFrame">
</head>
<body>
<a href="intro.html">Introduction</a><p>
<div class="subheader">Smack Extensions</div><p>
<a href="privatedata.html">Private Data</a><br>
<a href="xhtml.html">XHTML Messages</a><br>
<a href="messageevents.html">Message Events</a><br>
<a href="dataforms.html">Data Forms</a><br>
<a href="muc.html">Multi User Chat</a><br>
<a href="rosterexchange.html">Roster Item Exchange</a><br>
<a href="time.html">Time Exchange</a><br>
<a href="invitation.html">Group Chat Invitations</a><br>
<a href="disco.html">Service Discovery</a><br>
<a href="filetransfer.html">File Transfer</a><br>
<a href="pubsub.html">PubSub</a><br>
<a href="caps.html">Entity Capabilities</a><br>
<a href="privacy.html">Privacy</a><br>
<a href="hoxt.html">HTTP over XMPP</a><br>
<a href="properties.html">JiveProperties</a>
</p>
</body>
</html>

View file

@ -1,200 +0,0 @@
<html>
<head>
<title>XHTML Support</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">XHTML Messages</div><p>
Provides the ability to send and receive formatted messages using XHTML.
<p>Follow these links to learn how to compose, send, receive and discover support for
XHTML messages:</p>
<ul>
<li><a href="#xhtmlcompose">Compose an XHTML Message</a></li>
<li><a href="#xhtmlsend">Send an XHTML Message</a></li>
<li><a href="#xhtmlreceive">Receive an XHTML Message</a></li>
<li><a href="#xhtmldiscover">Discover support for XHTML Messages</a></li>
</ul>
<b>XEP related:</b> <a href="http://www.xmpp.org/extensions/xep-0071.html">XEP-71</a>
<hr>
<div class="subheader"><a name="xhtmlcompose">Compose an XHTML Message</a></div><p>
<b>Description</b><p>
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.</p>
<p>
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.</p>
<b>Usage</b><p>
Create an instance of <i><b>XHTMLText</b></i> 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 <b>#append(String textToAppend)</b>.</p>
<p>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
<b>#addBody(Message message, String body)</b> to the <i><b>XHTMLManager</b></i> class where <i>message</i>
is the message that will receive the XHTML body and <i>body</i> is the string to add as an XHTML body to
the message.</b></p>
<b>Example</b><p>
In this example we can see how to compose the following XHTML message: <br>
<font color="#0000FF">&lt;body&gt;&lt;p style='font-size:large'&gt;Hey John, this is my new &lt;span
style='color:green'&gt;green&lt;/span&gt;&lt;em&gt;!!!!&lt;/em&gt;&lt;/p&gt;&lt;/body&gt;</font>
<blockquote>
<pre> <font color="#3f7f5f">// Create a message to send</font>
Message msg = chat.createMessage();
msg.setSubject(<font color="#0000FF">"Any subject you want"</font>);
msg.setBody(<font color="#0000FF">"Hey John, this is my new green!!!!"</font>);
<font color="#3f7f5f">// Create an XHTMLText to send with the message</font>
XHTMLText xhtmlText = new XHTMLText(null, null);
xhtmlText.appendOpenParagraphTag(<font color="#0000FF">"font-size:large"</font>);
xhtmlText.append(<font color="#0000FF">"Hey John, this is my new "</font>);
xhtmlText.appendOpenSpanTag(<font color="#0000FF">"color:green"</font>);
xhtmlText.append(<font color="#0000FF">"green"</font>);
xhtmlText.appendCloseSpanTag();
xhtmlText.appendOpenEmTag();
xhtmlText.append(<font color="#0000FF">"!!!!"</font>);
xhtmlText.appendCloseEmTag();
xhtmlText.appendCloseParagraphTag();
<font color="#3f7f5f">// Add the XHTML text to the message</font>
XHTMLManager.addBody(msg, xhtmlText.toString());
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="xhtmlsend">Send an XHTML Message</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
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 <b>#send(Message)</b> of <i><b>Chat</b></i> or you can use
the message <b>#send(Packet)</b> of <i><b>XMPPConnection</b></i>.</p>
<b>Example</b><p>
In this example we can see how to send a message with XHTML content as part of a chat.
<blockquote>
<pre> <font color="#3f7f5f">// Create a message to send</font>
Message msg = chat.createMessage();
<font color="#3f7f5f">// Obtain the XHTML text to send from somewhere</font>
String xhtmlBody = getXHTMLTextToSend();
<font color="#3f7f5f">// Add the XHTML text to the message</font>
XHTMLManager.addBody(msg, xhtmlBody);
<font color="#3f7f5f">// Send the message that contains the XHTML</font>
chat.sendMessage(msg);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="xhtmlreceive">Receive an XHTML Message</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
To get the XHTML bodies of a given message just send the message <b>#getBodies(Message)</b>
to the class <i><b>XHTMLManager</b></i>. The answer of this message will be an
<i><b>Iterator</b></i> with the different XHTML bodies of the message or null if none.</p>
<b>Example</b><p>
In this example we can see how to create a PacketListener that obtains the XHTML bodies of any received message.
<blockquote>
<pre> <font color="#3f7f5f">// Create a listener for the chat and display any XHTML content</font>
PacketListener packetListener = new PacketListener() {
public void processPacket(Packet packet) {
Message message = (Message) packet;
<font color="#3f7f5f">// Obtain the XHTML bodies of the message</font>
Iterator it = XHTMLManager.getBodies(message);
if (it != null) {
<font color="#3f7f5f">// Display the bodies on the console</font>
while (it.hasNext()) {
String body = (String) it.next();
System.out.println(body);
}
}
};
chat.addMessageListener(packetListener);
</pre>
</blockquote>
<hr>
<div class="subheader"><a name="xhtmldiscover">Discover support for XHTML Messages</a></div><p>
<b>Description</b><p>
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.</p>
<b>Usage</b><p>
In order to discover if a remote user supports XHTML messages send <b>#isServiceEnabled(XMPPConnection
connection, String userID)</b> to the class <i><b>XHTMLManager</b></i> 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.</p>
<b>Example</b><p>
In this example we can see how to discover if a remote user supports XHTML Messages.
<blockquote>
<pre> Message msg = chat.createMessage();
<font color="#3f7f5f">// Include a normal body in the message</font>
msg.setBody(getTextToSend());
<font color="#3f7f5f">// Check if the other user supports XHTML messages</font>
if (XHTMLManager.isServiceEnabled(connection, chat.getParticipant())) {
<font color="#3f7f5f">// Obtain the XHTML text to send from somewhere</font>
String xhtmlBody = getXHTMLTextToSend();
<font color="#3f7f5f">// Include an XHTML body in the message</font>
XHTMLManager.addBody(msg, xhtmlBody);
}
<font color="#3f7f5f">// Send the message</font>
chat.sendMessage(msg);
</pre>
</blockquote>
</body>
</html>

View file

@ -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:
```
<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());
```
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);
```

View file

@ -1,152 +0,0 @@
<html>
<head>
<title>Smack: Getting Started - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">
Smack: Getting Started
</div>
<div class="nav">
&laquo; <a href="index.html">Table of Contents</a>
</div>
<p>
This document will introduce you to the Smack API and provide an overview of
important classes and concepts.
</p>
<p class="subheader">
JAR Files and Requirements
</p>
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:
<ul>
<li><tt>smack-core.jar</tt> -- provides core XMPP functionality. All XMPP features that are
part of the XMPP RFCs are included.</li>
<li><tt>smack-extensions.jar</tt> -- 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 <a href="extensions/index.html">extensions manual</a>.</li>
<li><tt>smack-experimental.jar</tt> -- support for experimental extensions (XEPs) defined
by the XMPP Standards Foundation. The API and functionality of those extensions should be
considered as unstable.</li>
<li><tt>smack-legacy.jar</tt> -- support for legacy extensions (XEPs) defined
by the XMPP Standards Foundation.</li>
<li><tt>smack-bosh.jar</tt> -- support for BOSH (XEP-0124). This code should be considered
as beta.</li>
<li><tt>smack-jingle.jar</tt> -- support for Jingle. This code is old and currenlty
unmaintained.</li>
<li><tt>smack-resolver-dnsjava.jar</tt> -- support for resolving DNS SRV records with the
help of dnsjava. Ideal for platforms that do not support the javax.naming API.</li>
<li><tt>smack-resolver-javax.jar</tt> -- support for resolving DNS SRV records with the
javax namespace API.</li>
<li><tt>smack-debug.jar</tt> -- an enhanced GUI debugger for protocol traffic. It will
automatically be used when found in the classpath and when <a href="debugging.html">debugging</a>
is enabled.</li>
</ul>
<p class="subheader">Configuration</p>
Smack has an initialization process that involves 2 phases.
<ul>
<li>Initializing system properties - Initializing all the system properties accessible through the class
<b>SmackConfiguration</b>. These properties are retrieve by the <i>getXXX</i> methods on that class.
<li>Initializing startup classes - Initializing any classes meant to be active at startup by instantiating
the class, and then calling the <i>initialize</i> method on that class if it extends <b>SmackInitializer</b>.
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.
</ul>
<p>
Initialization is accomplished via a configuration file. By default,
Smack will load the one embedded in the Smack jar
at <i>org.jivesoftware.smack/smack-config.xml</i>. 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.
</p>
<p class="subheader">
Establishing a Connection
</p>
The classes subclassing <tt>AbstractXMPPConnection</tt> are used to
create a connection to an XMPP server. Below are code examples for
making a connection:<p>
<div class="code">
<pre>
<font color="gray"><i>// Create a connection to the jabber.org server.</i></font>
AbstractXMPPConnection conn1 = <font color="navy"><b>new</b></font> XMPPTCPConnection(<font color="green">"jabber.org"</font>);
conn1.connect();
<font color="gray"><i>// Create a connection to the jabber.org server on a specific port.</i></font>
ConnectionConfiguration config = new ConnectionConfiguration(<font color="green">"jabber.org"</font>, 5222);
AbstractXMPPConnection conn2 = <font color="navy"><b>new</b></font> XMPPTCPConnection(config);
conn2.connect();
</pre></div>
<p>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
<a href="connections.html">XMPPConnection Management</a> for full details.</p>
<p>Once you've created a connection, you should login using a username and password
with the <tt>AbstractXMPPConnection.login(String username, String password)</tt> method.
Once you've logged in, you can being chatting with other users by creating
new <tt>Chat</tt> or <tt>GroupChat</tt> objects.
<p class="subheader">
Working with the Roster
</p>
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.<p>
Retrieve the roster using the <tt>XMPPConnection.getRoster()</tt> 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.
<p class="subheader">
Reading and Writing Packets
</p>
Each message to the XMPP server from a client is called a packet and is
sent as XML. The <tt>org.jivesoftware.smack.packet</tt> package contains
classes that encapsulate the three different basic packet types allowed by
XMPP (message, presence, and IQ). Classes such as <tt>Chat</tt> and <tt>GroupChat</tt>
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":<p>
<div class="code">
<pre>
<font color="gray"><i>// Create a new presence. Pass in false to indicate we're unavailable.</i></font>
Presence presence = new Presence(Presence.Type.unavailable);
presence.setStatus(<font color="green">"Gone fishing"</font>);
<font color="gray"><i>// Send the packet (assume we have a AbstractXMPPConnection instance called "con").</i></font>
con.sendPacket(presence);
</pre></div>
<p>
Smack provides two ways to read incoming packets: <tt>PacketListener</tt>, and
<tt>PacketCollector</tt>. Both use <tt>PacketFilter</tt> 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.
<p><div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

View file

@ -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

View file

@ -1,35 +0,0 @@
<html>
<head>
<title>Smack Documentation - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<font size="4"><b>Smack Documentation</b></font>
<p>
<strong>Contents:</strong>
</p>
<ul>
<li><a href="overview.html">Overview</a>
<li><a href="gettingstarted.html">Getting Started Guide</a>
<li><a href="connections.html">Managing Connections</a></li>
<li><a href="messaging.html">Messaging Basics</a>
<li><a href="roster.html">Roster and Presence</a>
<li><a href="processing.html">Processing Incoming Packets</a>
<li><a href="providers.html">Provider Architecture</a>
<li><a href="debugging.html">Debugging with Smack</a>
<p>
<li><a href="extensions/index.html">Smack Extensions Manual</a>
<p>
<li><a href="legacy/index.html">Smack Legacy Code Manual</a>
</ul>
<div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

14
documentation/index.md Normal file
View file

@ -0,0 +1,14 @@
**Smack Documentation**
**Contents:**
* [Overview](overview.html)
* [Getting Started Guide](gettingstarted.html)
* [Managing Connections](connections.html)
* [Messaging Basics](messaging.html)
* [Roster and Presence](roster.html)
* [Processing Incoming Packets](processing.html)
* [Provider Architecture](providers.html)
* [Debugging with Smack](debugging.html)
* [Smack Extensions Manual](extensions/index.html)

View file

@ -1,128 +0,0 @@
<html>
<head>
<title>Smack: Chat - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<div class="header">
Messaging using Chats
</div>
<div class="nav">
&laquo; <a href="index.html">Table of Contents</a>
</div>
<p>
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 <tt>org.jivesoftware.smack.Chat</tt> class.
</p>
<p class="subheader">
Chat
</p>
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:<p>
<div class="code"><pre><font color="gray"><i>// Assume we've created a XMPPConnection name "connection".</i></font>
ChatManager chatmanager = connection.getChatManager();
Chat newChat = chatmanager.createChat(<font
color="green">"jsmith@jivesoftware.com"</font>, new MessageListener() {
public void processMessage(Chat chat, Message message) {
System.out.println(<font color="green">"Received message: "</font> + message);
}
});
try {
newChat.sendMessage(<font color="green">"Howdy!"</font>);
}
catch (XMPPException e) {
System.out.println(<font color="green">"Error Delivering block"</font>);
}
</pre>
</div>
<p>
The <tt>Chat.sendMessage(String)</tt> 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
<tt>Chat.createMessage()</tt> and <tt>Chat.sendMessage(Message)</tt> methods, as in the
following code snippet:
<p>
<div class="code"><pre>
Message newMessage = new Message();
newMessage.setBody(<font color="green">"Howdy!"</font>);
message.setProperty(<font color="green">"favoriteColor"</font>, <font color="green">"red"</font>);
newChat.sendMessage(newMessage);
</pre>
</div>
<p>
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.
<p>
<div class="code"><pre>
<font color="gray"><i> // Assume a MessageListener we've setup with a chat.</i></font>
public void processMessage(Chat chat, Message message) {
<font color="gray"><i>// Send back the same text the other user sent us.</i></font>
chat.sendMessage(message.getBody());
}
</pre>
</div>
<p class="subheader">
Incoming Chat
</p>
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.
</br>
</br>
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.<p>
<div class="code"><pre><font color="gray"><i>// Assume we've created a XMPPConnection name "connection".</i></font>
ChatManager chatmanager = connection.getChatManager().addChatListener(
new ChatManagerListener() {
@Override
public void chatCreated(Chat chat, boolean createdLocally)
{
if (!createdLocally)
chat.addMessageListener(new MyNewMessageListener());;
}
});
</pre>
</div>
In addition to thread based chat messages, there are some clients that
do not send a thread id as part of the chat. To handle this scenario,
Smack will attempt match the incoming messages to the best fit existing
chat, based on the JID. It will attempt to find a chat with the same full
JID, failing that, it will try the base JID. If no existing chat to the
user can found, then a new one is created.
<p>
<br clear="all"/><br><br>
<div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

View file

@ -0,0 +1,94 @@
Messaging using Chats
=====================
[Back](index.html)
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());;
}
});
```
In addition to thread based chat messages, there are some clients that do not
send a thread id as part of the chat. To handle this scenario, Smack will
attempt match the incoming messages to the best fit existing chat, based on
the JID. It will attempt to find a chat with the same full JID, failing that,
it will try the base JID. If no existing chat to the user can found, then a
new one is created.
Copyright (C) Jive Software 2002-2008

View file

@ -1,79 +0,0 @@
<html>
<head>
<title>Smack: Overview - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">
Smack Overview
</div>
<div class="nav">
&laquo; <a href="index.html">Table of Contents</a>
</div>
<p>
Smack is a library for communicating with XMPP servers to perform real-time communications, including
instant messaging and group chat.<p>
<p class="subheader">
Smack Key Advantages
</p>
<ul>
<li>Extremely simple to use, yet powerful API. Sending a text message to a user
can be accomplished in only a few lines of code:
<div class="code"><pre>
XMPPConnection connection = <font color="navy"><b>new</b></font> XMPPTCPConnection(<font color="green">"jabber.org"</font>);
connection.connect();
connection.login(<font color="green">"mtucker"</font>, <font color="green">"password"</font>);
Chat chat = connection.getChatManager().createChat(<font color="green">"jsmith@jivesoftware.com"</font>, new MessageListener() {
public void processMessage(Chat chat, Message message) {
System.out.println(<font color="green">"Received message: "</font> + message);
}
});
chat.sendMessage(<font color="green">"Howdy!"</font>);
</pre></div>
<li>Doesn't force you to code at the packet level, as other libraries do. Smack provides
intelligent higher level constructs such as the <tt>Chat</tt> and <tt>Roster</tt>
classes, which let you program more efficiently.
<li>Does not require that you're familiar with the XMPP XML format, or even that you're familiar with XML.
<li>Provides easy machine to machine communication. Smack lets you set any number of properties on
each message, including properties that are Java objects.
<li>Open Source under the Apache License, which means you can incorporate Smack into your commercial or
non-commercial applications.
</ul>
<p class="subheader">
About XMPP
</p>
XMPP (eXtensible Messaging and Presence Protocol) is an open protocol standardized by the IETF
and supported and extended by the XMPP Standards Foundation
((<a href="http://www.jabber.org">http://www.xmpp.org</a>).
<p class="subheader">
How To Use This Documentation
</p>
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.
<br clear="all" /><br><br>
<div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

43
documentation/overview.md Normal file
View file

@ -0,0 +1,43 @@
Smack Overview
[Back](index.html)
Smack is a library for communicating with XMPP servers to perform real-time
communications, including instant messaging and group chat.
Smack Key Advantages
* Extremely simple to use, yet powerful API. Sending a text message to a user can be accomplished in only a few lines of code:
XMPPConnection connection = new XMPPTCPConnection("xmpp.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!");
* Doesn't force you to code at the packet level, as other libraries do. Smack provides intelligent higher level constructs such as the `Chat` and `Roster` classes, which let you program more efficiently.
* Does not require that you're familiar with the XMPP XML format, or even that you're familiar with XML.
* Provides easy machine to machine communication. Smack lets you set any number of properties on each message, including properties that are Java objects.
* Open Source under the Apache License, which means you can incorporate Smack into your commercial or non-commercial applications.
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](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.
Copyright (C) Jive Software 2002-2008

View file

@ -1,87 +0,0 @@
<html>
<head>
<title>Smack: Processing Incoming Packets - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">
Processing Incoming Packets
</div>
<div class="nav">
&laquo; <a href="index.html">Table of Contents</a>
</div>
<p>
Smack provides a flexible framework for processing incoming packets using two constructs:
<ul>
<li><tt>org.jivesoftware.smack.PacketCollector</tt> -- a class that lets you
synchronously wait for new packets.
<li><tt>org.jivesoftware.smack.PacketListener</tt> -- an interface for asynchronously
notifying you of incoming packets.
</ul>
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 <tt>XMPPConnection</tt> instance.<p>
The <tt>org.jivesoftware.smack.filter.PacketFilter</tt> interface determines which
specific packets will be delivered to a <tt>PacketCollector</tt> or <tt>PacketListener</tt>.
Many pre-defined filters can be found in the <tt>org.jivesoftware.smack.filter</tt> package.
<p>
The following code snippet demonstrates registering both a packet collector and a packet
listener:<p>
<div class="code"><pre>
<font color="gray"><i>// Create a packet filter to listen for new messages from a particular</i></font>
<font color="gray"><i>// user. We use an AndFilter to combine two other filters.</i></font>
PacketFilter filter = new AndFilter(new PacketTypeFilter(<b>Message.class</b>),
new FromContainsFilter(<font color="green">"mary@jivesoftware.com"</font>));
<font color="gray"><i>// Assume we've created a XMPPConnection name "connection".</i></font>
<font color="gray"><i>// First, register a packet collector using the filter we created.</i></font>
PacketCollector myCollector = connection.createPacketCollector(filter);
<font color="gray"><i>// Normally, you'd do something with the collector, like wait for new packets.</i></font>
<font color="gray"><i>// Next, create a packet listener. We use an anonymous inner class for brevity.</i></font>
PacketListener myListener = new PacketListener() {
<b>public</b> <b>void</b> processPacket(Packet packet) {
<font color="gray"><i>// Do something with the incoming packet here.</i></font>
}
};
<font color="gray"><i>// Register the listener.</i></font>
connection.addPacketListener(myListener, filter);
</pre></div><p>
<p class="subheader">
Standard Packet Filters
</p>
A rich set of packet filters are included with Smack, or you can create your own filters by coding
to the <tt>PacketFilter</tt> interface. The default set of filters includes:
<ul>
<li> <tt>PacketTypeFilter</tt> -- filters for packets that are a particular Class type.
<li> <tt>PacketIDFilter</tt> -- filters for packets with a particular packet ID.
<li> <tt>ThreadFilter</tt> -- filters for message packets with a particular thread ID.
<li> <tt>ToContainsFilter</tt> -- filters for packets that are sent to a particular address.
<li> <tt>FromContainsFilter</tt> -- filters for packets that are sent to a particular address.
<li> <tt>PacketExtensionFilter</tt> -- filters for packets that have a particular packet extension.
<li> <tt>AndFilter</tt> -- implements the logical AND operation over two filters.
<li> <tt>OrFilter</tt> -- implements the logical OR operation over two filters.
<li> <tt>NotFilter</tt> -- implements the logical NOT operation on a filter.
</ul>
<br clear="all" /><br><br>
<div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

View file

@ -0,0 +1,58 @@
Processing Incoming Packets
===========================
[Back](index.html)
Smack provides a flexible framework for processing incoming packets using two
constructs:
* `org.jivesoftware.smack.PacketCollector` -- a class that lets you synchronously wait for new packets.
* `org.jivesoftware.smack.PacketListener` -- an interface for asynchronously notifying you of incoming packets. 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 `XMPPConnection` instance.
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:
* `PacketTypeFilter` -- filters for packets that are a particular Class type.
* `PacketIDFilter` -- filters for packets with a particular packet ID.
* `ThreadFilter` -- filters for message packets with a particular thread ID.
* `ToContainsFilter` -- filters for packets that are sent to a particular address.
* `FromContainsFilter` -- filters for packets that are sent to a particular address.
* `PacketExtensionFilter` -- filters for packets that have a particular packet extension.
* `AndFilter` -- implements the logical AND operation over two filters.
* `OrFilter` -- implements the logical OR operation over two filters.
* `NotFilter` -- implements the logical NOT operation on a filter.
Copyright (C) Jive Software 2002-2008

View file

@ -1,282 +0,0 @@
<html>
<head>
<title>Smack: Provider Architecture - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">
Provider Architecture: Packet Extensions and Custom IQ's
</div>
<div class="nav">
&laquo; <a href="index.html">Table of Contents</a>
</div>
<p>
<p class="subheader">Introduction</p>
The Smack provider architecture is a system for plugging in
custom XML parsing of packet extensions and IQ packets. The
standard <a href="extensions/index.html">Smack Extensions</a>
are built using the provider architecture. There are two types of
providers:<ul>
<li><tt>IQProvider</tt> -- parses IQ requests into Java objects.
<li><tt>Extension Provider</tt> -- parses XML sub-documents attached to
packets into PacketExtension instances.</ul>
By default, Smack only knows how to process a few standard packets and sub-packets
that are in a few namespaces such as:<ul>
<li>jabber:iq:auth
<li>jabber:iq:roster
<li>jabber:iq:register</ul>
There are many more IQ types and extensions that are part of XMPP standards, and of
course an endless number that can be added as custom extensions. To support this, an
extensible parsing mechanism is provided via Smack and user build providers.
<p>
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 <a href="http://www.xmlpull.org/">XML Pull Parser</a>, 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.
<p>
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.
<p>
Management of these providers is accomplished via the <a href="">ProviderManager</a>
class. There are multiple ways to add providers to the manager.<ul>
<li>Call addXXProvider methods - You can call the appropriate add methods directly.
<pre>
ProviderManager.getInstance().addIQProvider("element", "namespace", new MyIQProvider());
ProviderManager.getInstance().addExtensionProvider("element", "namespace", new MyExtProvider());
</pre>
<li>Add a loader - You can add a ProviderLoader which will inject a means of loading multiple
providers (both types) into the manager. This is the mechanism used by Smack to load from the
Smack specific file format (via ProviderFileLoader). Implementers can provide the means to load
providers from any source they wish, or simply reuse the ProviderFileLoader to load from
their own provider files.
<pre>
ProviderManager.getInstance().addLoader(new ProviderFileLoader(FileUtils.getStreamForUrl("classpath:com/myco/provider/myco_custom.providers", null)));
</pre>
<li>VM Argument - You can add a provider file via the VM argument <i>smack.provider.file</i>.
This will load the file at the specified URL during startup when Smack initializes.
This also assumes the default configuration, since it requires that the <b>VmArgInitializer</b> was
part of the startup configuration.
<pre>
-Dsmack.provider.file=classpath:com/myco/provider/myco_custom.providers
or
-Dsmack.provider.file=file:///c:/myco/provider/myco_custom.providers
</pre>
</ul>
<p class="subheader">IQ Providers</p>
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:
<p>
<i>Introspection</i>
<p>
<u>Time Packet</u>
<pre>
&lt;iq type='result' to='joe@example.com' from='mary@example.com' id='time_1'&gt;
&lt;query xmlns='jabber:iq:time'&gt;
&lt;utc&gt;20020910T17:58:35&lt;/utc&gt;
&lt;tz&gt;MDT&lt;/tz&gt;
&lt;display&gt;Tue Sep 10 12:58:35 2002&lt;/display&gt;
&lt;/query&gt;
&lt;/iq&gt;
</pre>
<p>
<u>Time IQ Class</u>
<pre>
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;
}
}
</pre>
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.
<p>
<i>IQProvider Implementation</i>
<p>
<u>Disco Items Packet</u>
<pre>
&lt;iq type='result' from='shakespeare.lit' to='romeo@montague.net/orchard' id='items1'&gt;
&lt;query xmlns='http://jabber.org/protocol/disco#items'&gt;
&lt;item jid='people.shakespeare.lit' name='Directory of Characters'/&gt;
&lt;item jid='plays.shakespeare.lit' name='Play-Specific Chatrooms'/&gt;
&lt;item jid='mim.shakespeare.lit' name='Gateway to Marlowe IM'/&gt;
&lt;item jid='words.shakespeare.lit' name='Shakespearean Lexicon'/&gt;
&lt;item jid='globe.shakespeare.lit' name='Calendar of Performances'/&gt;
&lt;item jid='headlines.shakespeare.lit' name='Latest Shakespearean News'/&gt;
&lt;item jid='catalog.shakespeare.lit' name='Buy Shakespeare Stuff!'/&gt;
&lt;item jid='en2fr.shakespeare.lit' name='French Translation Service'/&gt;
&lt;/query&gt;
&lt;/iq&gt;
</pre>
<p>
<u>Disco Items IQProvider</u>
<pre>
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;
}
}
</pre>
<p class="subheader">Extension Providers</p>
Packet extension providers are responsible for parsing packet extensions, which are
child elements in a custom namespace of IQ, message and presence packets.
<p>
<u>Pubsub Subscription Packet</u>
<pre>
&lt;iq type='result' from='pubsub.shakespeare.lit' to='francisco@denmark.lit/barracks' id='sub1'&gt;
&lt;pubsub xmlns='http://jabber.org/protocol/pubsub'&gt;
&lt;subscription node='princely_musings' jid='francisco@denmark.lit' subscription='unconfigured'&gt;
&lt;subscribe-options&gt;
&lt;required/&gt;
&lt;/subscribe-options&gt;
&lt;/subscription&gt;
&lt;/pubsub&gt;
&lt;/iq&gt;
</pre>
<p>
<u>Subscription PacketExtensionProvider Implementation</u>
<pre>
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);
}
}
</pre>
<p class="subheader">Provider file format</p>
This is the format for a provider file which can be parsed by the <b>ProviderFileLoader</b>.
<pre>
&lt;?xml version="1.0"?&gt;
&lt;smackProviders&gt;
&lt;iqProvider&gt;
&lt;elementName&gt;query&lt;/elementName&gt;
&lt;namespace&gt;jabber:iq:time&lt;/namespace&gt;
&lt;className&gt;org.jivesoftware.smack.packet.Time&lt/className&gt;
&lt;/iqProvider&gt;
&lt;iqProvider&gt;
&lt;elementName&gt;query&lt;/elementName&gt;
&lt;namespace&gt;http://jabber.org/protocol/disco#items&lt;/namespace&gt;
&lt;className&gt;org.jivesoftware.smackx.provider.DiscoverItemsProvider&lt/className&gt;
&lt;/iqProvider&gt;
&lt;extensionProvider&gt;
&lt;elementName&gt;subscription&lt;/elementName&gt;
&lt;namespace&gt;http://jabber.org/protocol/pubsub&lt;/namespace&gt;
&lt;className&gt;org.jivesoftware.smackx.pubsub.provider.SubscriptionProvider&lt/className&gt;
&lt;/extensionProvider&gt;
&lt;/smackProviders&gt;</pre>
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 <b>ProviderManager</b> will overwrite any other that was loaded
before it.
<p>
<br clear="all" /><br><br>
<div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

258
documentation/providers.md Normal file
View file

@ -0,0 +1,258 @@
Provider Architecture: Packet Extensions and Custom IQ's
========================================================
[Back](index.html)
Introduction
------------
The Smack provider architecture is a system for plugging in custom XML parsing
of packet extensions and IQ packets. The standard [Smack
Extensions](extensions/index.html) are built using the provider architecture.
There are two types of providers:
* `IQProvider` -- parses IQ requests into Java objects.
* `Extension Provider` -- parses XML sub-documents attached to packets into PacketExtension instances. By default, Smack only knows how to process a few standard packets and sub-packets that are in a few namespaces such as:
* jabber:iq:auth
* jabber:iq:roster
* jabber:iq:register There are many more IQ types and extensions that are part of XMPP standards, and of course an endless number that can be added as custom extensions. To support this, an extensible parsing mechanism is provided via Smack and user build 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](http://www.xmlpull.org/), 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.
* Call addXXProvider methods - You can call the appropriate add methods directly.
```
ProviderManager.getInstance().addIQProvider("element", "namespace", new MyIQProvider());
ProviderManager.getInstance().addExtensionProvider("element", "namespace", new MyExtProvider());
```
* Add a loader - You can add a ProviderLoader which will inject a means of loading multiple providers (both types) into the manager. This is the mechanism used by Smack to load from the Smack specific file format (via ProviderFileLoader). Implementers can provide the means to load providers from any source they wish, or simply reuse the ProviderFileLoader to load from their own provider files.
ProviderManager.getInstance().addLoader(new ProviderFileLoader(FileUtils.getStreamForUrl("classpath:com/myco/provider/myco_custom.providers", null)));
* VM Argument - You can add a provider file via the VM argument _smack.provider.file_. This will load the file at the specified URL during startup when Smack initializes. This also assumes the default configuration, since it requires that the **VmArgInitializer** was part of the startup configuration.
`-Dsmack.provider.file=classpath:com/myco/provider/myco_custom.provider`s
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.
Copyright (C) Jive Software 2002-2008

View file

@ -1,125 +0,0 @@
<html>
<head>
<title>Smack: Roster and Presence - Jive Software</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="header">
Roster and Presence
</div>
<div class="nav">
&laquo; <a href="index.html">Table of Contents</a>
</div>
<p>
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.<p>
A <tt>Roster</tt> instance is obtained using the <tt>XMPPConnection.getRoster()</tt>
method.
<p class="subheader">Roster Entries</p>
<p>
Every user in a roster is represented by a RosterEntry, which consists of:<ul>
<li>An XMPP address (e.g. jsmith@example.com).
<li>A name you've assigned to the user (e.g. "Joe").
<li>The list of groups in the roster that the entry belongs to. If the roster
entry belongs to no groups, it's called an "unfiled entry".
</ul>
The following code snippet prints all entries in the roster:
<pre>
Roster roster = connection.getRoster();
Collection&lt;RosterEntry&gt; entries = roster.getEntries();
for (RosterEntry entry : entries) {
System.out.println(entry);
}
</pre>
Methods also exist to get individual entries, the list of unfiled entries, or to get one or
all roster groups.
<p class="subheader">Presence</p>
<img src="images/roster.png" width="166" height="322" vspace="5" hspace="5" alt="Roster" border="0" align="right">
<p>Every entry in the roster has presence associated with it. The
<tt>Roster.getPresence(String user)</tt> method will return a Presence object with
the user's presence or <tt>null</tt> if the user is not online or you are not
subscribed to the user's presence. <i>Note:</i> typically, presence
subscription is always tied to the user being on the roster, but this is not
true in all cases.</p>
<p>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.</p>
<p class="subheader">Listening for Roster and Presence Changes</p>
<p>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.</p>
<p>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.
<br clear="all">
<pre>
Roster roster = con.getRoster();
roster.addRosterListener(new RosterListener() {
// Ignored events public void entriesAdded(Collection&lt;String&gt; addresses) {}
public void entriesDeleted(Collection&lt;String&gt; addresses) {}
public void entriesUpdated(Collection&lt;String&gt; addresses) {}
public void presenceChanged(Presence presence) {
System.out.println("Presence changed: " + presence.getFrom() + " " + presence);
}
});
</pre>
<p class="subheader">Adding Entries to the Roster</p>
<p>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.</p>
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: <ul>
<li> Automatically accept all presence subscription requests.
<li> Automatically reject all presence subscription requests.
<li> Process presence subscription requests manually.
</ul>
The mode can be set using the <tt>Roster.setSubscriptionMode(Roster.SubscriptionMode)</tt>
method. Simple clients normally use one of the automated subscription modes, while
full-featured clients should manually process subscription requests and let the
end-user accept or reject each request. If using the manual mode, a PacketListener
should be registered that listens for Presence packets that have a type of
<tt>Presence.Type.subscribe</tt>.
<br clear="all" /><br><br>
<div class="footer">
Copyright &copy; Jive Software 2002-2008
</div>
</body>
</html>

94
documentation/roster.md Normal file
View file

@ -0,0 +1,94 @@
Roster and Presence
===================
[Back](index.html)
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:
* An XMPP address (e.g. jsmith@example.com).
* A name you've assigned to the user (e.g. "Joe").
* The list of groups in the roster that the entry belongs to. If the roster entry belongs to no groups, it's called an "unfiled entry". The following code snippet prints all entries in the roster:
```
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
![Roster](images/roster.png)
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:
* Automatically accept all presence subscription requests.
* Automatically reject all presence subscription requests.
* Process presence subscription requests manually. The mode can be set using the `Roster.setSubscriptionMode(Roster.SubscriptionMode)` method. Simple clients normally use one of the automated subscription modes, while full-featured clients should manually process subscription requests and let the end-user accept or reject each request. If using the manual mode, a PacketListener should be registered that listens for Presence packets that have a type of `Presence.Type.subscribe`.
Copyright (C) Jive Software 2002-2008

View file

@ -1,56 +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-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;
}

View file

@ -141,6 +141,30 @@ hr {
<div id="pageBody"> <div id="pageBody">
<h2>4.0.3 -- <span style="font-weight: normal;">2014-08-16</span></h2>
<h2> Bug
</h2>
<ul>
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-589'>SMACK-589</a>] - FormField.Option toXML() produces malformed XML
</li>
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-592'>SMACK-592</a>] - OfflineMessagesManager.getMessages() does send request before collector is set up and could leak collector
</li>
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-594'>SMACK-594</a>] - PrivateData Bookmarks.toXML() returns invalid XML
</li>
</ul>
<h2> Improvement
</h2>
<ul>
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-539'>SMACK-539</a>] - Verify ConnectionConfiguration parameters
</li>
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-588'>SMACK-588</a>] - Typo in org.jivesoftware.smackx.pubsub.ConfigureForm: s/isSubscibe/isSubscribe/
</li>
<li>[<a href='https://igniterealtime.org/issues/browse/SMACK-593'>SMACK-593</a>] - Smack should prefer full flush over sync flush when using compression
</li>
</ul>
<h2>4.0.2 -- <span style="font-weight: normal;">2014-07-27</span></h2> <h2>4.0.2 -- <span style="font-weight: normal;">2014-07-27</span></h2>
<h2> Improvement <h2> Improvement

View file

@ -169,13 +169,13 @@ public class Bookmarks implements PrivateData {
@Override @Override
public XmlStringBuilder toXML() { public XmlStringBuilder toXML() {
XmlStringBuilder buf = new XmlStringBuilder(); XmlStringBuilder buf = new XmlStringBuilder();
buf.openElement(ELEMENT).xmlnsAttribute(NAMESPACE); buf.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngelBracket();
for (BookmarkedURL urlStorage : getBookmarkedURLS()) { for (BookmarkedURL urlStorage : getBookmarkedURLS()) {
if(urlStorage.isShared()) { if(urlStorage.isShared()) {
continue; continue;
} }
buf.openElement("url").attribute("name", urlStorage.getName()).attribute("url", urlStorage.getURL()); buf.halfOpenElement("url").attribute("name", urlStorage.getName()).attribute("url", urlStorage.getURL());
buf.condAttribute(urlStorage.isRss(), "rss", "true"); buf.condAttribute(urlStorage.isRss(), "rss", "true");
buf.closeEmptyElement(); buf.closeEmptyElement();
} }
@ -185,7 +185,7 @@ public class Bookmarks implements PrivateData {
if(conference.isShared()) { if(conference.isShared()) {
continue; continue;
} }
buf.openElement("conference"); buf.halfOpenElement("conference");
buf.attribute("name", conference.getName()); buf.attribute("name", conference.getName());
buf.attribute("autojoin", Boolean.toString(conference.isAutoJoin())); buf.attribute("autojoin", Boolean.toString(conference.isAutoJoin()));
buf.attribute("jid", conference.getJid()); buf.attribute("jid", conference.getJid());