diff --git a/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java b/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java index db20c06f2..d59c46643 100644 --- a/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java +++ b/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java @@ -223,11 +223,8 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection { } @Override - protected void loginNonAnonymously() + protected void loginNonAnonymously(String username, String password, String resource) throws XMPPException, SmackException, IOException { - String password = config.getPassword(); - String resource = config.getResource(); - String username = config.getUsername(); if (saslAuthentication.hasNonAnonymousAuthentication()) { // Authenticate using SASL if (password != null) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index 1fe7bafef..c06ad1436 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -73,6 +73,7 @@ import org.jivesoftware.smack.provider.ProviderManager; import org.jivesoftware.smack.rosterstore.RosterStore; import org.jivesoftware.smack.util.DNSUtil; import org.jivesoftware.smack.util.PacketParserUtils; +import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.dns.HostAddress; import org.jxmpp.util.XmppStringUtils; import org.xmlpull.v1.XmlPullParser; @@ -359,6 +360,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { */ protected abstract void connectInternal() throws SmackException, IOException, XMPPException; + private String usedUsername, usedPassword, usedResource; + /** * Logs in to the server using the strongest authentication mode supported by * the server, then sets presence to available. If the server supports SASL authentication @@ -388,11 +391,56 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { if (isAnonymous()) { loginAnonymously(); } else { - loginNonAnonymously(); + // The previously used username, password and resource take over precedence over the + // ones from the connection configuration + String username = usedUsername != null ? usedUsername : config.getUsername(); + String password = usedPassword != null ? usedPassword : config.getPassword(); + String resource = usedResource != null ? usedResource : config.getResource(); + login(username, password, resource); } } - protected abstract void loginNonAnonymously() throws XMPPException, SmackException, IOException; + /** + * Same as {@link #login(String, String, String)}, but takes the resource from the connection + * configuration. + * + * @param username + * @param password + * @throws XMPPException + * @throws SmackException + * @throws IOException + * @see #login + */ + public void login(String username, String password) throws XMPPException, SmackException, + IOException { + login(username, password, config.getResource()); + } + + /** + * Login with the given username. You may omit the password if a callback handler is used. If + * resource is null, then the server will generate one. + * + * @param username + * @param password + * @param resource + * @throws XMPPException + * @throws SmackException + * @throws IOException + * @see #login + */ + public void login(String username, String password, String resource) throws XMPPException, + SmackException, IOException { + if (StringUtils.isNullOrEmpty(username)) { + throw new IllegalArgumentException("Username must not be null or empty"); + } + usedUsername = username; + usedPassword = password; + usedResource = resource; + loginNonAnonymously(username, password, resource); + } + + protected abstract void loginNonAnonymously(String username, String password, String resource) + throws XMPPException, SmackException, IOException; protected abstract void loginAnonymously() throws XMPPException, SmackException, IOException; @@ -471,8 +519,8 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } @Override - public boolean isAnonymous() { - return config.isAnonymous(); + public final boolean isAnonymous() { + return config.getUsername() == null && usedUsername == null; } private String serviceName; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java index 4745f2751..6790bc4bc 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/ConnectionConfiguration.java @@ -102,10 +102,6 @@ public abstract class ConnectionConfiguration { } password = builder.password; callbackHandler = builder.callbackHandler; - if (callbackHandler == null && (password == null || username == null) && !builder.anonymous) { - throw new IllegalArgumentException( - "Must provide either a username and password, a callback handler or set the connection configuration anonymous"); - } // Resource can be null, this means that the server must provide one resource = builder.resource; @@ -142,10 +138,6 @@ public abstract class ConnectionConfiguration { debuggerEnabled = builder.debuggerEnabled; } - public boolean isAnonymous() { - return username == null && callbackHandler == null; - } - /** * Returns the server name of the target server. * @@ -401,7 +393,6 @@ public abstract class ConnectionConfiguration { private HostnameVerifier hostnameVerifier; private String username; private String password; - private boolean anonymous; private String resource = "Smack"; private boolean sendPresence = true; private boolean rosterLoadedAtLogin = true; @@ -421,8 +412,7 @@ public abstract class ConnectionConfiguration { /** * Set the XMPP entities username and password. *

- * The username is the localpart of the entities JID, e.g. localpart@example.org. In order to - * create an anonymous connection, call {@link #makeAnonymous} instead. + * The username is the localpart of the entities JID, e.g. localpart@example.org. *

* * @param username @@ -435,22 +425,6 @@ public abstract class ConnectionConfiguration { return getThis(); } - /** - * Create a configuration for a anonymous XMPP connection. - *

- * Anonyous connections don't provide a username or other authentification credentials like a password. Instead - * the XMPP server, if supporting anonymous connections, will assign a username to the client. - *

- * - * @return a reference to this builder. - */ - public B makeAnonymous() { - this.username = null; - this.password = null; - anonymous = true; - return getThis(); - } - /** * Set the service name of this XMPP service (i.e., the XMPP domain). * diff --git a/smack-core/src/test/java/org/jivesoftware/smack/DummyConnection.java b/smack-core/src/test/java/org/jivesoftware/smack/DummyConnection.java index 2a5235d71..8a8503b30 100644 --- a/smack-core/src/test/java/org/jivesoftware/smack/DummyConnection.java +++ b/smack-core/src/test/java/org/jivesoftware/smack/DummyConnection.java @@ -45,7 +45,6 @@ import org.jivesoftware.smack.packet.TopLevelStreamElement; */ public class DummyConnection extends AbstractXMPPConnection { - private boolean anonymous = false; private boolean reconnect = false; private String connectionID; @@ -93,7 +92,6 @@ public class DummyConnection extends AbstractXMPPConnection { connectionID = null; roster = null; authenticated = false; - anonymous = false; for (ConnectionListener listener : getConnectionListeners()) { listener.connectionClosed(); @@ -123,11 +121,6 @@ public class DummyConnection extends AbstractXMPPConnection { return roster; } - @Override - public boolean isAnonymous() { - return anonymous; - } - @Override public boolean isSecureConnection() { return false; @@ -139,15 +132,14 @@ public class DummyConnection extends AbstractXMPPConnection { } @Override - protected void loginNonAnonymously() + protected void loginNonAnonymously(String username, String password, String resource) throws XMPPException { - user = config.getUsername() + user = username + "@" + config.getServiceName() + "/" - + (config.getResource() != null ? config.getResource() : "Test"); + + (resource != null ? resource : "Test"); roster = new Roster(this); - anonymous = false; authenticated = true; } @@ -159,7 +151,6 @@ public class DummyConnection extends AbstractXMPPConnection { if (isAuthenticated()) { throw new IllegalStateException("Already logged in to server."); } - anonymous = true; authenticated = true; } diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java index a51c6997e..d37af04e9 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java @@ -339,10 +339,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { } @Override - protected synchronized void loginNonAnonymously() throws XMPPException, SmackException, IOException { - String password = config.getPassword(); - String resource = config.getResource(); - String username = config.getUsername(); + protected synchronized void loginNonAnonymously(String username, String password, String resource) throws XMPPException, SmackException, IOException { if (saslAuthentication.hasNonAnonymousAuthentication()) { // Authenticate using SASL if (password != null) {