From 64e7b8a868a2c27d3b1b462c82c7cb22c487bbf0 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Fri, 14 Mar 2014 01:48:33 +0100 Subject: [PATCH] Move getRoster() to XMPPConnection Also remove the Exceptions from the signature of getRoster(). Extend ConnectionListener with connected() and authenticated() callbacks, required by Roster to be notified so that the Roster can be loaded *after* login. --- .../jivesoftware/smack/BOSHConnection.java | 80 ++--------------- .../smack/AbstractConnectionListener.java | 15 +++- .../smack/ConnectionListener.java | 12 +++ .../smack/ReconnectionManager.java | 20 +---- .../java/org/jivesoftware/smack/Roster.java | 55 +++++++----- .../jivesoftware/smack/XMPPConnection.java | 88 ++++++++++++++++++- .../smack/debugger/ConsoleDebugger.java | 8 ++ .../smackx/debugger/EnhancedDebugger.java | 3 +- .../filetransfer/FileTransferNegotiator.java | 18 +--- .../smackx/muc/MultiUserChat.java | 21 +---- .../smackx/muc/RoomListenerMultiplexor.java | 18 +--- .../jivesoftware/smackx/ping/PingManager.java | 16 ++-- .../smackx/jingle/JingleSession.java | 14 +-- .../org/jivesoftware/smack/PacketReader.java | 11 +-- .../org/jivesoftware/smack/TCPConnection.java | 74 ++-------------- 15 files changed, 193 insertions(+), 260 deletions(-) diff --git a/bosh/src/main/java/org/jivesoftware/smack/BOSHConnection.java b/bosh/src/main/java/org/jivesoftware/smack/BOSHConnection.java index bbbe206e7..db3192316 100644 --- a/bosh/src/main/java/org/jivesoftware/smack/BOSHConnection.java +++ b/bosh/src/main/java/org/jivesoftware/smack/BOSHConnection.java @@ -102,12 +102,6 @@ public class BOSHConnection extends XMPPConnection { */ private String user = null; - /** - * The roster maybe also called buddy list holds the list of the users contacts. - */ - private Roster roster = null; - - /** * Create a HTTP Binding connection to a XMPP server. * @@ -202,6 +196,7 @@ public class BOSHConnection extends XMPPConnection { + getHost() + ":" + getPort() + "."; throw new SmackException(errorMessage); } + callConnectionConnectedListener(); } public String getConnectionID() { @@ -214,42 +209,6 @@ public class BOSHConnection extends XMPPConnection { } } - public Roster getRoster() throws XMPPException, SmackException { - if (roster == null) { - return null; - } - if (!config.isRosterLoadedAtLogin()) { - roster.reload(); - } - // If this is the first time the user has asked for the roster after calling - // login, we want to wait for the server to send back the user's roster. - // This behavior shields API users from having to worry about the fact that - // roster operations are asynchronous, although they'll still have to listen - // for changes to the roster. Note: because of this waiting logic, internal - // Smack code should be wary about calling the getRoster method, and may - // need to access the roster object directly. - if (!roster.rosterInitialized) { - try { - synchronized (roster) { - long waitTime = SmackConfiguration.getDefaultPacketReplyTimeout(); - long start = System.currentTimeMillis(); - while (!roster.rosterInitialized) { - if (waitTime <= 0) { - break; - } - roster.wait(waitTime); - long now = System.currentTimeMillis(); - waitTime -= now - start; - start = now; - } - } - } catch (InterruptedException ie) { - // Ignore. - } - } - return roster; - } - public String getUser() { return user; } @@ -311,14 +270,6 @@ public class BOSHConnection extends XMPPConnection { } } - // Create the roster if it is not a reconnection. - if (this.roster == null) { - this.roster = new Roster(this); - } - if (config.isRosterLoadedAtLogin()) { - this.roster.reload(); - } - // Set presence to online. if (config.isSendPresence()) { sendPacket(new Presence(Presence.Type.available)); @@ -337,6 +288,7 @@ public class BOSHConnection extends XMPPConnection { if (config.isDebuggerEnabled() && debugger != null) { debugger.userHasLogged(user); } + callConnectionAuthenticatedListener(); } public void loginAnonymously() throws XMPPException, SmackException, IOException { @@ -361,9 +313,6 @@ public class BOSHConnection extends XMPPConnection { // Update the serviceName with the one returned by the server config.setServiceName(StringUtils.parseServer(response)); - // Anonymous users can't have a roster. - roster = null; - // Set presence to online. if (config.isSendPresence()) { sendPacket(new Presence(Presence.Type.available)); @@ -380,6 +329,7 @@ public class BOSHConnection extends XMPPConnection { if (config.isDebuggerEnabled() && debugger != null) { debugger.userHasLogged(user); } + callConnectionAuthenticatedListener(); } public void sendPacket(Packet packet) { @@ -431,17 +381,7 @@ public class BOSHConnection extends XMPPConnection { wasAuthenticated = false; isFirstInitialization = true; - // Notify connection listeners of the connection closing if done hasn't already been set. - for (ConnectionListener listener : getConnectionListeners()) { - try { - listener.connectionClosed(); - } - catch (Exception e) { - // Catch and print any exception so we can recover - // from a faulty listener and finish the shutdown process - e.printStackTrace(); - } - } + callConnectionClosedListener(); } /** @@ -612,17 +552,7 @@ public class BOSHConnection extends XMPPConnection { shutdown(new Presence(Presence.Type.unavailable)); // Print the stack trace to help catch the problem e.printStackTrace(); - // Notify connection listeners of the error. - for (ConnectionListener listener : getConnectionListeners()) { - try { - listener.connectionClosedOnError(e); - } - catch (Exception e2) { - // Catch and print any exception so we can recover - // from a faulty listener - e2.printStackTrace(); - } - } + callConnectionClosedOnErrorListener(e); } diff --git a/core/src/main/java/org/jivesoftware/smack/AbstractConnectionListener.java b/core/src/main/java/org/jivesoftware/smack/AbstractConnectionListener.java index 3e8cee6c8..bc8b27b8e 100644 --- a/core/src/main/java/org/jivesoftware/smack/AbstractConnectionListener.java +++ b/core/src/main/java/org/jivesoftware/smack/AbstractConnectionListener.java @@ -25,25 +25,38 @@ package org.jivesoftware.smack; * @author Henning Staib */ public class AbstractConnectionListener implements ConnectionListener { + @Override + public void connected(XMPPConnection connection) { + // do nothing + } + @Override + public void authenticated(XMPPConnection connection) { + // do nothing + } + + @Override public void connectionClosed() { // do nothing } + @Override public void connectionClosedOnError(Exception e) { // do nothing } + @Override public void reconnectingIn(int seconds) { // do nothing } + @Override public void reconnectionFailed(Exception e) { // do nothing } + @Override public void reconnectionSuccessful() { // do nothing } - } diff --git a/core/src/main/java/org/jivesoftware/smack/ConnectionListener.java b/core/src/main/java/org/jivesoftware/smack/ConnectionListener.java index 1f5b7e71c..7df1827be 100644 --- a/core/src/main/java/org/jivesoftware/smack/ConnectionListener.java +++ b/core/src/main/java/org/jivesoftware/smack/ConnectionListener.java @@ -28,6 +28,18 @@ package org.jivesoftware.smack; */ public interface ConnectionListener { + /** + * TODO + * @param connection + */ + public void connected(XMPPConnection connection); + + /** + * TODO + * @param connection + */ + public void authenticated(XMPPConnection connection); + /** * Notification that the connection was closed normally or that the reconnection * process has been aborted. diff --git a/core/src/main/java/org/jivesoftware/smack/ReconnectionManager.java b/core/src/main/java/org/jivesoftware/smack/ReconnectionManager.java index a2ae412a4..f19a62ce4 100644 --- a/core/src/main/java/org/jivesoftware/smack/ReconnectionManager.java +++ b/core/src/main/java/org/jivesoftware/smack/ReconnectionManager.java @@ -35,7 +35,7 @@ import java.util.logging.Logger; * * @author Francisco Vives */ -public class ReconnectionManager implements ConnectionListener { +public class ReconnectionManager extends AbstractConnectionListener { private static final Logger LOGGER = Logger.getLogger(ReconnectionManager.class.getName()); // Holds the connection to the server @@ -187,10 +187,12 @@ public class ReconnectionManager implements ConnectionListener { } } + @Override public void connectionClosed() { done = true; } + @Override public void connectionClosedOnError(Exception e) { done = false; if (e instanceof StreamErrorException) { @@ -207,20 +209,4 @@ public class ReconnectionManager implements ConnectionListener { this.reconnect(); } } - - public void reconnectingIn(int seconds) { - // ignore - } - - public void reconnectionFailed(Exception e) { - // ignore - } - - /** - * The connection has successfull gotten connected. - */ - public void reconnectionSuccessful() { - // ignore - } - } diff --git a/core/src/main/java/org/jivesoftware/smack/Roster.java b/core/src/main/java/org/jivesoftware/smack/Roster.java index e7adb5599..b658f28c5 100644 --- a/core/src/main/java/org/jivesoftware/smack/Roster.java +++ b/core/src/main/java/org/jivesoftware/smack/Roster.java @@ -29,6 +29,8 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotLoggedInException; @@ -59,6 +61,7 @@ import org.jivesoftware.smack.util.StringUtils; */ public class Roster { + private static final Logger LOGGER = Logger.getLogger(Roster.class.getName()); /** * The default subscription processing mode to use when a Roster is created. By default * all subscription requests are automatically accepted. @@ -123,9 +126,9 @@ public class Roster { PacketFilter presenceFilter = new PacketTypeFilter(Presence.class); presencePacketListener = new PresencePacketListener(); connection.addPacketListener(presencePacketListener, presenceFilter); - + // Listen for connection events - final ConnectionListener connectionListener = new AbstractConnectionListener() { + connection.addConnectionListener(new AbstractConnectionListener() { public void connectionClosed() { // Changes the presence available contacts to unavailable @@ -137,22 +140,34 @@ public class Roster { setOfflinePresences(); } - }; - - // if not connected add listener after successful login - if(!this.connection.isConnected()) { - XMPPConnection.addConnectionCreationListener(new ConnectionCreationListener() { - - public void connectionCreated(XMPPConnection connection) { - if(connection.equals(Roster.this.connection)) { - Roster.this.connection.addConnectionListener(connectionListener); - } - - } - }); - } else { - connection.addConnectionListener(connectionListener); + }); + // If the connection is already established, call reload + if (connection.isAuthenticated()) { + try { + reload(); + } + catch (NotLoggedInException e) { + LOGGER.log(Level.SEVERE, "Could not reload Roster", e); + } } + connection.addConnectionListener(new AbstractConnectionListener() { + public void authenticated(XMPPConnection connection) { + // Anonymous users can't have a roster, but it iss possible that a Roster instance is + // retrieved if getRoster() is called *before* connect(). So we have to check here + // again if it's an anonymous connection. + if (connection.isAnonymous()) + return; + if (!connection.getConfiguration().isRosterLoadedAtLogin()) + return; + try { + Roster.this.reload(); + } + catch (NotLoggedInException e) { + LOGGER.log(Level.SEVERE, "Could not reload Roster", e); + return; + } + } + }); } /** @@ -189,11 +204,9 @@ public class Roster { * Reloads the entire roster from the server. This is an asynchronous operation, * 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. - * - * @throws SmackException If not logged in. - * @throws IllegalStateException if logged in anonymously + * @throws NotLoggedInException If not logged in. */ - public void reload() throws XMPPException, SmackException { + public void reload() throws NotLoggedInException{ if (!connection.isAuthenticated()) { throw new NotLoggedInException(); } diff --git a/core/src/main/java/org/jivesoftware/smack/XMPPConnection.java b/core/src/main/java/org/jivesoftware/smack/XMPPConnection.java index 29701edaf..0e885cca1 100644 --- a/core/src/main/java/org/jivesoftware/smack/XMPPConnection.java +++ b/core/src/main/java/org/jivesoftware/smack/XMPPConnection.java @@ -224,6 +224,8 @@ public abstract class XMPPConnection { private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(2); + private Roster roster; + /** * Create an executor to deliver incoming packets to listeners. We'll use a single thread with an unbounded queue. */ @@ -482,11 +484,53 @@ public abstract class XMPPConnection { * {@link RosterListener}s will throw an IllegalStateException. * * @return the user's roster. - * @throws XMPPException if an error occurs on the XMPP protocol level. - * @throws SmackException if an error occurs somehwere else besides XMPP protocol level. + * @throws IllegalStateException if the connection is anonymous */ - public abstract Roster getRoster() throws XMPPException, SmackException; + public Roster getRoster() { + if (isAnonymous()) { + throw new IllegalStateException("Anonymous users can't have a roster"); + } + // synchronize against login() + synchronized(this) { + if (roster == null) { + roster = new Roster(this); + } + if (!isAuthenticated()) { + return roster; + } + } + // If this is the first time the user has asked for the roster after calling + // login, we want to wait for the server to send back the user's roster. This + // behavior shields API users from having to worry about the fact that roster + // operations are asynchronous, although they'll still have to listen for + // changes to the roster. Note: because of this waiting logic, internal + // Smack code should be wary about calling the getRoster method, and may need to + // access the roster object directly. + // Also only check for rosterInitalized is isRosterLoadedAtLogin is set, otherwise the user + // has to manually call Roster.reload() before he can expect a initialized roster. + if (!roster.rosterInitialized && config.isRosterLoadedAtLogin()) { + try { + synchronized (roster) { + long waitTime = SmackConfiguration.getDefaultPacketReplyTimeout(); + long start = System.currentTimeMillis(); + while (!roster.rosterInitialized) { + if (waitTime <= 0) { + break; + } + roster.wait(waitTime); + long now = System.currentTimeMillis(); + waitTime -= now - start; + start = now; + } + } + } + catch (InterruptedException ie) { + // Ignore. + } + } + return roster; + } /** * Returns the SASLAuthentication manager that is responsible for authenticating with * the server. @@ -944,6 +988,44 @@ public abstract class XMPPConnection { } } + void callConnectionConnectedListener() { + for (ConnectionListener listener : getConnectionListeners()) { + listener.connected(this); + } + } + + void callConnectionAuthenticatedListener() { + for (ConnectionListener listener : getConnectionListeners()) { + listener.connected(this); + } + } + + void callConnectionClosedListener() { + for (ConnectionListener listener : getConnectionListeners()) { + try { + listener.connectionClosed(); + } + catch (Exception e) { + // Catch and print any exception so we can recover + // from a faulty listener and finish the shutdown process + LOGGER.log(Level.SEVERE, "Error in listener while closing connection", e); + } + } + } + + void callConnectionClosedOnErrorListener(Exception e) { + for (ConnectionListener listener : getConnectionListeners()) { + try { + listener.connectionClosedOnError(e); + } + catch (Exception e2) { + // Catch and print any exception so we can recover + // from a faulty listener + LOGGER.log(Level.SEVERE, "Error in listener while closing connection", e2); + } + } + } + /** * A wrapper class to associate a packet filter with a listener. */ diff --git a/core/src/main/java/org/jivesoftware/smack/debugger/ConsoleDebugger.java b/core/src/main/java/org/jivesoftware/smack/debugger/ConsoleDebugger.java index e900d93f0..18200d93c 100644 --- a/core/src/main/java/org/jivesoftware/smack/debugger/ConsoleDebugger.java +++ b/core/src/main/java/org/jivesoftware/smack/debugger/ConsoleDebugger.java @@ -109,6 +109,14 @@ public class ConsoleDebugger implements SmackDebugger { }; connListener = new ConnectionListener() { + public void connected(XMPPConnection connection) { + System.out.println(dateFormatter.format(new Date()) + " XMPPConnection connected (" + + connection.hashCode() + ")"); + } + public void authenticated(XMPPConnection connection) { + System.out.println(dateFormatter.format(new Date()) + + " XMPPConnection authenticated (" + connection.hashCode() + ")"); + } public void connectionClosed() { System.out.println( dateFormatter.format(new Date()) + " XMPPConnection closed (" + diff --git a/debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java b/debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java index ec93ad470..11c0b5380 100644 --- a/debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java +++ b/debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java @@ -17,6 +17,7 @@ package org.jivesoftware.smackx.debugger; +import org.jivesoftware.smack.AbstractConnectionListener; import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.XMPPConnection; @@ -199,7 +200,7 @@ public class EnhancedDebugger implements SmackDebugger { }; // Create a thread that will listen for any connection closed event - connListener = new ConnectionListener() { + connListener = new AbstractConnectionListener() { public void connectionClosed() { SwingUtilities.invokeLater(new Runnable() { public void run() { diff --git a/extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferNegotiator.java b/extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferNegotiator.java index 561344d86..fbb6bc514 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferNegotiator.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/filetransfer/FileTransferNegotiator.java @@ -27,8 +27,8 @@ import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; +import org.jivesoftware.smack.AbstractConnectionListener; import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.PacketCollector; import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.packet.IQ; @@ -215,26 +215,16 @@ public class FileTransferNegotiator { } private void configureConnection(final XMPPConnection connection) { - connection.addConnectionListener(new ConnectionListener() { + connection.addConnectionListener(new AbstractConnectionListener() { + @Override public void connectionClosed() { cleanup(connection); } + @Override public void connectionClosedOnError(Exception e) { cleanup(connection); } - - public void reconnectionFailed(Exception e) { - // ignore - } - - public void reconnectionSuccessful() { - // ignore - } - - public void reconnectingIn(int seconds) { - // ignore - } }); } diff --git a/extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java b/extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java index 1993453b0..04ee4dc9c 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java @@ -32,9 +32,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; +import org.jivesoftware.smack.AbstractConnectionListener; import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.ConnectionCreationListener; -import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.PacketCollector; import org.jivesoftware.smack.PacketInterceptor; @@ -2338,7 +2338,7 @@ public class MultiUserChat { * * @author Gaston Dombiak */ - private static class InvitationsMonitor implements ConnectionListener { + private static class InvitationsMonitor extends AbstractConnectionListener { // We use a WeakHashMap so that the GC can collect the monitor when the // connection is no longer referenced by any object. // Note that when the InvitationsMonitor is used, i.e. when there are InvitationListeners, it will add a @@ -2447,26 +2447,11 @@ public class MultiUserChat { } } + @Override public void connectionClosed() { cancel(); } - public void connectionClosedOnError(Exception e) { - // ignore - } - - public void reconnectingIn(int seconds) { - // ignore - } - - public void reconnectionSuccessful() { - // ignore - } - - public void reconnectionFailed(Exception e) { - // ignore - } - /** * Initializes the listeners to detect received room invitations and to detect when the * connection gets closed. As soon as a room invitation is received the invitations diff --git a/extensions/src/main/java/org/jivesoftware/smackx/muc/RoomListenerMultiplexor.java b/extensions/src/main/java/org/jivesoftware/smackx/muc/RoomListenerMultiplexor.java index 1f5833347..aee730f9c 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/muc/RoomListenerMultiplexor.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/muc/RoomListenerMultiplexor.java @@ -17,7 +17,7 @@ package org.jivesoftware.smackx.muc; -import org.jivesoftware.smack.ConnectionListener; +import org.jivesoftware.smack.AbstractConnectionListener; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.filter.PacketFilter; @@ -38,7 +38,7 @@ import java.util.concurrent.ConcurrentHashMap; * * @author Larry Kirschner */ -class RoomListenerMultiplexor implements ConnectionListener { +class RoomListenerMultiplexor extends AbstractConnectionListener { // We use a WeakHashMap so that the GC can collect the monitor when the // connection is no longer referenced by any object. @@ -98,26 +98,16 @@ class RoomListenerMultiplexor implements ConnectionListener { listener.addRoom(address, roomListener); } + @Override public void connectionClosed() { cancel(); } + @Override public void connectionClosedOnError(Exception e) { cancel(); } - public void reconnectingIn(int seconds) { - // ignore - } - - public void reconnectionSuccessful() { - // ignore - } - - public void reconnectionFailed(Exception e) { - // ignore - } - /** * Initializes the listeners to detect received room invitations and to detect when the * connection gets closed. As soon as a room invitation is received the invitations diff --git a/extensions/src/main/java/org/jivesoftware/smackx/ping/PingManager.java b/extensions/src/main/java/org/jivesoftware/smackx/ping/PingManager.java index 91e265863..8dc08ba21 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/ping/PingManager.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/ping/PingManager.java @@ -26,11 +26,11 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; +import org.jivesoftware.smack.AbstractConnectionListener; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.ConnectionCreationListener; -import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.XMPPException; @@ -134,7 +134,11 @@ public class PingManager extends Manager { connection().sendPacket(pong); } }, PING_PACKET_FILTER); - connection.addConnectionListener(new ConnectionListener() { + connection.addConnectionListener(new AbstractConnectionListener() { + @Override + public void authenticated(XMPPConnection connection) { + maybeSchedulePingServerTask(); + } @Override public void connectionClosed() { maybeStopPingServerTask(); @@ -143,14 +147,6 @@ public class PingManager extends Manager { public void connectionClosedOnError(Exception arg0) { maybeStopPingServerTask(); } - @Override - public void reconnectionSuccessful() { - maybeSchedulePingServerTask(); - } - @Override - public void reconnectingIn(int seconds) {} - @Override - public void reconnectionFailed(Exception e) {} }); maybeSchedulePingServerTask(); } diff --git a/jingle/src/main/java/org/jivesoftware/smackx/jingle/JingleSession.java b/jingle/src/main/java/org/jivesoftware/smackx/jingle/JingleSession.java index eedc44a88..cb7fa95af 100644 --- a/jingle/src/main/java/org/jivesoftware/smackx/jingle/JingleSession.java +++ b/jingle/src/main/java/org/jivesoftware/smackx/jingle/JingleSession.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Random; import java.util.logging.Logger; +import org.jivesoftware.smack.AbstractConnectionListener; import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.SmackException; @@ -625,23 +626,16 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList */ private void installConnectionListeners(final XMPPConnection connection) { if (connection != null) { - connectionListener = new ConnectionListener() { + connectionListener = new AbstractConnectionListener() { + @Override public void connectionClosed() { unregisterInstanceFor(connection); } + @Override public void connectionClosedOnError(java.lang.Exception e) { unregisterInstanceFor(connection); } - - public void reconnectingIn(int i) { - } - - public void reconnectionSuccessful() { - } - - public void reconnectionFailed(Exception exception) { - } }; connection.addConnectionListener(connectionListener); } diff --git a/tcp/src/main/java/org/jivesoftware/smack/PacketReader.java b/tcp/src/main/java/org/jivesoftware/smack/PacketReader.java index bf5c392e7..17b737bd0 100644 --- a/tcp/src/main/java/org/jivesoftware/smack/PacketReader.java +++ b/tcp/src/main/java/org/jivesoftware/smack/PacketReader.java @@ -117,16 +117,7 @@ class PacketReader { public void shutdown() { // Notify connection listeners of the connection closing if done hasn't already been set. if (!done) { - for (ConnectionListener listener : connection.getConnectionListeners()) { - try { - listener.connectionClosed(); - } - catch (Exception e) { - // Catch and print any exception so we can recover - // from a faulty listener and finish the shutdown process - LOGGER.log(Level.SEVERE, "Error in listener while closing connection", e); - } - } + connection.callConnectionClosedListener(); } done = true; } diff --git a/tcp/src/main/java/org/jivesoftware/smack/TCPConnection.java b/tcp/src/main/java/org/jivesoftware/smack/TCPConnection.java index b17e26bce..46aff9ebe 100644 --- a/tcp/src/main/java/org/jivesoftware/smack/TCPConnection.java +++ b/tcp/src/main/java/org/jivesoftware/smack/TCPConnection.java @@ -93,8 +93,6 @@ public class TCPConnection extends XMPPConnection { PacketWriter packetWriter; PacketReader packetReader; - Roster roster = null; - /** * Collection of available stream compression methods offered by the server. */ @@ -266,14 +264,6 @@ public class TCPConnection extends XMPPConnection { authenticated = true; anonymous = false; - // Create the roster if it is not a reconnection or roster already created by getRoster() - if (this.roster == null) { - this.roster = new Roster(this); - } - if (config.isRosterLoadedAtLogin()) { - this.roster.reload(); - } - // Set presence to online. if (config.isSendPresence()) { packetWriter.sendPacket(new Presence(Presence.Type.available)); @@ -289,6 +279,7 @@ public class TCPConnection extends XMPPConnection { if (config.isDebuggerEnabled() && debugger != null) { debugger.userHasLogged(user); } + callConnectionAuthenticatedListener(); } @Override @@ -332,52 +323,7 @@ public class TCPConnection extends XMPPConnection { if (config.isDebuggerEnabled() && debugger != null) { debugger.userHasLogged(user); } - } - - public Roster getRoster() throws XMPPException, SmackException { - // synchronize against login() - 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()) { - roster.reload(); - } - // If this is the first time the user has asked for the roster after calling - // login, we want to wait for the server to send back the user's roster. This - // behavior shields API users from having to worry about the fact that roster - // operations are asynchronous, although they'll still have to listen for - // changes to the roster. Note: because of this waiting logic, internal - // Smack code should be wary about calling the getRoster method, and may need to - // access the roster object directly. - if (!roster.rosterInitialized) { - try { - synchronized (roster) { - long waitTime = SmackConfiguration.getDefaultPacketReplyTimeout(); - long start = System.currentTimeMillis(); - while (!roster.rosterInitialized) { - if (waitTime <= 0) { - break; - } - roster.wait(waitTime); - long now = System.currentTimeMillis(); - waitTime -= now - start; - start = now; - } - } - } - catch (InterruptedException ie) { - // Ignore. - } - } - return roster; + callConnectionAuthenticatedListener(); } public boolean isConnected() { @@ -919,6 +865,11 @@ public class TCPConnection extends XMPPConnection { public void connect() throws SmackException, IOException, XMPPException { // Establishes the connection, readers and writers connectUsingConfiguration(config); + // TODO is there a case where connectUsing.. does not throw an exception but connected is + // still false? + if (connected) { + callConnectionConnectedListener(); + } // Automatically makes the login if the user was previously connected successfully // to the server and the connection was terminated abruptly if (connected && wasAuthenticated) { @@ -963,16 +914,7 @@ public class TCPConnection extends XMPPConnection { // Closes the connection temporary. A reconnection is possible shutdown(new Presence(Presence.Type.unavailable)); // Notify connection listeners of the error. - for (ConnectionListener listener : getConnectionListeners()) { - try { - listener.connectionClosedOnError(e); - } - catch (Exception e2) { - // Catch and print any exception so we can recover - // from a faulty listener - e2.printStackTrace(); - } - } + callConnectionClosedOnErrorListener(e); } /**