1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-26 05:52:06 +01:00

Merge trunk (3.2 release) up to the 3.2 branch for development on 3.2.x releases.

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/branches/smack_3_2_0@12370 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
rcollier 2011-05-12 02:06:35 +00:00
commit 22d04c26e3
27 changed files with 689 additions and 235 deletions

View file

@ -28,7 +28,7 @@
<property name="version.major" value="3" /> <property name="version.major" value="3" />
<property name="version.minor" value="2" /> <property name="version.minor" value="2" />
<property name="version.revision" value="0" /> <property name="version.revision" value="0" />
<property name="version.extra" value="Beta2" /> <property name="version.extra" value="" />
<if> <if>
<equals arg1="${version.extra}" arg2=""/> <equals arg1="${version.extra}" arg2=""/>
@ -98,8 +98,8 @@
destdir="${compile.dir}" destdir="${compile.dir}"
includeAntRuntime="no" includeAntRuntime="no"
debug="on" debug="on"
source="1.5" source="1.6"
target="1.5" target="1.6"
> >
<src path="${basedir}/source" /> <src path="${basedir}/source" />
<classpath> <classpath>
@ -113,8 +113,8 @@
destdir="${compile.dir}/jingle/extension" destdir="${compile.dir}/jingle/extension"
includeAntRuntime="no" includeAntRuntime="no"
debug="on" debug="on"
source="1.5" source="1.6"
target="1.5" target="1.6"
> >
<src path="${basedir}/jingle/extension/source" /> <src path="${basedir}/jingle/extension/source" />
<classpath> <classpath>
@ -141,8 +141,8 @@
destdir="${compile.test.dir}" destdir="${compile.test.dir}"
includeAntRuntime="no" includeAntRuntime="no"
debug="on" debug="on"
source="1.5" source="1.6"
target="1.5" target="1.6"
> >
<src path="${test.dir}" /> <src path="${test.dir}" />
<classpath> <classpath>

View file

@ -141,22 +141,22 @@ hr {
<div id="pageBody"> <div id="pageBody">
<h2>3.2.0 Beta -- <span style="font-weight: normal;">February 4, 2011</span></h2> <h2>3.2.0 -- <span style="font-weight: normal;">May 3, 2011</span></h2>
<h2>New Feature</h2> <h3>New Feature</h3>
<ul> <ul>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-272'>SMACK-272</a>] - Add support for pubsub (XEP-0060)</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-272'>SMACK-272</a>] - Add support for pubsub (XEP-0060)</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-296'>SMACK-296</a>] - Add support for XEP-0224: Attention</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-296'>SMACK-296</a>] - Add support for XEP-0224: Attention</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-319'>SMACK-319</a>] - Add common interfaces for SOCKS5 Bytestreams and In-Band Bytestreams</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-319'>SMACK-319</a>] - Add common interfaces for SOCKS5 Bytestreams and In-Band Bytestreams</li>
</ul> </ul>
<h2>Improvement</h2> <h3>Improvement</h3>
<ul> <ul>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-137'>SMACK-137</a>] - File Transfer Settings</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-137'>SMACK-137</a>] - File Transfer Settings</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-156'>SMACK-156</a>] - Add the ability to register for roster events before logging in</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-156'>SMACK-156</a>] - Add the ability to register for roster events before logging in</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-261'>SMACK-261</a>] - Minor Jingle cleanup to better support Jingle in Spark</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-261'>SMACK-261</a>] - Minor Jingle cleanup to better support Jingle in Spark</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-266'>SMACK-266</a>] - Add provider for fastpath to smackx</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-277'>SMACK-277</a>] - Update XMLUnit to the latest version</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-277'>SMACK-277</a>] - Update XMLUnit to the latest version</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-282'>SMACK-282</a>] - Support SASL-related error conditions.</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-282'>SMACK-282</a>] - Support SASL-related error conditions.</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-283'>SMACK-283</a>] - Investigate why Jingle is connecting to stun.xten.net</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-285'>SMACK-285</a>] - Add support for Nicks</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-285'>SMACK-285</a>] - Add support for Nicks</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-289'>SMACK-289</a>] - There is no way of retrieving items from a pubsub node when the user has multiple subscriptions.</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-289'>SMACK-289</a>] - There is no way of retrieving items from a pubsub node when the user has multiple subscriptions.</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-294'>SMACK-294</a>] - Handle empty roster groups and no goups in the same way</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-294'>SMACK-294</a>] - Handle empty roster groups and no goups in the same way</li>
@ -174,8 +174,9 @@ hr {
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-310'>SMACK-310</a>] - Add Support for Localized Message Subjects</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-310'>SMACK-310</a>] - Add Support for Localized Message Subjects</li>
</ul> </ul>
<h2>Bug</h2> <h3>Bug</h3>
<ul> <ul>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-163'>SMACK-163</a>] - Fix NPE in RoomInfo when subject has not value</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-207'>SMACK-207</a>] - Parsing of messages may disconnect Smack/Spark</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-207'>SMACK-207</a>] - Parsing of messages may disconnect Smack/Spark</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-225'>SMACK-225</a>] - Improper handeling of DNS SRV records</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-225'>SMACK-225</a>] - Improper handeling of DNS SRV records</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-232'>SMACK-232</a>] - Better handling of Roster error</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-232'>SMACK-232</a>] - Better handling of Roster error</li>
@ -184,6 +185,7 @@ hr {
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-269'>SMACK-269</a>] - Smack 3.1.0 creates a new chat for every incoming message</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-269'>SMACK-269</a>] - Smack 3.1.0 creates a new chat for every incoming message</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-271'>SMACK-271</a>] - Deadlock in XMPPConnection while login and parsing stream features</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-271'>SMACK-271</a>] - Deadlock in XMPPConnection while login and parsing stream features</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-275'>SMACK-275</a>] - Patch: Fix for broken SASL DIGEST-MD5 implementation</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-275'>SMACK-275</a>] - Patch: Fix for broken SASL DIGEST-MD5 implementation</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-280'>SMACK-280</a>] - The authentification should use the Connection#sendPacket method and work transparent with packets and packet listeners.</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-288'>SMACK-288</a>] - The parsing of the result for a LeafNode.getItems() call is incorrect. It creates a DefaultPacketExtension instead of an Item for every other item in the result.</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-288'>SMACK-288</a>] - The parsing of the result for a LeafNode.getItems() call is incorrect. It creates a DefaultPacketExtension instead of an Item for every other item in the result.</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-290'>SMACK-290</a>] - Deadlock while getting Roster before it&#39;s initialized</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-290'>SMACK-290</a>] - Deadlock while getting Roster before it&#39;s initialized</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-291'>SMACK-291</a>] - RosterGroup modifications should depend on roster push</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-291'>SMACK-291</a>] - RosterGroup modifications should depend on roster push</li>
@ -193,6 +195,8 @@ hr {
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-312'>SMACK-312</a>] - Only fire RosterListener#entriesUpdated for RosterEntries that changed</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-312'>SMACK-312</a>] - Only fire RosterListener#entriesUpdated for RosterEntries that changed</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-327'>SMACK-327</a>] - getFeatures() method on DiscoverInfo is improperly set to be package protected instead of public</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-327'>SMACK-327</a>] - getFeatures() method on DiscoverInfo is improperly set to be package protected instead of public</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-328'>SMACK-328</a>] - Number format exception while parsing dates.</li> <li>[<a href='http://issues.igniterealtime.org/browse/SMACK-328'>SMACK-328</a>] - Number format exception while parsing dates.</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-332'>SMACK-332</a>] - Smack 3.2.0b2 shows wrong version in Smack Dubugger Window</li>
<li>[<a href='http://issues.igniterealtime.org/browse/SMACK-334'>SMACK-334</a>] - Error in form for FileTransferNegotiator</li>
</ul> </ul>
<h2>3.1.0 -- <span style="font-weight: normal;">November 20, 2008</span></h2> <h2>3.1.0 -- <span style="font-weight: normal;">November 20, 2008</span></h2>

View file

@ -52,11 +52,6 @@ public class STUNResolver extends TransportResolver {
// The filename where the STUN servers are stored. // The filename where the STUN servers are stored.
public final static String STUNSERVERS_FILENAME = "META-INF/stun-config.xml"; public final static String STUNSERVERS_FILENAME = "META-INF/stun-config.xml";
// Fallback values when we don't have any STUN server to use...
private final static String FALLBACKHOSTNAME = "stun.xten.net";
private final static int FALLBACKHOSTPORT = 3478;
// Current STUN server we are using // Current STUN server we are using
protected STUNService currentServer; protected STUNService currentServer;
@ -189,10 +184,10 @@ public class STUNResolver extends TransportResolver {
} }
catch (XmlPullParserException e) { catch (XmlPullParserException e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
catch (IOException e) { catch (IOException e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
currentServer = bestSTUNServer(serversList); currentServer = bestSTUNServer(serversList);
@ -247,13 +242,7 @@ public class STUNResolver extends TransportResolver {
} }
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
}
// If the list of candidates is empty, add at least one default server
if (serversList.isEmpty()) {
currentServer = new STUNService(FALLBACKHOSTNAME, FALLBACKHOSTPORT);
serversList.add(currentServer);
} }
return serversList; return serversList;
@ -370,14 +359,14 @@ public class STUNResolver extends TransportResolver {
} }
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
} }
} }
} }
} }
catch (SocketException e) { catch (SocketException e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
finally { finally {
setInitialized(); setInitialized();
@ -524,7 +513,7 @@ public class STUNResolver extends TransportResolver {
} }
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); LOGGER.error(e.getMessage(), e);
} }
return result; return result;

View file

@ -323,9 +323,13 @@ public abstract class Connection {
/** /**
* Logs in to the server using the strongest authentication mode supported by * Logs in to the server using the strongest authentication mode supported by
* the server, then sets presence to available. If more than five seconds * the server, then sets presence to available. If the server supports SASL authentication
* (default timeout) elapses in each step of the authentication process without * then the user will be authenticated using SASL if not Non-SASL authentication will
* a response from the server, or if an error occurs, a XMPPException will be thrown.<p> * be tried. If more than five seconds (default timeout) elapses in each step of the
* authentication process without a response from the server, or if an error occurs, a
* XMPPException will be thrown.<p>
*
* Before logging in (i.e. authenticate) to the server the connection must be connected.
* *
* It is possible to log in without sending an initial available presence by using * It is possible to log in without sending an initial available presence by using
* {@link ConnectionConfiguration#setSendPresence(boolean)}. If this connection is * {@link ConnectionConfiguration#setSendPresence(boolean)}. If this connection is
@ -346,15 +350,13 @@ public abstract class Connection {
/** /**
* Logs in to the server using the strongest authentication mode supported by * Logs in to the server using the strongest authentication mode supported by
* the server. If the server supports SASL authentication then the user will be * the server, then sets presence to available. If the server supports SASL authentication
* authenticated using SASL if not Non-SASL authentication will be tried. If more than * then the user will be authenticated using SASL if not Non-SASL authentication will
* five seconds (default timeout) elapses in each step of the authentication process * be tried. If more than five seconds (default timeout) elapses in each step of the
* without a response from the server, or if an error occurs, a XMPPException will be * authentication process without a response from the server, or if an error occurs, a
* thrown.<p> * XMPPException will be thrown.<p>
* *
* Before logging in (i.e. authenticate) to the server the connection must be connected. * Before logging in (i.e. authenticate) to the server the connection must be connected.
* For compatibility and easiness of use the connection will automatically connect to the
* server if not already connected.<p>
* *
* It is possible to log in without sending an initial available presence by using * It is possible to log in without sending an initial available presence by using
* {@link ConnectionConfiguration#setSendPresence(boolean)}. If this connection is * {@link ConnectionConfiguration#setSendPresence(boolean)}. If this connection is

View file

@ -1,7 +1,7 @@
package org.jivesoftware.smack; package org.jivesoftware.smack;
import org.jivesoftware.smack.packet.StreamError; import org.jivesoftware.smack.packet.StreamError;
import java.util.Random;
/** /**
* Handles the automatic reconnection process. Every time a connection is dropped without * Handles the automatic reconnection process. Every time a connection is dropped without
* the application explictly closing it, the manager automatically tries to reconnect to * the application explictly closing it, the manager automatically tries to reconnect to
@ -20,6 +20,8 @@ public class ReconnectionManager implements ConnectionListener {
// Holds the connection to the server // Holds the connection to the server
private Connection connection; private Connection connection;
private Thread reconnectionThread;
private int randomBase = new Random().nextInt(11) + 5; // between 5 and 15 seconds
// Holds the state of the reconnection // Holds the state of the reconnection
boolean done = false; boolean done = false;
@ -61,11 +63,14 @@ public class ReconnectionManager implements ConnectionListener {
* <li>Finally it will try indefinitely every 5 minutes. * <li>Finally it will try indefinitely every 5 minutes.
* </ol> * </ol>
*/ */
protected void reconnect() { synchronized protected void reconnect() {
if (this.isReconnectionAllowed()) { if (this.isReconnectionAllowed()) {
// Since there is no thread running, creates a new one to attempt // Since there is no thread running, creates a new one to attempt
// the reconnection. // the reconnection.
Thread reconnectionThread = new Thread() { // avoid to run duplicated reconnectionThread -- fd: 16/09/2010
if (reconnectionThread!=null && reconnectionThread.isAlive()) return;
reconnectionThread = new Thread() {
/** /**
* Holds the current number of reconnection attempts * Holds the current number of reconnection attempts
@ -78,13 +83,14 @@ public class ReconnectionManager implements ConnectionListener {
* @return the number of seconds until the next reconnection attempt. * @return the number of seconds until the next reconnection attempt.
*/ */
private int timeDelay() { private int timeDelay() {
attempts++;
if (attempts > 13) { if (attempts > 13) {
return 60 * 5; // 5 minutes return randomBase*6*5; // between 2.5 and 7.5 minutes (~5 minutes)
} }
if (attempts > 7) { if (attempts > 7) {
return 60; // 1 minute return randomBase*6; // between 30 and 90 seconds (~1 minutes)
} }
return 10; // 10 seconds return randomBase; // 10 seconds
} }
/** /**

View file

@ -854,9 +854,11 @@ public class Roster {
// If the entry was in then list then update its state with the new values // If the entry was in then list then update its state with the new values
RosterEntry oldEntry = entries.put(item.getUser(), entry); RosterEntry oldEntry = entries.put(item.getUser(), entry);
// Keep note that an entry has been updated but only if it's different RosterPacket.Item oldItem = RosterEntry.toRosterItem(oldEntry);
if (oldEntry == null || !oldEntry.equalsDeep(entry)) { //We have also to check if only the group names have changed from the item
updatedEntries.add(item.getUser()); if (oldEntry == null || !oldEntry.equalsDeep(entry) || !item.getGroupNames().equals(oldItem.getGroupNames()))
{
updatedEntries.add(item.getUser());
} }
} }
// If the roster entry belongs to any groups, remove it from the // If the roster entry belongs to any groups, remove it from the

View file

@ -44,7 +44,7 @@ import java.util.*;
*/ */
public final class SmackConfiguration { public final class SmackConfiguration {
private static final String SMACK_VERSION = "3.2.0 Beta2"; private static final String SMACK_VERSION = "3.2.0";
private static int packetReplyTimeout = 5000; private static int packetReplyTimeout = 5000;
private static int keepAliveInterval = 30000; private static int keepAliveInterval = 30000;

View file

@ -184,34 +184,7 @@ public class XMPPConnection extends Connection {
return user; return user;
} }
/** @Override
* Logs in to the server using the strongest authentication mode supported by
* the server. If the server supports SASL authentication then the user will be
* authenticated using SASL if not Non-SASL authentication will be tried. If more than
* five seconds (default timeout) elapses in each step of the authentication process
* without a response from the server, or if an error occurs, a XMPPException will be
* thrown.<p>
*
* Before logging in (i.e. authenticate) to the server the connection must be connected.
* For compatibility and easiness of use the connection will automatically connect to the
* server if not already connected.<p>
*
* It is possible to log in without sending an initial available presence by using
* {@link ConnectionConfiguration#setSendPresence(boolean)}. If this connection is
* not interested in loading its roster upon login then use
* {@link ConnectionConfiguration#setRosterLoadedAtLogin(boolean)}.
* Finally, if you want to not pass a password and instead use a more advanced mechanism
* while using SASL then you may be interested in using
* {@link ConnectionConfiguration#setCallbackHandler(javax.security.auth.callback.CallbackHandler)}.
* For more advanced login settings see {@link ConnectionConfiguration}.
*
* @param username the username.
* @param password the password or <tt>null</tt> if using a CallbackHandler.
* @param resource the resource.
* @throws XMPPException if an error occurs.
* @throws IllegalStateException if not connected to the server, or already logged in
* to the server.
*/
public synchronized void login(String username, String password, String resource) throws XMPPException { public synchronized void login(String username, String password, String resource) throws XMPPException {
if (!isConnected()) { if (!isConnected()) {
throw new IllegalStateException("Not connected to server."); throw new IllegalStateException("Not connected to server.");
@ -286,16 +259,7 @@ public class XMPPConnection extends Connection {
} }
} }
/** @Override
* Logs in to the server anonymously. Very few servers are configured to support anonymous
* authentication, so it's fairly likely logging in anonymously will fail. If anonymous login
* does succeed, your XMPP address will likely be in the form "server/123ABC" (where "123ABC"
* is a random value generated by the server).
*
* @throws XMPPException if an error occurs or anonymous logins are not supported by the server.
* @throws IllegalStateException if not connected to the server, or already logged in
* to the server.
*/
public synchronized void loginAnonymously() throws XMPPException { public synchronized void loginAnonymously() throws XMPPException {
if (!isConnected()) { if (!isConnected()) {
throw new IllegalStateException("Not connected to server."); throw new IllegalStateException("Not connected to server.");

View file

@ -169,7 +169,7 @@ public class PrivacyItem {
* *
* @param order indicates the order in the list. * @param order indicates the order in the list.
*/ */
private void setOrder(int order) { public void setOrder(int order) {
this.order = order; this.order = order;
} }

View file

@ -316,7 +316,27 @@ public class EnhancedDebugger implements SmackDebugger {
menu.add(menuItem1); menu.add(menuItem1);
// Add listener to the text area so the popup menu can come up. // Add listener to the text area so the popup menu can come up.
messageTextArea.addMouseListener(new PopupListener(menu)); messageTextArea.addMouseListener(new PopupListener(menu));
allPane.setBottomComponent(new JScrollPane(messageTextArea)); JPanel sublayout = new JPanel(new BorderLayout());
sublayout.add(new JScrollPane(messageTextArea), BorderLayout.CENTER);
JButton clearb = new JButton("Clear All Packets");
clearb.addActionListener(new AbstractAction() {
private static final long serialVersionUID = -8576045822764763613L;
@Override
public void actionPerformed(ActionEvent e) {
for(int i=0; i< messagesTable.getRowCount();i++)
{
messagesTable.removeRow(i);
}
}
});
sublayout.add(clearb, BorderLayout.NORTH);
allPane.setBottomComponent(sublayout);
allPane.setDividerLocation(150); allPane.setDividerLocation(150);
tabbedPane.add("All Packets", allPane); tabbedPane.add("All Packets", allPane);

View file

@ -473,7 +473,7 @@ public class FileTransferNegotiator {
private DataForm createDefaultInitiationForm() { private DataForm createDefaultInitiationForm() {
DataForm form = new DataForm(Form.TYPE_FORM); DataForm form = new DataForm(Form.TYPE_FORM);
FormField field = new FormField(STREAM_DATA_FIELD_NAME); FormField field = new FormField(STREAM_DATA_FIELD_NAME);
field.setType(FormField.TYPE_LIST_MULTI); field.setType(FormField.TYPE_LIST_SINGLE);
if (!IBB_ONLY) { if (!IBB_ONLY) {
field.addOption(new FormField.Option(Socks5BytestreamManager.NAMESPACE)); field.addOption(new FormField.Option(Socks5BytestreamManager.NAMESPACE));
} }

View file

@ -21,6 +21,7 @@
package org.jivesoftware.smackx.muc; package org.jivesoftware.smackx.muc;
import org.jivesoftware.smackx.Form; import org.jivesoftware.smackx.Form;
import org.jivesoftware.smackx.FormField;
import org.jivesoftware.smackx.packet.DiscoverInfo; import org.jivesoftware.smackx.packet.DiscoverInfo;
import java.util.Iterator; import java.util.Iterator;
@ -88,17 +89,14 @@ public class RoomInfo {
// Get the information based on the discovered extended information // Get the information based on the discovered extended information
Form form = Form.getFormFrom(info); Form form = Form.getFormFrom(info);
if (form != null) { if (form != null) {
this.description = FormField descField = form.getField("muc#roominfo_description");
form.getField("muc#roominfo_description").getValues().next(); this.description = descField == null ? "" : descField.getValues().next();
Iterator<String> values = form.getField("muc#roominfo_subject").getValues();
if (values.hasNext()) { FormField subjField = form.getField("muc#roominfo_subject");
this.subject = values.next(); this.subject = subjField == null ? "" : subjField.getValues().next();
}
else { FormField occCountField = form.getField("muc#roominfo_occupants");
this.subject = ""; this.occupantsCount = occCountField == null ? -1 : Integer.parseInt(occCountField.getValues()
}
this.occupantsCount =
Integer.parseInt(form.getField("muc#roominfo_occupants").getValues()
.next()); .next());
} }
} }

View file

@ -161,7 +161,9 @@ public class ConfigureForm extends Form
public void setChildrenAssociationPolicy(ChildrenAssociationPolicy policy) public void setChildrenAssociationPolicy(ChildrenAssociationPolicy policy)
{ {
addField(ConfigureNodeFields.children_association_policy, FormField.TYPE_LIST_SINGLE); addField(ConfigureNodeFields.children_association_policy, FormField.TYPE_LIST_SINGLE);
setAnswer(ConfigureNodeFields.children_association_policy.getFieldName(), policy.toString()); List<String> values = new ArrayList<String>(1);
values.add(policy.toString());
setAnswer(ConfigureNodeFields.children_association_policy.getFieldName(), values);
} }
/** /**

View file

@ -13,7 +13,7 @@
*/ */
package org.jivesoftware.smackx.pubsub; package org.jivesoftware.smackx.pubsub;
import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.pubsub.provider.ItemProvider; import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
/** /**
@ -39,7 +39,7 @@ import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
* *
* @author Robin Collier * @author Robin Collier
*/ */
public class Item implements PacketExtension public class Item extends NodeExtension
{ {
private String id; private String id;
@ -52,6 +52,7 @@ public class Item implements PacketExtension
*/ */
public Item() public Item()
{ {
super(PubSubElementType.ITEM);
} }
/** /**
@ -63,9 +64,28 @@ public class Item implements PacketExtension
*/ */
public Item(String itemId) public Item(String itemId)
{ {
// The element type is actually irrelevant since we override getNamespace() to return null
super(PubSubElementType.ITEM);
id = itemId; id = itemId;
} }
/**
* Create an <tt>Item</tt> with an id and a node id.
* <p>
* <b>Note:</b> This is not valid for publishing an item to a node, only receiving from
* one as part of {@link Message}. If used to create an Item to publish
* (via {@link LeafNode#publish(Item)}, the server <i>may</i> return an
* error for an invalid packet.
*
* @param itemId The id of the item.
* @param nodeId The id of the node which the item was published to.
*/
public Item(String itemId, String nodeId)
{
super(PubSubElementType.ITEM_EVENT, nodeId);
id = itemId;
}
/** /**
* Get the item id. Unique to the node it is associated with. * Get the item id. Unique to the node it is associated with.
* *
@ -76,16 +96,13 @@ public class Item implements PacketExtension
return id; return id;
} }
public String getElementName() @Override
{
return "item";
}
public String getNamespace() public String getNamespace()
{ {
return null; return null;
} }
@Override
public String toXML() public String toXML()
{ {
StringBuilder builder = new StringBuilder("<item"); StringBuilder builder = new StringBuilder("<item");
@ -96,6 +113,12 @@ public class Item implements PacketExtension
builder.append(id); builder.append(id);
builder.append("'"); builder.append("'");
} }
if (getNode() != null) {
builder.append(" node='");
builder.append(getNode());
builder.append("'");
}
builder.append("/>"); builder.append("/>");
return builder.toString(); return builder.toString();

View file

@ -16,6 +16,8 @@ package org.jivesoftware.smackx.pubsub;
import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smackx.pubsub.provider.ItemProvider; import org.jivesoftware.smackx.pubsub.provider.ItemProvider;
import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
/** /**
* This class represents an item that has been, or will be published to a * This class represents an item that has been, or will be published to a
* pubsub node. An <tt>Item</tt> has several properties that are dependent * pubsub node. An <tt>Item</tt> has several properties that are dependent
@ -43,6 +45,20 @@ public class PayloadItem<E extends PacketExtension> extends Item
{ {
private E payload; private E payload;
/**
* Create an <tt>Item</tt> with no id and a payload The id will be set by the server.
*
* @param payloadExt A {@link PacketExtension} which represents the payload data.
*/
public PayloadItem(E payloadExt)
{
super();
if (payloadExt == null)
throw new IllegalArgumentException("payload cannot be 'null'");
payload = payloadExt;
}
/** /**
* Create an <tt>Item</tt> with an id and payload. * Create an <tt>Item</tt> with an id and payload.
* *
@ -58,6 +74,28 @@ public class PayloadItem<E extends PacketExtension> extends Item
payload = payloadExt; payload = payloadExt;
} }
/**
* Create an <tt>Item</tt> with an id, node id and payload.
*
* <p>
* <b>Note:</b> This is not valid for publishing an item to a node, only receiving from
* one as part of {@link Message}. If used to create an Item to publish
* (via {@link LeafNode#publish(Item)}, the server <i>may</i> return an
* error for an invalid packet.
*
* @param itemId The id of this item.
* @param nodeId The id of the node the item was published to.
* @param payloadExt A {@link PacketExtension} which represents the payload data.
*/
public PayloadItem(String itemId, String nodeId, E payloadExt)
{
super(itemId, nodeId);
if (payloadExt == null)
throw new IllegalArgumentException("payload cannot be 'null'");
payload = payloadExt;
}
/** /**
* Get the payload associated with this <tt>Item</tt>. Customising the payload * Get the payload associated with this <tt>Item</tt>. Customising the payload
* parsing from the server can be accomplished as described in {@link ItemProvider}. * parsing from the server can be accomplished as described in {@link ItemProvider}.
@ -69,6 +107,7 @@ public class PayloadItem<E extends PacketExtension> extends Item
return payload; return payload;
} }
@Override
public String toXML() public String toXML()
{ {
StringBuilder builder = new StringBuilder("<item"); StringBuilder builder = new StringBuilder("<item");
@ -80,6 +119,11 @@ public class PayloadItem<E extends PacketExtension> extends Item
builder.append("'"); builder.append("'");
} }
if (getNode() != null) {
builder.append(" node='");
builder.append(getNode());
builder.append("'");
}
builder.append(">"); builder.append(">");
builder.append(payload.toXML()); builder.append(payload.toXML());
builder.append("</item>"); builder.append("</item>");

View file

@ -32,6 +32,9 @@ public enum PubSubElementType
OPTIONS("options", PubSubNamespace.BASIC), OPTIONS("options", PubSubNamespace.BASIC),
DEFAULT("default", PubSubNamespace.OWNER), DEFAULT("default", PubSubNamespace.OWNER),
ITEMS("items", PubSubNamespace.BASIC), ITEMS("items", PubSubNamespace.BASIC),
ITEMS_EVENT("items", PubSubNamespace.EVENT),
ITEM("item", PubSubNamespace.BASIC),
ITEM_EVENT("item", PubSubNamespace.EVENT),
PUBLISH("publish", PubSubNamespace.BASIC), PUBLISH("publish", PubSubNamespace.BASIC),
PUBLISH_OPTIONS("publish-options", PubSubNamespace.BASIC), PUBLISH_OPTIONS("publish-options", PubSubNamespace.BASIC),
PURGE_OWNER("purge", PubSubNamespace.OWNER), PURGE_OWNER("purge", PubSubNamespace.OWNER),

View file

@ -48,13 +48,15 @@ final public class PubSubManager
private Map<String, Node> nodeMap = new ConcurrentHashMap<String, Node>(); private Map<String, Node> nodeMap = new ConcurrentHashMap<String, Node>();
/** /**
* Create a pubsub manager associated to the specified connection. * Create a pubsub manager associated to the specified connection. Defaults the service
* name to <i>pubsub</i>
* *
* @param connection The XMPP connection * @param connection The XMPP connection
*/ */
public PubSubManager(Connection connection) public PubSubManager(Connection connection)
{ {
con = connection; con = connection;
to = "pubsub." + connection.getServiceName();
} }
/** /**

View file

@ -35,13 +35,14 @@ public class ItemProvider implements PacketExtensionProvider
public PacketExtension parseExtension(XmlPullParser parser) throws Exception public PacketExtension parseExtension(XmlPullParser parser) throws Exception
{ {
String id = parser.getAttributeValue(null, "id"); String id = parser.getAttributeValue(null, "id");
String node = parser.getAttributeValue(null, "node");
String elem = parser.getName(); String elem = parser.getName();
int tag = parser.next(); int tag = parser.next();
if (tag == XmlPullParser.END_TAG) if (tag == XmlPullParser.END_TAG)
{ {
return new Item(id); return new Item(id, node);
} }
else else
{ {
@ -63,11 +64,11 @@ public class ItemProvider implements PacketExtensionProvider
if (!done) if (!done)
tag = parser.next(); tag = parser.next();
} }
return new PayloadItem<SimplePayload>(id, new SimplePayload(payloadElemName, payloadNS, payloadText.toString())); return new PayloadItem<SimplePayload>(id, node, new SimplePayload(payloadElemName, payloadNS, payloadText.toString()));
} }
else else
{ {
return new PayloadItem<PacketExtension>(id, PacketParserUtils.parsePacketExtension(payloadElemName, payloadNS, parser)); return new PayloadItem<PacketExtension>(id, node, PacketParserUtils.parsePacketExtension(payloadElemName, payloadNS, parser));
} }
} }
} }

View file

@ -0,0 +1,77 @@
package org.jivesoftware.smack;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.IQ.Type;
public class ThreadedDummyConnection extends DummyConnection
{
private BlockingQueue<IQ> replyQ = new ArrayBlockingQueue<IQ>(1);
private BlockingQueue<Packet> messageQ = new LinkedBlockingQueue<Packet>(5);
@Override
public void sendPacket(Packet packet)
{
super.sendPacket(packet);
if ((packet instanceof IQ) && !replyQ.isEmpty())
{
// Set reply packet to match one being sent. We haven't started the
// other thread yet so this is still safe.
IQ replyPacket = replyQ.peek();
replyPacket.setPacketID(packet.getPacketID());
replyPacket.setFrom(packet.getTo());
replyPacket.setTo(packet.getFrom());
replyPacket.setType(Type.RESULT);
new ProcessQueue(replyQ).start();
}
}
public void addMessage(Message msgToProcess)
{
messageQ.add(msgToProcess);
}
public void addIQReply(IQ reply)
{
replyQ.add(reply);
}
public void processMessages()
{
if (!messageQ.isEmpty())
new ProcessQueue(messageQ).start();
else
System.out.println("No messages to process");
}
class ProcessQueue extends Thread
{
private BlockingQueue<? extends Packet> processQ;
ProcessQueue(BlockingQueue<? extends Packet> queue)
{
processQ = queue;
}
@Override
public void run()
{
try
{
processPacket(processQ.take());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
};
}

View file

@ -0,0 +1,92 @@
package org.jivesoftware.smack.filters;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import org.jivesoftware.smack.filter.FromMatchesFilter;
import org.jivesoftware.smack.packet.Packet;
import org.junit.Test;
public class FromMatchesFilterTest {
private static final String BASE_JID1 = "ss@muc.myserver.com";
private static final String FULL_JID1_R1 = BASE_JID1 + "/resource";
private static final String FULL_JID1_R2 = BASE_JID1 + "/resource2";
private static final String BASE_JID2 = "sss@muc.myserver.com";
private static final String FULL_JID2 = BASE_JID2 + "/resource";
private static final String SERVICE_JID1 = "muc.myserver.com";
private static final String SERVICE_JID2 = "pubsub.myserver.com";
@Test
public void compareMatchingFullJid()
{
FromMatchesFilter filter = new FromMatchesFilter(FULL_JID1_R1);
Packet packet = new Packet() {
@Override
public String toXML() { return null; }
};
packet.setFrom(FULL_JID1_R1);
assertTrue(filter.accept(packet));
packet.setFrom(BASE_JID1);
assertFalse(filter.accept(packet));
packet.setFrom(FULL_JID1_R2);
assertFalse(filter.accept(packet));
packet.setFrom(BASE_JID2);
assertFalse(filter.accept(packet));
packet.setFrom(FULL_JID2);
assertFalse(filter.accept(packet));
}
@Test
public void compareMatchingBaseJid()
{
FromMatchesFilter filter = new FromMatchesFilter(BASE_JID1);
Packet packet = new Packet() {
@Override
public String toXML() { return null; }
};
packet.setFrom(BASE_JID1);
assertTrue(filter.accept(packet));
packet.setFrom(FULL_JID1_R1);
assertTrue(filter.accept(packet));
packet.setFrom(FULL_JID1_R2);
assertTrue(filter.accept(packet));
packet.setFrom(BASE_JID2);
assertFalse(filter.accept(packet));
packet.setFrom(FULL_JID2);
assertFalse(filter.accept(packet));
}
@Test
public void compareMatchingServiceJid()
{
FromMatchesFilter filter = new FromMatchesFilter(SERVICE_JID1);
Packet packet = new Packet() {
@Override
public String toXML() { return null; }
};
packet.setFrom(SERVICE_JID1);
assertTrue(filter.accept(packet));
packet.setFrom(SERVICE_JID2);
assertFalse(filter.accept(packet));
packet.setFrom(BASE_JID1);
assertFalse(filter.accept(packet));
packet.setFrom(FULL_JID1_R1);
assertFalse(filter.accept(packet));
}
}

View file

@ -8,6 +8,8 @@
package org.jivesoftware.smack.packet; package org.jivesoftware.smack.packet;
import static org.custommonkey.xmlunit.XMLAssert.*; import static org.custommonkey.xmlunit.XMLAssert.*;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -105,6 +107,7 @@ public class MessageTest {
assertXMLEqual(control, message.toXML()); assertXMLEqual(control, message.toXML());
} }
@Ignore
@Test @Test
public void multipleMessageBodiesTest() throws IOException, SAXException, ParserConfigurationException { public void multipleMessageBodiesTest() throws IOException, SAXException, ParserConfigurationException {
final String messageBody1 = "This is a test of the emergency broadcast system, 1."; final String messageBody1 = "This is a test of the emergency broadcast system, 1.";

View file

@ -19,6 +19,7 @@ import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.Diff;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.Packet;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.xmlpull.mxp1.MXParser; import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
@ -714,6 +715,7 @@ public class PacketParserUtilsTest {
} }
@Ignore
@Test @Test
public void multipleMessageBodiesParsingTest() throws Exception { public void multipleMessageBodiesParsingTest() throws Exception {
String control = XMLBuilder.create("message") String control = XMLBuilder.create("message")
@ -734,7 +736,6 @@ public class PacketParserUtilsTest {
.t("This is a test of the emergency broadcast system, 3.") .t("This is a test of the emergency broadcast system, 3.")
.asString(outputProperties); .asString(outputProperties);
Packet message = PacketParserUtils.parseMessage(getParser(control)); Packet message = PacketParserUtils.parseMessage(getParser(control));
assertXMLEqual(control, message.toXML()); assertXMLEqual(control, message.toXML());
} }

View file

@ -0,0 +1,41 @@
package org.jivesoftware.smackx.filetransfer;
import static org.junit.Assert.*;
import org.jivesoftware.smack.DummyConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class FileTransferNegotiatorTest {
private DummyConnection connection;
@Before
public void setUp() throws Exception {
// Uncomment this to enable debug output
//Connection.DEBUG_ENABLED = true;
connection = new DummyConnection();
connection.connect();
connection.login("me", "secret");
new ServiceDiscoveryManager(connection);
}
@After
public void tearDown() throws Exception {
if (connection != null)
connection.disconnect();
}
@Test
public void verifyForm() throws Exception
{
FileTransferNegotiator fileNeg = FileTransferNegotiator.getInstanceFor(connection);
fileNeg.negotiateOutgoingTransfer("me", "streamid", "file", 1024, null, 10);
Packet packet = connection.getSentPacket();
assertTrue(packet.toXML().indexOf("\"stream-method\" type=\"list-single\"") != -1);
}
}

View file

@ -0,0 +1,50 @@
package org.jivesoftware.smackx.muc;
import org.jivesoftware.smackx.FormField;
import org.jivesoftware.smackx.muc.RoomInfo;
import org.jivesoftware.smackx.packet.DataForm;
import org.jivesoftware.smackx.packet.DiscoverInfo;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class RoomInfoTest
{
@Test
public void validateRoomWithEmptyForm()
{
DataForm dataForm = new DataForm("result");
DiscoverInfo discoInfo = new DiscoverInfo();
discoInfo.addExtension(dataForm);
RoomInfo roomInfo = new RoomInfo(discoInfo);
assertTrue(roomInfo.getDescription().isEmpty());
assertTrue(roomInfo.getSubject().isEmpty());
assertEquals(-1, roomInfo.getOccupantsCount());
}
@Test
public void validateRoomWithForm()
{
DataForm dataForm = new DataForm("result");
FormField desc = new FormField("muc#roominfo_description");
desc.addValue("The place for all good witches!");
dataForm.addField(desc);
FormField subject = new FormField("muc#roominfo_subject");
subject.addValue("Spells");
dataForm.addField(subject);
FormField occupants = new FormField("muc#roominfo_occupants");
occupants.addValue("3");
dataForm.addField(occupants);
DiscoverInfo discoInfo = new DiscoverInfo();
discoInfo.addExtension(dataForm);
RoomInfo roomInfo = new RoomInfo(discoInfo);
assertEquals("The place for all good witches!", roomInfo.getDescription());
assertEquals("Spells", roomInfo.getSubject());
assertEquals(3, roomInfo.getOccupantsCount());
}
}

View file

@ -0,0 +1,16 @@
package org.jivesoftware.smackx.pubsub;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class ConfigureFormTest
{
@Test
public void checkChildrenAssocPolicy()
{
ConfigureForm form = new ConfigureForm(FormType.submit);
form.setChildrenAssociationPolicy(ChildrenAssociationPolicy.owners);
assertEquals(ChildrenAssociationPolicy.owners, form.getChildrenAssociationPolicy());
}
}

View file

@ -0,0 +1,107 @@
package org.jivesoftware.smackx.pubsub;
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.io.Reader;
import java.io.StringReader;
import org.jivesoftware.smack.ThreadedDummyConnection;
import org.jivesoftware.smackx.pubsub.provider.ItemsProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
public class ItemValidationTest
{
private ThreadedDummyConnection connection;
@Before
public void setUp() throws Exception
{
// Uncomment this to enable debug output
// Connection.DEBUG_ENABLED = true;
connection = new ThreadedDummyConnection();
connection.connect();
connection.login("me", "secret");
}
@After
public void tearDown() throws Exception
{
if (connection != null)
connection.disconnect();
}
@Test
public void verifyBasicItem() throws Exception
{
Item simpleItem = new Item();
String simpleCtrl = "<item />";
assertXMLEqual(simpleCtrl, simpleItem.toXML());
Item idItem = new Item("uniqueid");
String idCtrl = "<item id='uniqueid'/>";
assertXMLEqual(idCtrl, idItem.toXML());
Item itemWithNodeId = new Item("testId", "testNode");
String nodeIdCtrl = "<item id='testId' node='testNode' />";
assertXMLEqual(nodeIdCtrl, itemWithNodeId.toXML());
}
@Test
public void verifyPayloadItem() throws Exception
{
SimplePayload payload = new SimplePayload(null, null, "<data>This is the payload</data>");
PayloadItem<SimplePayload> simpleItem = new PayloadItem<SimplePayload>(payload);
String simpleCtrl = "<item>" + payload.toXML() + "</item>";
assertXMLEqual(simpleCtrl, simpleItem.toXML());
PayloadItem<SimplePayload> idItem = new PayloadItem<SimplePayload>("uniqueid", payload);
String idCtrl = "<item id='uniqueid'>" + payload.toXML() + "</item>";
assertXMLEqual(idCtrl, idItem.toXML());
PayloadItem<SimplePayload> itemWithNodeId = new PayloadItem<SimplePayload>("testId", "testNode", payload);
String nodeIdCtrl = "<item id='testId' node='testNode'>" + payload.toXML() + "</item>";
assertXMLEqual(nodeIdCtrl, itemWithNodeId.toXML());
}
// @Test
// public void parseBasicItemWithoutNode() throws Exception
// {
// XmlPullParser parser = new MXParser();
// Reader reader = new StringReader(
// "<event xmlns='http://jabber.org/protocol/pubsub#event'>" +
// "<items node='testNode'>" +
// "<item id='testid1' />" +
// "</items></event>");
// parser.setInput(reader);
// ItemsProvider itemsProvider = new ItemsProvider();
// ItemsExtension ext = (ItemsExtension) itemsProvider.parseExtension(parser);
// Item basicItem = (Item) ext.getItems().get(0);
//
// assertEquals("testid1", basicItem.getId());
// assertNull(basicItem.getNode());
// }
// @Test
// public void parseBasicItemNode() throws Exception
// {
// BlockingQueue<Item> itemQ = new ArrayBlockingQueue<Item>(1);
//
// setupListener(itemQ);
// Message itemMsg = getMessage("<item id='testid1' node='testNode'>");
// connection.addMessage(itemMsg);
//
// Item basicItem = itemQ.poll(2, TimeUnit.SECONDS);
//
// assertNotNull(basicItem);
// assertEquals("testid1", basicItem.getId());
// assertEquals("testNode", basicItem.getNode());
// }
}

View file

@ -52,11 +52,16 @@
package org.jivesoftware.smackx.packet; package org.jivesoftware.smackx.packet;
import java.util.*; import java.util.Iterator;
import org.jivesoftware.smack.*; import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.filter.*; import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.packet.*; import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.filter.PacketExtensionFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.ThreadFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.test.SmackTestCase; import org.jivesoftware.smack.test.SmackTestCase;
/** /**
@ -70,7 +75,7 @@ public class XHTMLExtensionTest extends SmackTestCase {
private int bodiesReceived; private int bodiesReceived;
public XHTMLExtensionTest(String name) { public XHTMLExtensionTest(String name) {
super(name); super(name);
} }
/** /**
@ -79,27 +84,27 @@ public class XHTMLExtensionTest extends SmackTestCase {
* 1. User_1 will send a message with formatted text (XHTML) to user_2 * 1. User_1 will send a message with formatted text (XHTML) to user_2
*/ */
public void testSendSimpleXHTMLMessage() { public void testSendSimpleXHTMLMessage() {
// User1 creates a chat with user2 // User1 creates a chat with user2
Chat chat1 = getConnection(0).getChatManager().createChat(getBareJID(1), null); Chat chat1 = getConnection(0).getChatManager().createChat(getBareJID(1), null);
// User1 creates a message to send to user2 // User1 creates a message to send to user2
Message msg = new Message(); Message msg = new Message();
msg.setSubject("Any subject you want"); msg.setSubject("Any subject you want");
msg.setBody("Hey John, this is my new green!!!!"); msg.setBody("Hey John, this is my new green!!!!");
// Create a XHTMLExtension Package and add it to the message // Create a XHTMLExtension Package and add it to the message
XHTMLExtension xhtmlExtension = new XHTMLExtension(); XHTMLExtension xhtmlExtension = new XHTMLExtension();
xhtmlExtension.addBody( xhtmlExtension.addBody(
"<body><p style='font-size:large'>Hey John, this is my new <span style='color:green'>green</span><em>!!!!</em></p></body>"); "<body><p style='font-size:large'>Hey John, this is my new <span style='color:green'>green</span><em>!!!!</em></p></body>");
msg.addExtension(xhtmlExtension); msg.addExtension(xhtmlExtension);
// User1 sends the message that contains the XHTML to user2 // User1 sends the message that contains the XHTML to user2
try { try {
chat1.sendMessage(msg); chat1.sendMessage(msg);
Thread.sleep(200); Thread.sleep(200);
} }
catch (Exception e) { catch (Exception e) {
fail("An error occured sending the message with XHTML"); fail("An error occured sending the message with XHTML");
} }
} }
/** /**
@ -111,48 +116,48 @@ public class XHTMLExtensionTest extends SmackTestCase {
* something is wrong * something is wrong
*/ */
public void testSendSimpleXHTMLMessageAndDisplayReceivedXHTMLMessage() { public void testSendSimpleXHTMLMessageAndDisplayReceivedXHTMLMessage() {
// Create a chat for each connection // Create a chat for each connection
Chat chat1 = getConnection(0).getChatManager().createChat(getBareJID(1), null); Chat chat1 = getConnection(0).getChatManager().createChat(getBareJID(1), null);
final PacketCollector chat2 = getConnection(1).createPacketCollector( final PacketCollector chat2 = getConnection(1).createPacketCollector(
new ThreadFilter(chat1.getThreadID())); new ThreadFilter(chat1.getThreadID()));
// User1 creates a message to send to user2 // User1 creates a message to send to user2
Message msg = new Message(); Message msg = new Message();
msg.setSubject("Any subject you want"); msg.setSubject("Any subject you want");
msg.setBody("Hey John, this is my new green!!!!"); msg.setBody("Hey John, this is my new green!!!!");
// Create a XHTMLExtension Package and add it to the message // Create a XHTMLExtension Package and add it to the message
XHTMLExtension xhtmlExtension = new XHTMLExtension(); XHTMLExtension xhtmlExtension = new XHTMLExtension();
xhtmlExtension.addBody( xhtmlExtension.addBody(
"<body><p style='font-size:large'>Hey John, this is my new <span style='color:green'>green</span><em>!!!!</em></p></body>"); "<body><p style='font-size:large'>Hey John, this is my new <span style='color:green'>green</span><em>!!!!</em></p></body>");
msg.addExtension(xhtmlExtension); msg.addExtension(xhtmlExtension);
// User1 sends the message that contains the XHTML to user2 // User1 sends the message that contains the XHTML to user2
try { try {
chat1.sendMessage(msg); chat1.sendMessage(msg);
} }
catch (Exception e) { catch (Exception e) {
fail("An error occured sending the message with XHTML"); fail("An error occured sending the message with XHTML");
} }
Packet packet = chat2.nextResult(2000); Packet packet = chat2.nextResult(2000);
Message message = (Message) packet; Message message = (Message) packet;
assertNotNull("Body is null", message.getBody()); assertNotNull("Body is null", message.getBody());
try { try {
xhtmlExtension = xhtmlExtension =
(XHTMLExtension) message.getExtension( (XHTMLExtension) message.getExtension(
"html", "html",
"http://jabber.org/protocol/xhtml-im"); "http://jabber.org/protocol/xhtml-im");
assertNotNull( assertNotNull(
"Message without extension \"http://jabber.org/protocol/xhtml-im\"", "Message without extension \"http://jabber.org/protocol/xhtml-im\"",
xhtmlExtension); xhtmlExtension);
assertTrue("Message without XHTML bodies", xhtmlExtension.getBodiesCount() > 0); assertTrue("Message without XHTML bodies", xhtmlExtension.getBodiesCount() > 0);
for (Iterator it = xhtmlExtension.getBodies(); it.hasNext();) { for (Iterator it = xhtmlExtension.getBodies(); it.hasNext();) {
String body = (String) it.next(); String body = (String) it.next();
System.out.println(body); System.out.println(body);
} }
} }
catch (ClassCastException e) { catch (ClassCastException e) {
fail("ClassCastException - Most probable cause is that smack providers is misconfigured"); fail("ClassCastException - Most probable cause is that smack providers is misconfigured");
} }
} }
/** /**
@ -164,22 +169,23 @@ public class XHTMLExtensionTest extends SmackTestCase {
* something is wrong * something is wrong
*/ */
public void testSendComplexXHTMLMessageAndDisplayReceivedXHTMLMessage() { public void testSendComplexXHTMLMessageAndDisplayReceivedXHTMLMessage() {
// Create a chat for each connection // Create a chat for each connection
Chat chat1 = getConnection(0).getChatManager().createChat(getBareJID(1), null); Chat chat1 = getConnection(0).getChatManager().createChat(getBareJID(1), null);
final PacketCollector chat2 = getConnection(1).createPacketCollector( final PacketCollector chat2 = getConnection(1).createPacketCollector(
new ThreadFilter(chat1.getThreadID())); new ThreadFilter(chat1.getThreadID()));
// Create a Listener that listens for Messages with the extension // Create a Listener that listens for Messages with the extension
//"http://jabber.org/protocol/xhtml-im" //"http://jabber.org/protocol/xhtml-im"
// This listener will listen on the conn2 and answer an ACK if everything is ok // This listener will listen on the conn2 and answer an ACK if everything is ok
PacketFilter packetFilter = PacketFilter packetFilter =
new PacketExtensionFilter("html", "http://jabber.org/protocol/xhtml-im"); new PacketExtensionFilter("html", "http://jabber.org/protocol/xhtml-im");
PacketListener packetListener = new PacketListener() { PacketListener packetListener = new PacketListener() {
public void processPacket(Packet packet) { @Override
public void processPacket(Packet packet) {
} }
}; };
getConnection(1).addPacketListener(packetListener, packetFilter); getConnection(1).addPacketListener(packetListener, packetFilter);
// User1 creates a message to send to user2 // User1 creates a message to send to user2
Message msg = new Message(); Message msg = new Message();
@ -194,47 +200,48 @@ public class XHTMLExtensionTest extends SmackTestCase {
"<body xml:lang=\"en-US\"><h1>awesome!</h1><p>As Emerson once said:</p><blockquote><p>A foolish consistency is the hobgoblin of little minds.</p></blockquote></body>"); "<body xml:lang=\"en-US\"><h1>awesome!</h1><p>As Emerson once said:</p><blockquote><p>A foolish consistency is the hobgoblin of little minds.</p></blockquote></body>");
msg.addExtension(xhtmlExtension); msg.addExtension(xhtmlExtension);
// User1 sends the message that contains the XHTML to user2 // User1 sends the message that contains the XHTML to user2
try { try {
bodiesSent = xhtmlExtension.getBodiesCount(); bodiesSent = xhtmlExtension.getBodiesCount();
bodiesReceived = 0; bodiesReceived = 0;
chat1.sendMessage(msg); chat1.sendMessage(msg);
} }
catch (Exception e) { catch (Exception e) {
fail("An error occured sending the message with XHTML"); fail("An error occured sending the message with XHTML");
} }
Packet packet = chat2.nextResult(2000); Packet packet = chat2.nextResult(2000);
int received = 0; int received = 0;
Message message = (Message) packet; Message message = (Message) packet;
assertNotNull("Body is null", message.getBody()); assertNotNull("Body is null", message.getBody());
try { try {
xhtmlExtension = xhtmlExtension =
(XHTMLExtension) message.getExtension( (XHTMLExtension) message.getExtension(
"html", "html",
"http://jabber.org/protocol/xhtml-im"); "http://jabber.org/protocol/xhtml-im");
assertNotNull( assertNotNull(
"Message without extension \"http://jabber.org/protocol/xhtml-im\"", "Message without extension \"http://jabber.org/protocol/xhtml-im\"",
xhtmlExtension); xhtmlExtension);
assertTrue("Message without XHTML bodies", xhtmlExtension.getBodiesCount() > 0); assertTrue("Message without XHTML bodies", xhtmlExtension.getBodiesCount() > 0);
for (Iterator it = xhtmlExtension.getBodies(); it.hasNext();) { for (Iterator it = xhtmlExtension.getBodies(); it.hasNext();) {
received++; received++;
System.out.println((String) it.next()); System.out.println((String) it.next());
} }
bodiesReceived = received; bodiesReceived = received;
} }
catch (ClassCastException e) { catch (ClassCastException e) {
fail("ClassCastException - Most probable cause is that smack providers is " + fail("ClassCastException - Most probable cause is that smack providers is " +
"misconfigured"); "misconfigured");
} }
// Wait half second so that the complete test can run // Wait half second so that the complete test can run
assertEquals( assertEquals(
"Number of sent and received XHTMP bodies does not match", "Number of sent and received XHTMP bodies does not match",
bodiesSent, bodiesSent,
bodiesReceived); bodiesReceived);
} }
@Override
protected int getMaxConnections() { protected int getMaxConnections() {
return 2; return 2;
} }
} }