1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-06-27 22:14:52 +02:00

add the ability to register for roster events before logging in (SMACK-156)

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@11826 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Henning Staib 2010-08-15 16:32:09 +00:00 committed by henning
parent 7a3818783b
commit a5693609b2
9 changed files with 469 additions and 88 deletions

View file

@ -22,7 +22,7 @@ A roster also allows you to organize users into groups such as "Friends" and
etc.<p> etc.<p>
A <tt>Roster</tt> instance is obtained using the <tt>Connection.getRoster()</tt> A <tt>Roster</tt> instance is obtained using the <tt>Connection.getRoster()</tt>
method, but only after successfully logging into a server. method.
<p class="subheader">Roster Entries</p> <p class="subheader">Roster Entries</p>
@ -70,7 +70,9 @@ a Roster in the Exodus XMPP client to the right.</p>
<p>The presence information will likely <p>The presence information will likely
change often, and it's also possible for the roster entries to change or be deleted. 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 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 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 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. similar code to update the roster UI with the changing information.

View file

@ -419,11 +419,15 @@ public abstract class Connection {
} }
/** /**
* Returns the roster for the user logged into the server. If the user has not yet * Returns the roster for the user.
* logged into the server (or if the user is logged in anonymously), this method will return * <p>
* <tt>null</tt>. * This method will never return <code>null</code>, instead if the user has not yet logged into
* the server or is logged in anonymously all modifying methods of the returned roster object
* like {@link Roster#createEntry(String, String, String[])},
* {@link Roster#removeEntry(RosterEntry)} , etc. except adding or removing
* {@link RosterListener}s will throw an IllegalStateException.
* *
* @return the user's roster, or <tt>null</tt> if the user has not logged in yet. * @return the user's roster.
*/ */
public abstract Roster getRoster(); public abstract Roster getRoster();

View file

@ -62,7 +62,7 @@ public class Roster {
private final List<RosterListener> rosterListeners; private final List<RosterListener> rosterListeners;
private Map<String, Map<String, Presence>> presenceMap; private Map<String, Map<String, Presence>> presenceMap;
// The roster is marked as initialized when at least a single roster packet // The roster is marked as initialized when at least a single roster packet
// has been recieved and processed. // has been received and processed.
boolean rosterInitialized = false; boolean rosterInitialized = false;
private PresencePacketListener presencePacketListener; private PresencePacketListener presencePacketListener;
@ -111,8 +111,10 @@ public class Roster {
PacketFilter presenceFilter = new PacketTypeFilter(Presence.class); PacketFilter presenceFilter = new PacketTypeFilter(Presence.class);
presencePacketListener = new PresencePacketListener(); presencePacketListener = new PresencePacketListener();
connection.addPacketListener(presencePacketListener, presenceFilter); connection.addPacketListener(presencePacketListener, presenceFilter);
// Listen for connection events // Listen for connection events
connection.addConnectionListener(new ConnectionListener() { final ConnectionListener connectionListener = new AbstractConnectionListener() {
public void connectionClosed() { public void connectionClosed() {
// Changes the presence available contacts to unavailable // Changes the presence available contacts to unavailable
setOfflinePresences(); setOfflinePresences();
@ -123,18 +125,22 @@ public class Roster {
setOfflinePresences(); setOfflinePresences();
} }
public void reconnectingIn(int seconds) { };
// Ignore
} // if not connected add listener after successful login
if(!this.connection.isConnected()) {
public void reconnectionFailed(Exception e) { Connection.addConnectionCreationListener(new ConnectionCreationListener() {
// Ignore
} public void connectionCreated(Connection connection) {
if(connection.equals(Roster.this.connection)) {
public void reconnectionSuccessful() { Roster.this.connection.addConnectionListener(connectionListener);
// Ignore }
}
}); }
});
} else {
connection.addConnectionListener(connectionListener);
}
} }
/** /**
@ -171,8 +177,17 @@ public class Roster {
* Reloads the entire roster from the server. This is an asynchronous operation, * Reloads the entire roster from the server. This is an asynchronous operation,
* which means the method will return immediately, and the roster will be * which means the method will return immediately, and the roster will be
* reloaded at a later point when the server responds to the reload request. * reloaded at a later point when the server responds to the reload request.
*
* @throws IllegalStateException if connection is not logged in or logged in anonymously
*/ */
public void reload() { public void reload() {
if (!connection.isAuthenticated()) {
throw new IllegalStateException("Not logged in to server.");
}
if (connection.isAnonymous()) {
throw new IllegalStateException("Anonymous users can't have a roster.");
}
connection.sendPacket(new RosterPacket()); connection.sendPacket(new RosterPacket());
} }
@ -206,11 +221,19 @@ public class Roster {
* *
* @param name the name of the group. * @param name the name of the group.
* @return a new group. * @return a new group.
* @throws IllegalStateException if connection is not logged in or logged in anonymously
*/ */
public RosterGroup createGroup(String name) { public RosterGroup createGroup(String name) {
if (!connection.isAuthenticated()) {
throw new IllegalStateException("Not logged in to server.");
}
if (connection.isAnonymous()) {
throw new IllegalStateException("Anonymous users can't have a roster.");
}
if (groups.containsKey(name)) { if (groups.containsKey(name)) {
throw new IllegalArgumentException("Group with name " + name + " alread exists."); throw new IllegalArgumentException("Group with name " + name + " alread exists.");
} }
RosterGroup group = new RosterGroup(name, connection); RosterGroup group = new RosterGroup(name, connection);
groups.put(name, group); groups.put(name, group);
return group; return group;
@ -225,8 +248,16 @@ public class Roster {
* @param groups the list of group names the entry will belong to, or <tt>null</tt> if the * @param groups the list of group names the entry will belong to, or <tt>null</tt> if the
* the roster entry won't belong to a group. * the roster entry won't belong to a group.
* @throws XMPPException if an XMPP exception occurs. * @throws XMPPException if an XMPP exception occurs.
* @throws IllegalStateException if connection is not logged in or logged in anonymously
*/ */
public void createEntry(String user, String name, String[] groups) throws XMPPException { public void createEntry(String user, String name, String[] groups) throws XMPPException {
if (!connection.isAuthenticated()) {
throw new IllegalStateException("Not logged in to server.");
}
if (connection.isAnonymous()) {
throw new IllegalStateException("Anonymous users can't have a roster.");
}
// Create and send roster entry creation packet. // Create and send roster entry creation packet.
RosterPacket rosterPacket = new RosterPacket(); RosterPacket rosterPacket = new RosterPacket();
rosterPacket.setType(IQ.Type.SET); rosterPacket.setType(IQ.Type.SET);
@ -267,8 +298,16 @@ public class Roster {
* *
* @param entry a roster entry. * @param entry a roster entry.
* @throws XMPPException if an XMPP error occurs. * @throws XMPPException if an XMPP error occurs.
* @throws IllegalStateException if connection is not logged in or logged in anonymously
*/ */
public void removeEntry(RosterEntry entry) throws XMPPException { public void removeEntry(RosterEntry entry) throws XMPPException {
if (!connection.isAuthenticated()) {
throw new IllegalStateException("Not logged in to server.");
}
if (connection.isAnonymous()) {
throw new IllegalStateException("Anonymous users can't have a roster.");
}
// Only remove the entry if it's in the entry list. // Only remove the entry if it's in the entry list.
// The actual removal logic takes place in RosterPacketListenerprocess>>Packet(Packet) // The actual removal logic takes place in RosterPacketListenerprocess>>Packet(Packet)
if (!entries.containsKey(entry.getUser())) { if (!entries.containsKey(entry.getUser())) {
@ -389,7 +428,7 @@ public class Roster {
} }
/** /**
* Returns an unmodiable collections of all the roster groups. * Returns an unmodifiable collections of all the roster groups.
* *
* @return an iterator for all roster groups. * @return an iterator for all roster groups.
*/ */
@ -859,14 +898,14 @@ public class Roster {
// We have the list of old and new group names. We now need to // We have the list of old and new group names. We now need to
// remove the entry from the all the groups it may no longer belong // remove the entry from the all the groups it may no longer belong
// to. We do this by subracting the new group set from the old. // to. We do this by subtracting the new group set from the old.
for (String newGroupName : newGroupNames) { for (String newGroupName : newGroupNames) {
currentGroupNames.remove(newGroupName); currentGroupNames.remove(newGroupName);
} }
} }
// Loop through any groups that remain and remove the entries. // Loop through any groups that remain and remove the entries.
// This is neccessary for the case of remote entry removals. // This is necessary for the case of remote entry removals.
for (String groupName : currentGroupNames) { for (String groupName : currentGroupNames) {
RosterGroup group = getGroup(groupName); RosterGroup group = getGroup(groupName);
group.removeEntryLocal(entry); group.removeEntryLocal(entry);

View file

@ -119,7 +119,7 @@ public class XMPPConnection extends Connection {
} }
/** /**
* Creates a new XMPP conection in the same way {@link #XMPPConnection(String,CallbackHandler)} does, but * Creates a new XMPP connection in the same way {@link #XMPPConnection(String,CallbackHandler)} does, but
* with no callback handler for password prompting of the keystore. This will work * with no callback handler for password prompting of the keystore. This will work
* in most cases, provided the client is not required to provide a certificate to * in most cases, provided the client is not required to provide a certificate to
* the server. * the server.
@ -135,7 +135,7 @@ public class XMPPConnection extends Connection {
} }
/** /**
* Creates a new XMPP conection in the same way {@link #XMPPConnection(ConnectionConfiguration,CallbackHandler)} does, but * Creates a new XMPP connection in the same way {@link #XMPPConnection(ConnectionConfiguration,CallbackHandler)} does, but
* with no callback handler for password prompting of the keystore. This will work * with no callback handler for password prompting of the keystore. This will work
* in most cases, provided the client is not required to provide a certificate to * in most cases, provided the client is not required to provide a certificate to
* the server. * the server.
@ -210,7 +210,7 @@ public class XMPPConnection extends Connection {
* @param resource the resource. * @param resource the resource.
* @throws XMPPException if an error occurs. * @throws XMPPException if an error occurs.
* @throws IllegalStateException if not connected to the server, or already logged in * @throws IllegalStateException if not connected to the server, or already logged in
* to the serrver. * 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()) {
@ -257,7 +257,11 @@ public class XMPPConnection extends Connection {
useCompression(); useCompression();
} }
// Create the roster if it is not a reconnection. // Indicate that we're now authenticated.
authenticated = true;
anonymous = false;
// Create the roster if it is not a reconnection or roster already created by getRoster()
if (this.roster == null) { if (this.roster == null) {
this.roster = new Roster(this); this.roster = new Roster(this);
} }
@ -270,11 +274,7 @@ public class XMPPConnection extends Connection {
packetWriter.sendPacket(new Presence(Presence.Type.available)); packetWriter.sendPacket(new Presence(Presence.Type.available));
} }
// Indicate that we're now authenticated. // Stores the authentication for future reconnection
authenticated = true;
anonymous = false;
// Stores the autentication for future reconnection
config.setLoginInfo(username, password, resource); config.setLoginInfo(username, password, resource);
// If debugging is enabled, change the the debug window title to include the // If debugging is enabled, change the the debug window title to include the
@ -294,7 +294,7 @@ public class XMPPConnection extends Connection {
* *
* @throws XMPPException if an error occurs or anonymous logins are not supported 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 * @throws IllegalStateException if not connected to the server, or already logged in
* to the serrver. * to the server.
*/ */
public synchronized void loginAnonymously() throws XMPPException { public synchronized void loginAnonymously() throws XMPPException {
if (!isConnected()) { if (!isConnected()) {
@ -324,9 +324,6 @@ public class XMPPConnection extends Connection {
useCompression(); useCompression();
} }
// Anonymous users can't have a roster.
roster = null;
// Set presence to online. // Set presence to online.
packetWriter.sendPacket(new Presence(Presence.Type.available)); packetWriter.sendPacket(new Presence(Presence.Type.available));
@ -344,9 +341,18 @@ public class XMPPConnection extends Connection {
} }
public Roster getRoster() { public Roster getRoster() {
if (roster == null) { // synchronize against login()
return null; synchronized(this) {
// if connection is authenticated the roster is already set by login()
// or a previous call to getRoster()
if (!isAuthenticated() || isAnonymous()) {
if (roster == null) {
roster = new Roster(this);
}
return roster;
}
} }
if (!config.isRosterLoadedAtLogin()) { if (!config.isRosterLoadedAtLogin()) {
roster.reload(); roster.reload();
} }

View file

@ -0,0 +1,92 @@
package org.jivesoftware.smack;
import static org.junit.Assert.*;
import java.util.Collection;
import java.util.Iterator;
import org.jivesoftware.smack.Roster.SubscriptionMode;
import org.jivesoftware.smack.packet.Presence;
import org.junit.Before;
import org.junit.Test;
/**
* Tests the behavior of the roster if the connection is not authenticated yet.
*
* @author Henning Staib
*/
public class RosterOfflineTest {
Connection connection;
Roster roster;
@Before
public void setup() {
this.connection = new XMPPConnection("localhost");
assertFalse(connection.isConnected());
roster = connection.getRoster();
assertNotNull(roster);
}
@Test
public void shouldThrowNoExceptionOnGetterMethods() {
// all getter methods should work
assertFalse(roster.contains("test"));
Collection<RosterEntry> entries = roster.getEntries();
assertTrue(entries.size() == 0);
assertNull(roster.getEntry("test"));
assertEquals(0, roster.getEntryCount());
assertNull(roster.getGroup("test"));
assertEquals(0, roster.getGroupCount());
Collection<RosterGroup> groups = roster.getGroups();
assertEquals(0, groups.size());
Presence presence = roster.getPresence("test");
assertEquals(Presence.Type.unavailable, presence.getType());
Presence presenceResource = roster.getPresenceResource("test");
assertEquals(Presence.Type.unavailable, presenceResource.getType());
Iterator<Presence> iterator = roster.getPresences("test");
assertTrue(iterator.hasNext());
assertEquals(Presence.Type.unavailable, iterator.next().getType());
assertFalse(iterator.hasNext());
assertEquals(0, roster.getUnfiledEntries().size());
assertEquals(0, roster.getUnfiledEntryCount());
roster.setSubscriptionMode(SubscriptionMode.accept_all);
assertEquals(SubscriptionMode.accept_all, roster.getSubscriptionMode());
}
@Test(expected = IllegalStateException.class)
public void shouldThrowExceptionOnCreateEntry() throws Exception {
roster.createEntry("test", "test", null);
}
@Test(expected = IllegalStateException.class)
public void shouldThrowExceptionOnCreateGroup() throws Exception {
roster.createGroup("test");
}
@Test(expected = IllegalStateException.class)
public void shouldThrowExceptionOnReload() throws Exception {
roster.reload();
}
@Test(expected = IllegalStateException.class)
public void shouldThrowExceptionRemoveEntry() throws Exception {
roster.removeEntry(null);
}
}

View file

@ -0,0 +1,34 @@
package org.jivesoftware.smack;
/**
* Run all tests defined in RosterTest but initialize the roster before connection is logged in and
* authenticated.
*
* @author Henning Staib
*/
public class RosterInitializedBeforeConnectTest extends RosterSmackTest {
public RosterInitializedBeforeConnectTest(String name) {
super(name);
}
protected boolean createOfflineConnections() {
return true;
}
protected void setUp() throws Exception {
super.setUp();
// initialize all rosters before login
for (int i = 0; i < getMaxConnections(); i++) {
XMPPConnection connection = getConnection(i);
assertFalse(connection.isConnected());
Roster roster = connection.getRoster();
assertNotNull(roster);
connectAndLogin(i);
}
}
}

View file

@ -0,0 +1,193 @@
package org.jivesoftware.smack;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.test.SmackTestCase;
/**
* Test cases for adding the {@link RosterListener} in different connection states.
*
* @author Henning Staib
*/
public class RosterListenerTest extends SmackTestCase {
public RosterListenerTest(String arg0) {
super(arg0);
}
public void testAddingRosterListenerBeforeConnect() throws Exception {
int inviterIndex = 0;
int inviteeIndex = 1;
XMPPConnection inviterConnection = getConnection(inviterIndex);
connectAndLogin(inviterIndex);
assertTrue("Inviter is not online", inviterConnection.isConnected());
Roster inviterRoster = inviterConnection.getRoster();
// add user1 to roster to create roster events stored at XMPP server
inviterRoster.createEntry(getBareJID(inviteeIndex), getUsername(inviteeIndex), null);
Thread.sleep(500); // wait for XMPP server
XMPPConnection inviteeConnection = getConnection(inviteeIndex);
assertFalse("Invitee is already online", inviteeConnection.isConnected());
// collector for added entries
final List<String> addedEntries = new ArrayList<String>();
// register roster listener before login
Roster inviteeRoster = inviteeConnection.getRoster();
inviteeRoster.addRosterListener(new RosterListener() {
public void presenceChanged(Presence presence) {
// ignore
}
public void entriesUpdated(Collection<String> addresses) {
// ignore
}
public void entriesDeleted(Collection<String> addresses) {
// ignore
}
public void entriesAdded(Collection<String> addresses) {
addedEntries.addAll(addresses);
}
});
// connect after adding the listener
connectAndLogin(inviteeIndex);
Thread.sleep(500); // wait for packets to be processed
assertNotNull("inviter is not in roster", inviteeRoster.getEntry(getBareJID(inviterIndex)));
assertTrue("got no event for adding inviter",
addedEntries.contains(getBareJID(inviterIndex)));
}
public void testAddingRosterListenerAfterConnect() throws Exception {
int inviterIndex = 0;
int inviteeIndex = 1;
XMPPConnection inviterConnection = getConnection(inviterIndex);
connectAndLogin(inviterIndex);
assertTrue("Inviter is not online", inviterConnection.isConnected());
Roster inviterRoster = inviterConnection.getRoster();
// add user1 to roster to create roster events stored at XMPP server
inviterRoster.createEntry(getBareJID(inviteeIndex), getUsername(inviteeIndex), null);
Thread.sleep(500); // wait for XMPP server
XMPPConnection inviteeConnection = getConnection(inviteeIndex);
connectAndLogin(inviteeIndex);
assertTrue("Invitee is not online", inviteeConnection.isConnected());
// collector for added entries
final List<String> addedEntries = new ArrayList<String>();
// wait to simulate concurrency before adding listener
Thread.sleep(200);
// register roster listener after login
Roster inviteeRoster = inviteeConnection.getRoster();
inviteeRoster.addRosterListener(new RosterListener() {
public void presenceChanged(Presence presence) {
// ignore
}
public void entriesUpdated(Collection<String> addresses) {
// ignore
}
public void entriesDeleted(Collection<String> addresses) {
// ignore
}
public void entriesAdded(Collection<String> addresses) {
addedEntries.addAll(addresses);
}
});
Thread.sleep(500); // wait for packets to be processed
assertNotNull("Inviter is not in roster", inviteeRoster.getEntry(getBareJID(inviterIndex)));
assertFalse("got event for adding inviter", addedEntries.contains(getBareJID(inviterIndex)));
}
@Override
protected void tearDown() throws Exception {
cleanUpRoster();
super.tearDown();
}
protected int getMaxConnections() {
return 2;
}
protected boolean createOfflineConnections() {
return true;
}
/**
* Clean up all the entries in the roster
*/
private void cleanUpRoster() {
for (int i = 0; i < getMaxConnections(); i++) {
// Delete all the entries from the roster
Roster roster = getConnection(i).getRoster();
for (RosterEntry entry : roster.getEntries()) {
try {
roster.removeEntry(entry);
Thread.sleep(100);
}
catch (XMPPException e) {
e.printStackTrace();
fail(e.getMessage());
}
catch (InterruptedException e) {
// ignore
}
}
try {
Thread.sleep(700);
}
catch (InterruptedException e) {
fail(e.getMessage());
}
}
// Wait up to 6 seconds to receive roster removal notifications
long initial = System.currentTimeMillis();
while (System.currentTimeMillis() - initial < 6000
&& (getConnection(0).getRoster().getEntryCount() != 0 || getConnection(1).getRoster().getEntryCount() != 0)) {
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
}
}
assertEquals("Wrong number of entries in connection 0", 0,
getConnection(0).getRoster().getEntryCount());
assertEquals("Wrong number of groups in connection 0", 0,
getConnection(0).getRoster().getGroupCount());
assertEquals("Wrong number of entries in connection 1", 0,
getConnection(1).getRoster().getEntryCount());
assertEquals("Wrong number of groups in connection 1", 0,
getConnection(1).getRoster().getGroupCount());
}
}

View file

@ -446,18 +446,12 @@ public class RosterSmackTest extends SmackTestCase {
} }
assertNull("The group Amigos still exists", roster.getGroup("Amigos")); assertNull("The group Amigos still exists", roster.getGroup("Amigos"));
assertNotNull("The group with no name does not exist", roster.getGroup("")); assertNull("The group with no name does exist", roster.getGroup(""));
assertEquals("There are still groups in the roster", 0, roster.getGroupCount());
assertEquals( assertEquals(
"Wrong number of entries in the group with no name", "Wrong number of unfiled entries",
2, 2,
roster.getGroup("").getEntryCount()); roster.getUnfiledEntryCount());
/*assertEquals("There are still groups in the roster", 0, roster.getGroupCount());
assertEquals(
"Wrong number of entries in the group \"\" ",
2,
roster.getUnfiledEntryCount());*/
Thread.sleep(200); Thread.sleep(200);
} }

View file

@ -23,8 +23,6 @@ import junit.framework.TestCase;
import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.packet.XMPPError.Type;
import org.xmlpull.mxp1.MXParser; import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
@ -96,6 +94,23 @@ public abstract class SmackTestCase extends TestCase {
return null; return null;
} }
/**
* Returns <code>false</code> if the connections initialized by the test case will be
* automatically connected to the XMPP server.
* Returns <code>true</code> if the connections initialized by the test case will
* NOT be connected to the XMPP server. To connect the connections invoke
* {@link #connectAndLogin(int)}.
* <p>
* Connections are connected by default.
* Overwrite this method if the test case needs unconnected connections.
*
* @return <code>true</code> if connections should NOT be connected automatically,
* <code>false</code> if connections should be connected automatically.
*/
protected boolean createOfflineConnections() {
return false;
}
/** /**
* Returns the XMPPConnection located at the requested position. Each test case holds a * Returns the XMPPConnection located at the requested position. Each test case holds a
* pool of connections which is initialized while setting up the test case. The maximum * pool of connections which is initialized while setting up the test case. The maximum
@ -209,7 +224,8 @@ public abstract class SmackTestCase extends TestCase {
// Connect to the server // Connect to the server
for (int i = 0; i < getMaxConnections(); i++) { for (int i = 0; i < getMaxConnections(); i++) {
connections[i] = createConnection(); connections[i] = createConnection();
connections[i].connect(); if (!createOfflineConnections())
connections[i].connect();
} }
// Use the host name that the server reports. This is a good idea in most // Use the host name that the server reports. This is a good idea in most
// cases, but could fail if the user set a hostname in their XMPP server // cases, but could fail if the user set a hostname in their XMPP server
@ -217,41 +233,37 @@ public abstract class SmackTestCase extends TestCase {
host = connections[0].getHost(); host = connections[0].getHost();
serviceName = connections[0].getServiceName(); serviceName = connections[0].getServiceName();
for (int i = 0; i < getMaxConnections(); i++) { if (!createOfflineConnections()) {
String password = usernamePrefix + (i+1); for (int i = 0; i < getMaxConnections(); i++) {
String currentUser = password; String password = usernamePrefix + (i+1);
String currentUser = password;
if (passwordPrefix != null)
password = (samePassword ? passwordPrefix : passwordPrefix + (i+1)); if (passwordPrefix != null)
password = (samePassword ? passwordPrefix : passwordPrefix + (i+1));
try
{ try {
getConnection(i).login(currentUser, password, "Smack"); getConnection(i).login(currentUser, password, "Smack");
} } catch (XMPPException e) {
catch (XMPPException e) e.printStackTrace();
{
e.printStackTrace(); // Create the test accounts
if (!getConnection(0).getAccountManager().supportsAccountCreation())
// Create the test accounts fail("Server does not support account creation");
if (!getConnection(0).getAccountManager().supportsAccountCreation())
fail("Server does not support account creation"); // Create the account and try logging in again as the
// same user.
// Create the account and try logging in again as the try {
// same user. createAccount(i, currentUser, password);
try } catch (Exception e1) {
{ e1.printStackTrace();
createAccount(i, currentUser, password); fail("Could not create user: " + currentUser);
} }
catch (Exception e1) i--;
{ }
e1.printStackTrace(); }
fail("Could not create user: " + currentUser); // Let the server process the available presences
} Thread.sleep(150);
i--;
}
} }
// Let the server process the available presences
Thread.sleep(150);
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -261,16 +273,21 @@ public abstract class SmackTestCase extends TestCase {
protected void connectAndLogin(int connectionIndex) throws XMPPException protected void connectAndLogin(int connectionIndex) throws XMPPException
{ {
String password = usernamePrefix + connectionIndex; String password = usernamePrefix + (connectionIndex + 1);
if (passwordPrefix != null) if (passwordPrefix != null)
password = (samePassword ? passwordPrefix : passwordPrefix + connectionIndex); password = (samePassword ? passwordPrefix : passwordPrefix + (connectionIndex + 1));
XMPPConnection con = getConnection(connectionIndex); XMPPConnection con = getConnection(connectionIndex);
if (!con.isConnected()) if (!con.isConnected())
con.connect(); con.connect();
con.login(usernamePrefix + connectionIndex, password, "Smack"); try {
con.login(usernamePrefix + (connectionIndex + 1), password, "Smack");
} catch (XMPPException e) {
createAccount(connectionIndex, usernamePrefix + (connectionIndex + 1), password);
con.login(usernamePrefix + (connectionIndex + 1), password, "Smack");
}
} }
protected void disconnect(int connectionIndex) throws XMPPException protected void disconnect(int connectionIndex) throws XMPPException