mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-26 14:02:06 +01:00
Added reconnection support. SMACK-172
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@5367 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
96e4201f61
commit
3af86fd462
22 changed files with 501 additions and 194 deletions
|
@ -10,6 +10,7 @@
|
||||||
<className>org.jivesoftware.smackx.muc.MultiUserChat</className>
|
<className>org.jivesoftware.smackx.muc.MultiUserChat</className>
|
||||||
<className>org.jivesoftware.smackx.filetransfer.FileTransferManager</className>
|
<className>org.jivesoftware.smackx.filetransfer.FileTransferManager</className>
|
||||||
<className>org.jivesoftware.smackx.LastActivityManager</className>
|
<className>org.jivesoftware.smackx.LastActivityManager</className>
|
||||||
|
<className>org.jivesoftware.smack.ReconnectionManager</className>
|
||||||
</startupClasses>
|
</startupClasses>
|
||||||
|
|
||||||
<!-- Paket reply timeout in milliseconds -->
|
<!-- Paket reply timeout in milliseconds -->
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
package org.jivesoftware.smack;
|
package org.jivesoftware.smack;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,6 +55,16 @@ public class ConnectionConfiguration implements Cloneable {
|
||||||
|
|
||||||
private boolean debuggerEnabled = XMPPConnection.DEBUG_ENABLED;
|
private boolean debuggerEnabled = XMPPConnection.DEBUG_ENABLED;
|
||||||
|
|
||||||
|
// Flag that indicates if a reconnection should be attempted when abruptly disconnected
|
||||||
|
private boolean reconnectionAllowed = true;
|
||||||
|
|
||||||
|
// Holds the socket factory that is used to generate the socket in the connection
|
||||||
|
private SocketFactory socketFactory;
|
||||||
|
|
||||||
|
// Holds the authentication information for future reconnections
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
public ConnectionConfiguration(String host, int port, String serviceName) {
|
public ConnectionConfiguration(String host, int port, String serviceName) {
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
@ -354,4 +365,61 @@ public class ConnectionConfiguration implements Cloneable {
|
||||||
protected Object clone() throws CloneNotSupportedException {
|
protected Object clone() throws CloneNotSupportedException {
|
||||||
return super.clone();
|
return super.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets if the reconnection mechanism is allowed to be used. By default
|
||||||
|
* reconnection is allowed.
|
||||||
|
*
|
||||||
|
* @param isAllowed if the reconnection mechanism is allowed to use.
|
||||||
|
*/
|
||||||
|
public void setReconnectionAllowed(boolean isAllowed) {
|
||||||
|
this.reconnectionAllowed = isAllowed;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns if the reconnection mechanism is allowed to be used. By default
|
||||||
|
* reconnection is allowed.
|
||||||
|
*
|
||||||
|
* @return if the reconnection mechanism is allowed to be used.
|
||||||
|
*/
|
||||||
|
public boolean isReconnectionAllowed() {
|
||||||
|
return this.reconnectionAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the socket factory used to create new xmppConnection sockets.
|
||||||
|
* This is mainly used when reconnection is necessary.
|
||||||
|
*
|
||||||
|
* @param socketFactory used to create new sockets.
|
||||||
|
*/
|
||||||
|
public void setSocketFactory(SocketFactory socketFactory) {
|
||||||
|
this.socketFactory = socketFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the socket factory used to create new xmppConnection sockets.
|
||||||
|
* This is mainly used when reconnection is necessary.
|
||||||
|
*
|
||||||
|
* @return socketFactory used to create new sockets.
|
||||||
|
*/
|
||||||
|
public SocketFactory getSocketFactory() {
|
||||||
|
return this.socketFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setUsernameAndPassword(String username, String password) {
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the username used to login
|
||||||
|
*/
|
||||||
|
protected String getUsername() {
|
||||||
|
return this.username;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the password used to login
|
||||||
|
*/
|
||||||
|
protected String getPassword() {
|
||||||
|
return this.password;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ package org.jivesoftware.smack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that allows for implementing classes to listen for connection closing
|
* Interface that allows for implementing classes to listen for connection closing
|
||||||
* events. Listeners are registered with XMPPConnection objects.
|
* and reconnection events. Listeners are registered with XMPPConnection objects.
|
||||||
*
|
*
|
||||||
* @see XMPPConnection#addConnectionListener
|
* @see XMPPConnection#addConnectionListener
|
||||||
* @see XMPPConnection#removeConnectionListener
|
* @see XMPPConnection#removeConnectionListener
|
||||||
|
@ -32,14 +32,36 @@ package org.jivesoftware.smack;
|
||||||
public interface ConnectionListener {
|
public interface ConnectionListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification that the connection was closed normally.
|
* Notification that the connection was closed normally or that the reconnection
|
||||||
|
* process has been aborted.
|
||||||
*/
|
*/
|
||||||
public void connectionClosed();
|
public void connectionClosed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notification that the connection was closed due to an exception.
|
* Notification that the connection was closed due to an exception. When
|
||||||
|
* abruptly disconnected it is possible for the connection to try reconnecting
|
||||||
|
* to the server.
|
||||||
*
|
*
|
||||||
* @param e the exception.
|
* @param e the exception.
|
||||||
*/
|
*/
|
||||||
public void connectionClosedOnError(Exception e);
|
public void connectionClosedOnError(Exception e);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection will retry to reconnect in the specified number of seconds.
|
||||||
|
*
|
||||||
|
* @param seconds remaining seconds before attempting a reconnection.
|
||||||
|
*/
|
||||||
|
public void reconnectingIn(int seconds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection has reconnected successfully to the server. Connections will
|
||||||
|
* reconnect to the server when the previous socket connection was abruptly closed.
|
||||||
|
*/
|
||||||
|
public void reconectionSuccessful();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An attempt to connect to the server has failed. The connection will keep trying
|
||||||
|
* reconnecting to the server in a moment.
|
||||||
|
*/
|
||||||
|
public void reconnectionFailed(Exception e);
|
||||||
}
|
}
|
|
@ -44,12 +44,12 @@ import java.util.concurrent.TimeUnit;
|
||||||
*/
|
*/
|
||||||
class PacketReader {
|
class PacketReader {
|
||||||
|
|
||||||
private final Thread readerThread;
|
private Thread readerThread;
|
||||||
private final Thread listenerThread;
|
private Thread listenerThread;
|
||||||
|
|
||||||
private XMPPConnection connection;
|
private XMPPConnection connection;
|
||||||
private XmlPullParser parser;
|
private XmlPullParser parser;
|
||||||
private boolean done = false;
|
private boolean done;
|
||||||
private final VolatileMemberCollection<PacketCollector> collectors =
|
private final VolatileMemberCollection<PacketCollector> collectors =
|
||||||
new VolatileMemberCollection<PacketCollector>(50);
|
new VolatileMemberCollection<PacketCollector>(50);
|
||||||
protected final VolatileMemberCollection listeners = new VolatileMemberCollection(50);
|
protected final VolatileMemberCollection listeners = new VolatileMemberCollection(50);
|
||||||
|
@ -61,10 +61,20 @@ class PacketReader {
|
||||||
|
|
||||||
protected PacketReader(XMPPConnection connection) {
|
protected PacketReader(XMPPConnection connection) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the reader in order to be used. The reader is initialized during the
|
||||||
|
* first connection and when reconnecting due to an abruptly disconnection.
|
||||||
|
*/
|
||||||
|
protected void init() {
|
||||||
|
done = false;
|
||||||
|
connectionID = null;
|
||||||
|
|
||||||
readerThread = new Thread() {
|
readerThread = new Thread() {
|
||||||
public void run() {
|
public void run() {
|
||||||
parsePackets();
|
parsePackets(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
readerThread.setName("Smack Packet Reader");
|
readerThread.setName("Smack Packet Reader");
|
||||||
|
@ -73,7 +83,7 @@ class PacketReader {
|
||||||
listenerThread = new Thread() {
|
listenerThread = new Thread() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
processListeners();
|
processListeners(this);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -195,7 +205,8 @@ class PacketReader {
|
||||||
*/
|
*/
|
||||||
void notifyConnectionError(Exception e) {
|
void notifyConnectionError(Exception e) {
|
||||||
done = true;
|
done = true;
|
||||||
connection.close();
|
// Closes the connection temporary. A reconnection is possible
|
||||||
|
connection.shutdown();
|
||||||
// Print the stack trace to help catch the problem
|
// Print the stack trace to help catch the problem
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
// Notify connection listeners of the error.
|
// Notify connection listeners of the error.
|
||||||
|
@ -214,6 +225,26 @@ class PacketReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a notification indicating that the connection was reconnected successfully.
|
||||||
|
*/
|
||||||
|
protected void notifyReconnection() {
|
||||||
|
// Notify connection listeners of the reconnection.
|
||||||
|
List<ConnectionListener> listenersCopy;
|
||||||
|
synchronized (connectionListeners) {
|
||||||
|
// Make a copy since it's possible that a listener will be removed from the list
|
||||||
|
listenersCopy = new ArrayList<ConnectionListener>(connectionListeners);
|
||||||
|
for (ConnectionListener listener : listenersCopy) {
|
||||||
|
listener.reconectionSuccessful();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that the listenerThread is awake to shutdown properly
|
||||||
|
synchronized (listenerThread) {
|
||||||
|
listenerThread.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the parser using the latest connection's reader. Reseting the parser is necessary
|
* Resets the parser using the latest connection's reader. Reseting the parser is necessary
|
||||||
* when the plain connection has been secured or when a new opening stream element is going
|
* when the plain connection has been secured or when a new opening stream element is going
|
||||||
|
@ -232,9 +263,11 @@ class PacketReader {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process listeners.
|
* Process listeners.
|
||||||
|
*
|
||||||
|
* @param thread the thread that is being used by the reader to process incoming packets.
|
||||||
*/
|
*/
|
||||||
private void processListeners() {
|
private void processListeners(Thread thread) {
|
||||||
while (!done) {
|
while (!done && thread == listenerThread) {
|
||||||
boolean processedPacket = false;
|
boolean processedPacket = false;
|
||||||
Iterator it = listeners.getIterator();
|
Iterator it = listeners.getIterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
|
@ -257,8 +290,10 @@ class PacketReader {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse top-level packets in order to process them further.
|
* Parse top-level packets in order to process them further.
|
||||||
|
*
|
||||||
|
* @param thread the thread that is being used by the reader to parse incoming packets.
|
||||||
*/
|
*/
|
||||||
private void parsePackets() {
|
private void parsePackets(Thread thread) {
|
||||||
try {
|
try {
|
||||||
int eventType = parser.getEventType();
|
int eventType = parser.getEventType();
|
||||||
do {
|
do {
|
||||||
|
@ -356,12 +391,12 @@ class PacketReader {
|
||||||
}
|
}
|
||||||
else if (eventType == XmlPullParser.END_TAG) {
|
else if (eventType == XmlPullParser.END_TAG) {
|
||||||
if (parser.getName().equals("stream")) {
|
if (parser.getName().equals("stream")) {
|
||||||
// Close the connection.
|
// Disconnect the connection
|
||||||
connection.close();
|
connection.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
eventType = parser.next();
|
eventType = parser.next();
|
||||||
} while (!done && eventType != XmlPullParser.END_DOCUMENT);
|
} while (!done && eventType != XmlPullParser.END_DOCUMENT && thread == readerThread);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
if (!done) {
|
if (!done) {
|
||||||
|
@ -470,7 +505,7 @@ class PacketReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Release the lock after TLS has been negotiated or we are not insterested in TLS
|
// Release the lock after TLS has been negotiated or we are not insterested in TLS
|
||||||
if (!startTLSReceived || !connection.getConfiguration().isTLSEnabled()) {
|
if (!startTLSReceived || !connection.getConfiguration().isTLSEnabled()) {
|
||||||
releaseConnectionIDLock();
|
releaseConnectionIDLock();
|
||||||
}
|
}
|
||||||
|
@ -873,7 +908,7 @@ class PacketReader {
|
||||||
/**
|
/**
|
||||||
* A wrapper class to associate a packet collector with a listener.
|
* A wrapper class to associate a packet collector with a listener.
|
||||||
*/
|
*/
|
||||||
private static class ListenerWrapper {
|
protected static class ListenerWrapper {
|
||||||
|
|
||||||
private PacketListener packetListener;
|
private PacketListener packetListener;
|
||||||
private PacketCollector packetCollector;
|
private PacketCollector packetCollector;
|
||||||
|
|
|
@ -39,13 +39,14 @@ import java.util.List;
|
||||||
class PacketWriter {
|
class PacketWriter {
|
||||||
|
|
||||||
private Thread writerThread;
|
private Thread writerThread;
|
||||||
|
private Thread keepAliveThread;
|
||||||
private Writer writer;
|
private Writer writer;
|
||||||
private XMPPConnection connection;
|
private XMPPConnection connection;
|
||||||
final private LinkedList<Packet> queue;
|
final private LinkedList<Packet> queue;
|
||||||
private boolean done = false;
|
private boolean done;
|
||||||
|
|
||||||
final private List<ListenerWrapper> listeners = new ArrayList<ListenerWrapper>();
|
final protected List<ListenerWrapper> listeners = new ArrayList<ListenerWrapper>();
|
||||||
private boolean listenersDeleted = false;
|
private boolean listenersDeleted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamp when the last stanza was sent to the server. This information is used
|
* Timestamp when the last stanza was sent to the server. This information is used
|
||||||
|
@ -70,13 +71,24 @@ class PacketWriter {
|
||||||
* @param connection the connection.
|
* @param connection the connection.
|
||||||
*/
|
*/
|
||||||
protected PacketWriter(XMPPConnection connection) {
|
protected PacketWriter(XMPPConnection connection) {
|
||||||
this.connection = connection;
|
|
||||||
this.writer = connection.writer;
|
|
||||||
this.queue = new LinkedList<Packet>();
|
this.queue = new LinkedList<Packet>();
|
||||||
|
this.connection = connection;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the writer in order to be used. It is called at the first connection and also
|
||||||
|
* is invoked if the connection is disconnected by an error.
|
||||||
|
*/
|
||||||
|
protected void init() {
|
||||||
|
this.writer = connection.writer;
|
||||||
|
listenersDeleted = false;
|
||||||
|
interceptorDeleted = false;
|
||||||
|
done = false;
|
||||||
|
|
||||||
writerThread = new Thread() {
|
writerThread = new Thread() {
|
||||||
public void run() {
|
public void run() {
|
||||||
writePackets();
|
writePackets(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
writerThread.setName("Smack Packet Writer");
|
writerThread.setName("Smack Packet Writer");
|
||||||
|
@ -205,8 +217,11 @@ class PacketWriter {
|
||||||
// out a space character each time it runs to keep the TCP/IP connection open.
|
// out a space character each time it runs to keep the TCP/IP connection open.
|
||||||
int keepAliveInterval = SmackConfiguration.getKeepAliveInterval();
|
int keepAliveInterval = SmackConfiguration.getKeepAliveInterval();
|
||||||
if (keepAliveInterval > 0) {
|
if (keepAliveInterval > 0) {
|
||||||
Thread keepAliveThread = new Thread(new KeepAliveTask(keepAliveInterval));
|
KeepAliveTask target = new KeepAliveTask(keepAliveInterval);
|
||||||
|
keepAliveThread = new Thread(target);
|
||||||
|
target.setThread(keepAliveThread);
|
||||||
keepAliveThread.setDaemon(true);
|
keepAliveThread.setDaemon(true);
|
||||||
|
keepAliveThread.setName("Smack Keep Alive");
|
||||||
keepAliveThread.start();
|
keepAliveThread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,12 +262,12 @@ class PacketWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writePackets() {
|
private void writePackets(Thread thisThread) {
|
||||||
try {
|
try {
|
||||||
// Open the stream.
|
// Open the stream.
|
||||||
openStream();
|
openStream();
|
||||||
// Write out packets from the queue.
|
// Write out packets from the queue.
|
||||||
while (!done) {
|
while (!done && (writerThread == thisThread)) {
|
||||||
Packet packet = nextPacket();
|
Packet packet = nextPacket();
|
||||||
if (packet != null) {
|
if (packet != null) {
|
||||||
synchronized (writer) {
|
synchronized (writer) {
|
||||||
|
@ -370,7 +385,7 @@ class PacketWriter {
|
||||||
/**
|
/**
|
||||||
* A wrapper class to associate a packet filter with a listener.
|
* A wrapper class to associate a packet filter with a listener.
|
||||||
*/
|
*/
|
||||||
private static class ListenerWrapper {
|
protected static class ListenerWrapper {
|
||||||
|
|
||||||
private PacketListener packetListener;
|
private PacketListener packetListener;
|
||||||
private PacketFilter packetFilter;
|
private PacketFilter packetFilter;
|
||||||
|
@ -444,11 +459,16 @@ class PacketWriter {
|
||||||
private class KeepAliveTask implements Runnable {
|
private class KeepAliveTask implements Runnable {
|
||||||
|
|
||||||
private int delay;
|
private int delay;
|
||||||
|
private Thread thread;
|
||||||
|
|
||||||
public KeepAliveTask(int delay) {
|
public KeepAliveTask(int delay) {
|
||||||
this.delay = delay;
|
this.delay = delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setThread(Thread thread) {
|
||||||
|
this.thread = thread;
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
// Sleep 15 seconds before sending first heartbeat. This will give time to
|
// Sleep 15 seconds before sending first heartbeat. This will give time to
|
||||||
|
@ -458,7 +478,7 @@ class PacketWriter {
|
||||||
catch (InterruptedException ie) {
|
catch (InterruptedException ie) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
while (!done) {
|
while (!done && keepAliveThread == thread) {
|
||||||
synchronized (writer) {
|
synchronized (writer) {
|
||||||
// Send heartbeat if no packet has been sent to the server for a given time
|
// Send heartbeat if no packet has been sent to the server for a given time
|
||||||
if (System.currentTimeMillis() - lastActive >= delay) {
|
if (System.currentTimeMillis() - lastActive >= delay) {
|
||||||
|
|
|
@ -71,24 +71,27 @@ public class PrivacyListManager {
|
||||||
// the connection is closed
|
// the connection is closed
|
||||||
connection.addConnectionListener(new ConnectionListener() {
|
connection.addConnectionListener(new ConnectionListener() {
|
||||||
public void connectionClosed() {
|
public void connectionClosed() {
|
||||||
// Unregister this instance since the connection has been closed
|
// Unregister this instance since the connection has been closed
|
||||||
instances.remove(connection);
|
instances.remove(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectionClosedOnError(Exception e) {
|
public void connectionClosedOnError(Exception e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reconnectionFailed(Exception e) {
|
public void reconnectionFailed(Exception e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
public void attemptToReconnectIn(int seconds) {
|
|
||||||
|
public void reconnectingIn(int seconds) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
public void conectionReestablished() {
|
|
||||||
|
public void reconectionSuccessful() {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.addPacketListener(new PacketListener() {
|
connection.addPacketListener(new PacketListener() {
|
||||||
public void processPacket(Packet packet) {
|
public void processPacket(Packet packet) {
|
||||||
|
|
||||||
|
|
|
@ -68,14 +68,14 @@ public class SASLAuthentication implements UserAuthentication {
|
||||||
/**
|
/**
|
||||||
* Boolean indicating if SASL negotiation has finished and was successful.
|
* Boolean indicating if SASL negotiation has finished and was successful.
|
||||||
*/
|
*/
|
||||||
private boolean saslNegotiated = false;
|
private boolean saslNegotiated;
|
||||||
/**
|
/**
|
||||||
* Boolean indication if SASL authentication has failed. When failed the server may end
|
* Boolean indication if SASL authentication has failed. When failed the server may end
|
||||||
* the connection.
|
* the connection.
|
||||||
*/
|
*/
|
||||||
private boolean saslFailed = false;
|
private boolean saslFailed;
|
||||||
private boolean resourceBinded = false;
|
private boolean resourceBinded;
|
||||||
private boolean sessionSupported = false;
|
private boolean sessionSupported;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// Register SASL mechanisms supported by Smack
|
// Register SASL mechanisms supported by Smack
|
||||||
|
@ -126,6 +126,7 @@ public class SASLAuthentication implements UserAuthentication {
|
||||||
SASLAuthentication(XMPPConnection connection) {
|
SASLAuthentication(XMPPConnection connection) {
|
||||||
super();
|
super();
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -413,4 +414,16 @@ public class SASLAuthentication implements UserAuthentication {
|
||||||
void sessionsSupported() {
|
void sessionsSupported() {
|
||||||
sessionSupported = true;
|
sessionSupported = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the internal state in order to be able to be reused. The authentication
|
||||||
|
* is used by the connection at the first login and then reused after the connection
|
||||||
|
* is disconnected and then reconnected.
|
||||||
|
*/
|
||||||
|
protected void init() {
|
||||||
|
saslNegotiated = false;
|
||||||
|
saslFailed = false;
|
||||||
|
resourceBinded = false;
|
||||||
|
sessionSupported = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,26 @@ public class ConsoleDebugger implements SmackDebugger {
|
||||||
")");
|
")");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
public void reconnectionFailed(Exception e) {
|
||||||
|
System.out.println(
|
||||||
|
dateFormatter.format(new Date()) +
|
||||||
|
" Reconnection failed due to an exception (" +
|
||||||
|
connection.hashCode() +
|
||||||
|
")");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
public void reconectionSuccessful() {
|
||||||
|
System.out.println(
|
||||||
|
dateFormatter.format(new Date()) + " Connection reconnected (" +
|
||||||
|
connection.hashCode() +
|
||||||
|
")");
|
||||||
|
}
|
||||||
|
public void reconnectingIn(int seconds) {
|
||||||
|
System.out.println(
|
||||||
|
dateFormatter.format(new Date()) + " Connection (" +
|
||||||
|
connection.hashCode() +
|
||||||
|
") will reconnect in " + seconds);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,7 @@
|
||||||
|
|
||||||
package org.jivesoftware.smack.packet;
|
package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a XMPP error sub-packet. Typically, a server responds to a request that has
|
* Represents a XMPP error sub-packet. Typically, a server responds to a request that has
|
||||||
|
@ -79,8 +76,8 @@ public class XMPPError {
|
||||||
* @param condition the error condition.
|
* @param condition the error condition.
|
||||||
*/
|
*/
|
||||||
public XMPPError(Condition condition) {
|
public XMPPError(Condition condition) {
|
||||||
this.init(condition);
|
this.init(condition);
|
||||||
this.message = null;
|
this.message = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,7 +94,7 @@ public class XMPPError {
|
||||||
this.init(condition);
|
this.init(condition);
|
||||||
this.message = messageText;
|
this.message = messageText;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new error with the specified code and no message.
|
* Creates a new error with the specified code and no message.
|
||||||
*
|
*
|
||||||
|
@ -108,7 +105,7 @@ public class XMPPError {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.message = null;
|
this.message = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new error with the specified code and message.
|
* Creates a new error with the specified code and message.
|
||||||
* deprecated
|
* deprecated
|
||||||
|
@ -121,8 +118,7 @@ public class XMPPError {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new error with the specified code, type, condition and message.
|
* Creates a new error with the specified code, type, condition and message.
|
||||||
* This constructor is used when the condition is not recognized automatically by XMPPError
|
* This constructor is used when the condition is not recognized automatically by XMPPError
|
||||||
|
@ -156,7 +152,7 @@ public class XMPPError {
|
||||||
// If there is a default error specification for the received condition,
|
// If there is a default error specification for the received condition,
|
||||||
// it get configured with the infered type and code.
|
// it get configured with the infered type and code.
|
||||||
this.type = defaultErrorSpecification.getType();
|
this.type = defaultErrorSpecification.getType();
|
||||||
this.code = defaultErrorSpecification.getCode();
|
this.code = defaultErrorSpecification.getCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -167,7 +163,7 @@ public class XMPPError {
|
||||||
public String getCondition() {
|
public String getCondition() {
|
||||||
return condition;
|
return condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the error type.
|
* Returns the error type.
|
||||||
*
|
*
|
||||||
|
@ -176,7 +172,7 @@ public class XMPPError {
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the error code.
|
* Returns the error code.
|
||||||
*
|
*
|
||||||
|
@ -210,17 +206,17 @@ public class XMPPError {
|
||||||
}
|
}
|
||||||
buf.append(">");
|
buf.append(">");
|
||||||
if (condition != null) {
|
if (condition != null) {
|
||||||
buf.append("<").append(condition);
|
buf.append("<").append(condition);
|
||||||
buf.append(" xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>");
|
buf.append(" xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>");
|
||||||
}
|
}
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
buf.append("<text xml:lang=\"en\" xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">");
|
buf.append("<text xml:lang=\"en\" xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\">");
|
||||||
buf.append(message);
|
buf.append(message);
|
||||||
buf.append("</text>");
|
buf.append("</text>");
|
||||||
}
|
}
|
||||||
for (PacketExtension element : this.getExtensions()) {
|
for (PacketExtension element : this.getExtensions()) {
|
||||||
buf.append(element.toXML());
|
buf.append(element.toXML());
|
||||||
}
|
}
|
||||||
buf.append("</error>");
|
buf.append("</error>");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
@ -270,7 +266,7 @@ public class XMPPError {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a packet extension to the error.
|
* Adds a packet extension to the error.
|
||||||
*
|
*
|
||||||
|
@ -278,7 +274,7 @@ public class XMPPError {
|
||||||
*/
|
*/
|
||||||
public synchronized void addExtension(PacketExtension extension) {
|
public synchronized void addExtension(PacketExtension extension) {
|
||||||
if (applicationExtensions == null) {
|
if (applicationExtensions == null) {
|
||||||
applicationExtensions = new ArrayList<PacketExtension>();
|
applicationExtensions = new ArrayList<PacketExtension>();
|
||||||
}
|
}
|
||||||
applicationExtensions.add(extension);
|
applicationExtensions.add(extension);
|
||||||
}
|
}
|
||||||
|
@ -289,10 +285,9 @@ public class XMPPError {
|
||||||
* @param extension a packet extension.
|
* @param extension a packet extension.
|
||||||
*/
|
*/
|
||||||
public synchronized void setExtension(List<PacketExtension> extension) {
|
public synchronized void setExtension(List<PacketExtension> extension) {
|
||||||
applicationExtensions = extension;
|
applicationExtensions = extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to represent the type of the Error. The types are:
|
* A class to represent the type of the Error. The types are:
|
||||||
*
|
*
|
||||||
|
@ -311,7 +306,7 @@ public class XMPPError {
|
||||||
AUTH,
|
AUTH,
|
||||||
CONTINUE
|
CONTINUE
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to represent predefined error conditions.
|
* A class to represent predefined error conditions.
|
||||||
*/
|
*/
|
||||||
|
@ -341,7 +336,7 @@ public class XMPPError {
|
||||||
public static final Condition undefined_condition = new Condition("undefined-condition");
|
public static final Condition undefined_condition = new Condition("undefined-condition");
|
||||||
public static final Condition unexpected_condition = new Condition("unexpected-condition");
|
public static final Condition unexpected_condition = new Condition("unexpected-condition");
|
||||||
public static final Condition request_timeout = new Condition("request-timeout");
|
public static final Condition request_timeout = new Condition("request-timeout");
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
public Condition(String value) {
|
public Condition(String value) {
|
||||||
|
@ -353,80 +348,80 @@ public class XMPPError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to represent the error specification used to infer common usage.
|
* A class to represent the error specification used to infer common usage.
|
||||||
*/
|
*/
|
||||||
private static class ErrorSpecification {
|
private static class ErrorSpecification {
|
||||||
private int code;
|
private int code;
|
||||||
private Type type;
|
private Type type;
|
||||||
private Condition condition;
|
private Condition condition;
|
||||||
private static HashMap<Condition, ErrorSpecification> instances = errorSpecifications();
|
private static Map<Condition, ErrorSpecification> instances = errorSpecifications();
|
||||||
|
|
||||||
private ErrorSpecification(Condition condition, Type type, int code) {
|
private ErrorSpecification(Condition condition, Type type, int code) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HashMap<Condition, ErrorSpecification> errorSpecifications() {
|
private static Map<Condition, ErrorSpecification> errorSpecifications() {
|
||||||
HashMap<Condition, ErrorSpecification> instances = new HashMap<Condition, ErrorSpecification>(22);
|
Map<Condition, ErrorSpecification> instances = new HashMap<Condition, ErrorSpecification>(22);
|
||||||
instances.put(Condition.interna_server_error, new ErrorSpecification(
|
instances.put(Condition.interna_server_error, new ErrorSpecification(
|
||||||
Condition.interna_server_error, Type.WAIT, 500));
|
Condition.interna_server_error, Type.WAIT, 500));
|
||||||
instances.put(Condition.forbidden, new ErrorSpecification(Condition.forbidden,
|
instances.put(Condition.forbidden, new ErrorSpecification(Condition.forbidden,
|
||||||
Type.AUTH, 403));
|
Type.AUTH, 403));
|
||||||
instances.put(Condition.bad_request, new XMPPError.ErrorSpecification(
|
instances.put(Condition.bad_request, new XMPPError.ErrorSpecification(
|
||||||
Condition.bad_request, Type.MODIFY, 400));
|
Condition.bad_request, Type.MODIFY, 400));
|
||||||
instances.put(Condition.item_not_found, new XMPPError.ErrorSpecification(
|
instances.put(Condition.item_not_found, new XMPPError.ErrorSpecification(
|
||||||
Condition.item_not_found, Type.CANCEL, 404));
|
Condition.item_not_found, Type.CANCEL, 404));
|
||||||
instances.put(Condition.conflict, new XMPPError.ErrorSpecification(
|
instances.put(Condition.conflict, new XMPPError.ErrorSpecification(
|
||||||
Condition.conflict, Type.CANCEL, 409));
|
Condition.conflict, Type.CANCEL, 409));
|
||||||
instances.put(Condition.feature_not_implemented, new XMPPError.ErrorSpecification(
|
instances.put(Condition.feature_not_implemented, new XMPPError.ErrorSpecification(
|
||||||
Condition.feature_not_implemented, Type.CANCEL, 501));
|
Condition.feature_not_implemented, Type.CANCEL, 501));
|
||||||
instances.put(Condition.gone, new XMPPError.ErrorSpecification(
|
instances.put(Condition.gone, new XMPPError.ErrorSpecification(
|
||||||
Condition.gone, Type.MODIFY, 302));
|
Condition.gone, Type.MODIFY, 302));
|
||||||
instances.put(Condition.jid_malformed, new XMPPError.ErrorSpecification(
|
instances.put(Condition.jid_malformed, new XMPPError.ErrorSpecification(
|
||||||
Condition.jid_malformed, Type.MODIFY, 400));
|
Condition.jid_malformed, Type.MODIFY, 400));
|
||||||
instances.put(Condition.no_acceptable, new XMPPError.ErrorSpecification(
|
instances.put(Condition.no_acceptable, new XMPPError.ErrorSpecification(
|
||||||
Condition.no_acceptable, Type.MODIFY, 406));
|
Condition.no_acceptable, Type.MODIFY, 406));
|
||||||
instances.put(Condition.not_allowed, new XMPPError.ErrorSpecification(
|
instances.put(Condition.not_allowed, new XMPPError.ErrorSpecification(
|
||||||
Condition.not_allowed, Type.CANCEL, 405));
|
Condition.not_allowed, Type.CANCEL, 405));
|
||||||
instances.put(Condition.not_authorized, new XMPPError.ErrorSpecification(
|
instances.put(Condition.not_authorized, new XMPPError.ErrorSpecification(
|
||||||
Condition.not_authorized, Type.AUTH, 401));
|
Condition.not_authorized, Type.AUTH, 401));
|
||||||
instances.put(Condition.payment_required, new XMPPError.ErrorSpecification(
|
instances.put(Condition.payment_required, new XMPPError.ErrorSpecification(
|
||||||
Condition.payment_required, Type.AUTH, 402));
|
Condition.payment_required, Type.AUTH, 402));
|
||||||
instances.put(Condition.recipient_unavailable, new XMPPError.ErrorSpecification(
|
instances.put(Condition.recipient_unavailable, new XMPPError.ErrorSpecification(
|
||||||
Condition.recipient_unavailable, Type.WAIT, 404));
|
Condition.recipient_unavailable, Type.WAIT, 404));
|
||||||
instances.put(Condition.redirect, new XMPPError.ErrorSpecification(
|
instances.put(Condition.redirect, new XMPPError.ErrorSpecification(
|
||||||
Condition.redirect, Type.MODIFY, 302));
|
Condition.redirect, Type.MODIFY, 302));
|
||||||
instances.put(Condition.registration_required, new XMPPError.ErrorSpecification(
|
instances.put(Condition.registration_required, new XMPPError.ErrorSpecification(
|
||||||
Condition.registration_required, Type.AUTH, 407));
|
Condition.registration_required, Type.AUTH, 407));
|
||||||
instances.put(Condition.remote_server_not_found, new XMPPError.ErrorSpecification(
|
instances.put(Condition.remote_server_not_found, new XMPPError.ErrorSpecification(
|
||||||
Condition.remote_server_not_found, Type.CANCEL, 404));
|
Condition.remote_server_not_found, Type.CANCEL, 404));
|
||||||
instances.put(Condition.remote_server_timeout, new XMPPError.ErrorSpecification(
|
instances.put(Condition.remote_server_timeout, new XMPPError.ErrorSpecification(
|
||||||
Condition.remote_server_timeout, Type.WAIT, 504));
|
Condition.remote_server_timeout, Type.WAIT, 504));
|
||||||
instances.put(Condition.remote_server_error, new XMPPError.ErrorSpecification(
|
instances.put(Condition.remote_server_error, new XMPPError.ErrorSpecification(
|
||||||
Condition.remote_server_error, Type.CANCEL, 502));
|
Condition.remote_server_error, Type.CANCEL, 502));
|
||||||
instances.put(Condition.resource_constraint, new XMPPError.ErrorSpecification(
|
instances.put(Condition.resource_constraint, new XMPPError.ErrorSpecification(
|
||||||
Condition.resource_constraint, Type.WAIT, 500));
|
Condition.resource_constraint, Type.WAIT, 500));
|
||||||
instances.put(Condition.service_unavailable, new XMPPError.ErrorSpecification(
|
instances.put(Condition.service_unavailable, new XMPPError.ErrorSpecification(
|
||||||
Condition.service_unavailable, Type.CANCEL, 503));
|
Condition.service_unavailable, Type.CANCEL, 503));
|
||||||
instances.put(Condition.subscription_required, new XMPPError.ErrorSpecification(
|
instances.put(Condition.subscription_required, new XMPPError.ErrorSpecification(
|
||||||
Condition.subscription_required, Type.AUTH, 407));
|
Condition.subscription_required, Type.AUTH, 407));
|
||||||
instances.put(Condition.undefined_condition, new XMPPError.ErrorSpecification(
|
instances.put(Condition.undefined_condition, new XMPPError.ErrorSpecification(
|
||||||
Condition.undefined_condition, Type.WAIT, 500));
|
Condition.undefined_condition, Type.WAIT, 500));
|
||||||
instances.put(Condition.unexpected_condition, new XMPPError.ErrorSpecification(
|
instances.put(Condition.unexpected_condition, new XMPPError.ErrorSpecification(
|
||||||
Condition.unexpected_condition, Type.WAIT, 400));
|
Condition.unexpected_condition, Type.WAIT, 400));
|
||||||
instances.put(Condition.request_timeout, new XMPPError.ErrorSpecification(
|
instances.put(Condition.request_timeout, new XMPPError.ErrorSpecification(
|
||||||
Condition.request_timeout, Type.CANCEL, 408));
|
Condition.request_timeout, Type.CANCEL, 408));
|
||||||
|
|
||||||
return instances;
|
return instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ErrorSpecification specFor(Condition condition) {
|
protected static ErrorSpecification specFor(Condition condition) {
|
||||||
return instances.get(condition);
|
return instances.get(condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the error condition.
|
* Returns the error condition.
|
||||||
*
|
*
|
||||||
|
@ -435,7 +430,7 @@ public class XMPPError {
|
||||||
protected Condition getCondition() {
|
protected Condition getCondition() {
|
||||||
return condition;
|
return condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the error type.
|
* Returns the error type.
|
||||||
*
|
*
|
||||||
|
@ -444,7 +439,7 @@ public class XMPPError {
|
||||||
protected Type getType() {
|
protected Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the error code.
|
* Returns the error code.
|
||||||
*
|
*
|
||||||
|
|
|
@ -150,8 +150,19 @@ public class ServiceDiscoveryManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectionClosedOnError(Exception e) {
|
public void connectionClosedOnError(Exception e) {
|
||||||
// Unregister this instance since the connection has been closed
|
// ignore
|
||||||
instances.remove(connection);
|
}
|
||||||
|
|
||||||
|
public void reconnectionFailed(Exception e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconnectingIn(int seconds) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconectionSuccessful() {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,30 @@ public class EnhancedDebugger implements SmackDebugger {
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
public void reconnectingIn(final int seconds){
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
statusField.setValue("Attempt to reconnect in " + seconds + " seconds");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconectionSuccessful() {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
statusField.setValue("Reconnection stablished");
|
||||||
|
EnhancedDebuggerWindow.connectionEstablished(EnhancedDebugger.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconnectionFailed(Exception e) {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
statusField.setValue("Reconnection failed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,7 +575,7 @@ public class EnhancedDebugger implements SmackDebugger {
|
||||||
connPanel.add(
|
connPanel.add(
|
||||||
label,
|
label,
|
||||||
new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, 21, 0, new Insets(0, 0, 0, 0), 0, 0));
|
new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, 21, 0, new Insets(0, 0, 0, 0), 0, 0));
|
||||||
field = new JFormattedTextField(new Integer(connection.getPort()));
|
field = new JFormattedTextField(connection.getPort());
|
||||||
field.setMinimumSize(new java.awt.Dimension(150, 20));
|
field.setMinimumSize(new java.awt.Dimension(150, 20));
|
||||||
field.setMaximumSize(new java.awt.Dimension(150, 20));
|
field.setMaximumSize(new java.awt.Dimension(150, 20));
|
||||||
field.setEditable(false);
|
field.setEditable(false);
|
||||||
|
@ -618,16 +642,9 @@ public class EnhancedDebugger implements SmackDebugger {
|
||||||
packetsPanel.setBorder(BorderFactory.createTitledBorder("Transmitted Packets"));
|
packetsPanel.setBorder(BorderFactory.createTitledBorder("Transmitted Packets"));
|
||||||
|
|
||||||
statisticsTable =
|
statisticsTable =
|
||||||
new DefaultTableModel(new Object[][]{{"IQ", new Integer(0), new Integer(0)}, {
|
new DefaultTableModel(new Object[][]{{"IQ", 0, 0}, {"Message", 0, 0},
|
||||||
"Message", new Integer(0), new Integer(0)
|
{"Presence", 0, 0}, {"Other", 0, 0}, {"Total", 0, 0}},
|
||||||
}, {
|
new Object[]{"Type", "Received", "Sent"}) {
|
||||||
"Presence", new Integer(0), new Integer(0)
|
|
||||||
}, {
|
|
||||||
"Other", new Integer(0), new Integer(0)
|
|
||||||
}, {
|
|
||||||
"Total", new Integer(0), new Integer(0)
|
|
||||||
}
|
|
||||||
}, new Object[]{"Type", "Received", "Sent"}) {
|
|
||||||
public boolean isCellEditable(int rowIndex, int mColIndex) {
|
public boolean isCellEditable(int rowIndex, int mColIndex) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -719,7 +736,7 @@ public class EnhancedDebugger implements SmackDebugger {
|
||||||
private void addReadPacketToTable(final SimpleDateFormat dateFormatter, final Packet packet) {
|
private void addReadPacketToTable(final SimpleDateFormat dateFormatter, final Packet packet) {
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
String messageType = null;
|
String messageType;
|
||||||
String from = packet.getFrom();
|
String from = packet.getFrom();
|
||||||
String type = "";
|
String type = "";
|
||||||
Icon packetTypeIcon;
|
Icon packetTypeIcon;
|
||||||
|
@ -780,7 +797,7 @@ public class EnhancedDebugger implements SmackDebugger {
|
||||||
private void addSentPacketToTable(final SimpleDateFormat dateFormatter, final Packet packet) {
|
private void addSentPacketToTable(final SimpleDateFormat dateFormatter, final Packet packet) {
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
String messageType = null;
|
String messageType;
|
||||||
String to = packet.getTo();
|
String to = packet.getTo();
|
||||||
String type = "";
|
String type = "";
|
||||||
Icon packetTypeIcon;
|
Icon packetTypeIcon;
|
||||||
|
@ -840,9 +857,10 @@ public class EnhancedDebugger implements SmackDebugger {
|
||||||
// Surround this setting in a try/catch for compatibility with Java 1.4. This setting is required
|
// Surround this setting in a try/catch for compatibility with Java 1.4. This setting is required
|
||||||
// for Java 1.5
|
// for Java 1.5
|
||||||
try {
|
try {
|
||||||
tFactory.setAttribute("indent-number", new Integer(2));
|
tFactory.setAttribute("indent-number", 2);
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e) {
|
catch (IllegalArgumentException e) {
|
||||||
|
// Ignore
|
||||||
}
|
}
|
||||||
Transformer transformer = tFactory.newTransformer();
|
Transformer transformer = tFactory.newTransformer();
|
||||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||||
|
|
|
@ -29,7 +29,6 @@ import java.awt.event.*;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,7 +89,7 @@ public class EnhancedDebuggerWindow {
|
||||||
|
|
||||||
private JFrame frame = null;
|
private JFrame frame = null;
|
||||||
private JTabbedPane tabbedPane = null;
|
private JTabbedPane tabbedPane = null;
|
||||||
private java.util.List debuggers = new ArrayList();
|
private java.util.List<EnhancedDebugger> debuggers = new ArrayList<EnhancedDebugger>();
|
||||||
|
|
||||||
private EnhancedDebuggerWindow() {
|
private EnhancedDebuggerWindow() {
|
||||||
}
|
}
|
||||||
|
@ -178,6 +177,12 @@ public class EnhancedDebuggerWindow {
|
||||||
connectionClosedOnErrorIcon);
|
connectionClosedOnErrorIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized static void connectionEstablished(EnhancedDebugger debugger) {
|
||||||
|
getInstance().tabbedPane.setIconAt(
|
||||||
|
getInstance().tabbedPane.indexOfComponent(debugger.tabbedPane),
|
||||||
|
connectionActiveIcon);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the main debug window that provides information about Smack and also shows
|
* Creates the main debug window that provides information about Smack and also shows
|
||||||
* a tab panel for each connection that is being debugged.
|
* a tab panel for each connection that is being debugged.
|
||||||
|
@ -264,7 +269,7 @@ public class EnhancedDebuggerWindow {
|
||||||
if (tabbedPane.getSelectedIndex() < tabbedPane.getComponentCount() - 1) {
|
if (tabbedPane.getSelectedIndex() < tabbedPane.getComponentCount() - 1) {
|
||||||
int index = tabbedPane.getSelectedIndex();
|
int index = tabbedPane.getSelectedIndex();
|
||||||
// Notify to the debugger to stop debugging
|
// Notify to the debugger to stop debugging
|
||||||
EnhancedDebugger debugger = (EnhancedDebugger) debuggers.get(index);
|
EnhancedDebugger debugger = debuggers.get(index);
|
||||||
debugger.cancel();
|
debugger.cancel();
|
||||||
// Remove the debugger from the root window
|
// Remove the debugger from the root window
|
||||||
tabbedPane.remove(debugger.tabbedPane);
|
tabbedPane.remove(debugger.tabbedPane);
|
||||||
|
@ -281,18 +286,17 @@ public class EnhancedDebuggerWindow {
|
||||||
menuItem = new JMenuItem("Close All Not Active");
|
menuItem = new JMenuItem("Close All Not Active");
|
||||||
menuItem.addActionListener(new ActionListener() {
|
menuItem.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
ArrayList debuggersToRemove = new ArrayList();
|
ArrayList<EnhancedDebugger> debuggersToRemove = new ArrayList<EnhancedDebugger>();
|
||||||
// Remove all the debuggers of which their connections are no longer valid
|
// Remove all the debuggers of which their connections are no longer valid
|
||||||
for (int index = 0; index < tabbedPane.getComponentCount() - 1; index++) {
|
for (int index = 0; index < tabbedPane.getComponentCount() - 1; index++) {
|
||||||
EnhancedDebugger debugger = (EnhancedDebugger) debuggers.get(index);
|
EnhancedDebugger debugger = debuggers.get(index);
|
||||||
if (!debugger.isConnectionActive()) {
|
if (!debugger.isConnectionActive()) {
|
||||||
// Notify to the debugger to stop debugging
|
// Notify to the debugger to stop debugging
|
||||||
debugger.cancel();
|
debugger.cancel();
|
||||||
debuggersToRemove.add(debugger);
|
debuggersToRemove.add(debugger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Iterator it = debuggersToRemove.iterator(); it.hasNext();) {
|
for (EnhancedDebugger debugger : debuggersToRemove) {
|
||||||
EnhancedDebugger debugger = (EnhancedDebugger) it.next();
|
|
||||||
// Remove the debugger from the root window
|
// Remove the debugger from the root window
|
||||||
tabbedPane.remove(debugger.tabbedPane);
|
tabbedPane.remove(debugger.tabbedPane);
|
||||||
debuggers.remove(debugger);
|
debuggers.remove(debugger);
|
||||||
|
@ -324,8 +328,7 @@ public class EnhancedDebuggerWindow {
|
||||||
*/
|
*/
|
||||||
public void rootWindowClosing(WindowEvent evt) {
|
public void rootWindowClosing(WindowEvent evt) {
|
||||||
// Notify to all the debuggers to stop debugging
|
// Notify to all the debuggers to stop debugging
|
||||||
for (Iterator it = debuggers.iterator(); it.hasNext();) {
|
for (EnhancedDebugger debugger : debuggers) {
|
||||||
EnhancedDebugger debugger = (EnhancedDebugger) it.next();
|
|
||||||
debugger.cancel();
|
debugger.cancel();
|
||||||
}
|
}
|
||||||
// Release any reference to the debuggers
|
// Release any reference to the debuggers
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.jivesoftware.smackx.packet.StreamInitiation;
|
||||||
|
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the negotiation of file transfers according to JEP-0096. If a file is
|
* Manages the negotiation of file transfers according to JEP-0096. If a file is
|
||||||
|
@ -64,7 +65,8 @@ public class FileTransferNegotiator {
|
||||||
|
|
||||||
private static final String[] PROTOCOLS = {BYTE_STREAM, INBAND_BYTE_STREAM};
|
private static final String[] PROTOCOLS = {BYTE_STREAM, INBAND_BYTE_STREAM};
|
||||||
|
|
||||||
private static final Map transferObject = new HashMap();
|
private static final Map<XMPPConnection, FileTransferNegotiator> transferObject =
|
||||||
|
new ConcurrentHashMap<XMPPConnection, FileTransferNegotiator>();
|
||||||
|
|
||||||
private static final String STREAM_INIT_PREFIX = "jsi_";
|
private static final String STREAM_INIT_PREFIX = "jsi_";
|
||||||
|
|
||||||
|
@ -92,7 +94,7 @@ public class FileTransferNegotiator {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transferObject.containsKey(connection)) {
|
if (transferObject.containsKey(connection)) {
|
||||||
return (FileTransferNegotiator) transferObject.get(connection);
|
return transferObject.get(connection);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FileTransferNegotiator transfer = new FileTransferNegotiator(
|
FileTransferNegotiator transfer = new FileTransferNegotiator(
|
||||||
|
@ -114,12 +116,12 @@ public class FileTransferNegotiator {
|
||||||
final boolean isEnabled) {
|
final boolean isEnabled) {
|
||||||
ServiceDiscoveryManager manager = ServiceDiscoveryManager
|
ServiceDiscoveryManager manager = ServiceDiscoveryManager
|
||||||
.getInstanceFor(connection);
|
.getInstanceFor(connection);
|
||||||
for (int i = 0; i < NAMESPACE.length; i++) {
|
for (String ns : NAMESPACE) {
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
manager.addFeature(NAMESPACE[i]);
|
manager.addFeature(ns);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
manager.removeFeature(NAMESPACE[i]);
|
manager.removeFeature(ns);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,9 +134,8 @@ public class FileTransferNegotiator {
|
||||||
* @return True if all related services are enabled, false if they are not.
|
* @return True if all related services are enabled, false if they are not.
|
||||||
*/
|
*/
|
||||||
public static boolean isServiceEnabled(final XMPPConnection connection) {
|
public static boolean isServiceEnabled(final XMPPConnection connection) {
|
||||||
for (int i = 0; i < NAMESPACE.length; i++) {
|
for (String ns : NAMESPACE) {
|
||||||
if (!ServiceDiscoveryManager.getInstanceFor(connection)
|
if (!ServiceDiscoveryManager.getInstanceFor(connection).includesFeature(ns))
|
||||||
.includesFeature(NAMESPACE[i]))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -198,14 +199,26 @@ public class FileTransferNegotiator {
|
||||||
public void connectionClosedOnError(Exception e) {
|
public void connectionClosedOnError(Exception e) {
|
||||||
cleanup(connection);
|
cleanup(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reconnectionFailed(Exception e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconectionSuccessful() {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconnectingIn(int seconds) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanup(final XMPPConnection connection) {
|
private void cleanup(final XMPPConnection connection) {
|
||||||
transferObject.remove(connection);
|
if (transferObject.remove(connection) != null) {
|
||||||
|
byteStreamTransferManager.cleanup();
|
||||||
byteStreamTransferManager.cleanup();
|
inbandTransferManager.cleanup();
|
||||||
inbandTransferManager.cleanup();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2614,6 +2614,18 @@ public class MultiUserChat {
|
||||||
cancel();
|
cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reconnectingIn(int seconds) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconectionSuccessful() {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconnectionFailed(Exception e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the listeners to detect received room invitations and to detect when the
|
* 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
|
* connection gets closed. As soon as a room invitation is received the invitations
|
||||||
|
|
|
@ -109,6 +109,18 @@ class RoomListenerMultiplexor implements ConnectionListener {
|
||||||
cancel();
|
cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reconnectingIn(int seconds) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconectionSuccessful() {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconnectionFailed(Exception e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the listeners to detect received room invitations and to detect when the
|
* 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
|
* connection gets closed. As soon as a room invitation is received the invitations
|
||||||
|
|
|
@ -32,10 +32,11 @@ public class LoginTest extends SmackTestCase {
|
||||||
public void testInvalidLogin() {
|
public void testInvalidLogin() {
|
||||||
try {
|
try {
|
||||||
XMPPConnection connection = new XMPPConnection(getHost(), getPort());
|
XMPPConnection connection = new XMPPConnection(getHost(), getPort());
|
||||||
|
connection.connect();
|
||||||
try {
|
try {
|
||||||
// Login with an invalid user
|
// Login with an invalid user
|
||||||
connection.login("invaliduser" , "invalidpass");
|
connection.login("invaliduser" , "invalidpass");
|
||||||
connection.close();
|
connection.disconnect();
|
||||||
fail("Invalid user was able to log into the server");
|
fail("Invalid user was able to log into the server");
|
||||||
}
|
}
|
||||||
catch (XMPPException e) {
|
catch (XMPPException e) {
|
||||||
|
@ -60,6 +61,8 @@ public class LoginTest extends SmackTestCase {
|
||||||
try {
|
try {
|
||||||
XMPPConnection conn1 = new XMPPConnection(getHost(), getPort());
|
XMPPConnection conn1 = new XMPPConnection(getHost(), getPort());
|
||||||
XMPPConnection conn2 = new XMPPConnection(getHost(), getPort());
|
XMPPConnection conn2 = new XMPPConnection(getHost(), getPort());
|
||||||
|
conn1.connect();
|
||||||
|
conn2.connect();
|
||||||
try {
|
try {
|
||||||
// Try to login anonymously
|
// Try to login anonymously
|
||||||
conn1.loginAnonymously();
|
conn1.loginAnonymously();
|
||||||
|
@ -76,8 +79,8 @@ public class LoginTest extends SmackTestCase {
|
||||||
fail(e.getMessage());
|
fail(e.getMessage());
|
||||||
}
|
}
|
||||||
// Close the connection
|
// Close the connection
|
||||||
conn1.close();
|
conn1.disconnect();
|
||||||
conn2.close();
|
conn2.disconnect();
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -93,10 +96,13 @@ public class LoginTest extends SmackTestCase {
|
||||||
ConnectionConfiguration config = new ConnectionConfiguration(getHost(), getPort());
|
ConnectionConfiguration config = new ConnectionConfiguration(getHost(), getPort());
|
||||||
config.setSASLAuthenticationEnabled(false);
|
config.setSASLAuthenticationEnabled(false);
|
||||||
XMPPConnection conn1 = new XMPPConnection(config);
|
XMPPConnection conn1 = new XMPPConnection(config);
|
||||||
|
conn1.connect();
|
||||||
|
|
||||||
config = new ConnectionConfiguration(getHost(), getPort());
|
config = new ConnectionConfiguration(getHost(), getPort());
|
||||||
config.setSASLAuthenticationEnabled(false);
|
config.setSASLAuthenticationEnabled(false);
|
||||||
XMPPConnection conn2 = new XMPPConnection(config);
|
XMPPConnection conn2 = new XMPPConnection(config);
|
||||||
|
conn2.connect();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Try to login anonymously
|
// Try to login anonymously
|
||||||
conn1.loginAnonymously();
|
conn1.loginAnonymously();
|
||||||
|
@ -113,8 +119,8 @@ public class LoginTest extends SmackTestCase {
|
||||||
fail(e.getMessage());
|
fail(e.getMessage());
|
||||||
}
|
}
|
||||||
// Close the connection
|
// Close the connection
|
||||||
conn1.close();
|
conn1.disconnect();
|
||||||
conn2.close();
|
conn2.disconnect();
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -128,6 +134,7 @@ public class LoginTest extends SmackTestCase {
|
||||||
public void testLoginWithNoResource() {
|
public void testLoginWithNoResource() {
|
||||||
try {
|
try {
|
||||||
XMPPConnection conn = new XMPPConnection(getHost(), getPort());
|
XMPPConnection conn = new XMPPConnection(getHost(), getPort());
|
||||||
|
conn.connect();
|
||||||
try {
|
try {
|
||||||
conn.getAccountManager().createAccount("user_1", "user_1");
|
conn.getAccountManager().createAccount("user_1", "user_1");
|
||||||
} catch (XMPPException e) {
|
} catch (XMPPException e) {
|
||||||
|
@ -142,7 +149,7 @@ public class LoginTest extends SmackTestCase {
|
||||||
assertNotNull("JID assigned by server is missing", conn.getUser());
|
assertNotNull("JID assigned by server is missing", conn.getUser());
|
||||||
assertNotNull("JID assigned by server does not have a resource",
|
assertNotNull("JID assigned by server does not have a resource",
|
||||||
StringUtils.parseResource(conn.getUser()));
|
StringUtils.parseResource(conn.getUser()));
|
||||||
conn.close();
|
conn.disconnect();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fail("User with no resource was able to log into the server");
|
fail("User with no resource was able to log into the server");
|
||||||
|
|
|
@ -86,6 +86,7 @@ public class MessengerLoginTest extends TestCase {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
XMPPConnection con = new XMPPConnection(host, port);
|
XMPPConnection con = new XMPPConnection(host, port);
|
||||||
|
con.connect();
|
||||||
con.login(username, password, resource);
|
con.login(username, password, resource);
|
||||||
}
|
}
|
||||||
catch (XMPPException e) {
|
catch (XMPPException e) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ public class PresenceTest extends SmackTestCase {
|
||||||
try {
|
try {
|
||||||
// User_1 will log in again using another resource
|
// User_1 will log in again using another resource
|
||||||
conn = new XMPPConnection(getHost(), getPort());
|
conn = new XMPPConnection(getHost(), getPort());
|
||||||
|
conn.connect();
|
||||||
conn.login(getUsername(1), getUsername(1), "OtherPlace");
|
conn.login(getUsername(1), getUsername(1), "OtherPlace");
|
||||||
// Change the presence priorities of User_1
|
// Change the presence priorities of User_1
|
||||||
getConnection(1).sendPacket(new Presence(Presence.Type.available, null, 1,
|
getConnection(1).sendPacket(new Presence(Presence.Type.available, null, 1,
|
||||||
|
@ -71,8 +72,7 @@ public class PresenceTest extends SmackTestCase {
|
||||||
chat2.nextMessage(1000));
|
chat2.nextMessage(1000));
|
||||||
|
|
||||||
// User_1 closes his connection
|
// User_1 closes his connection
|
||||||
chat2 = null;
|
conn.disconnect();
|
||||||
conn.close();
|
|
||||||
Thread.sleep(150);
|
Thread.sleep(150);
|
||||||
|
|
||||||
// Test delivery of message to the unique presence of the user_1
|
// Test delivery of message to the unique presence of the user_1
|
||||||
|
@ -85,6 +85,7 @@ public class PresenceTest extends SmackTestCase {
|
||||||
|
|
||||||
// User_1 will log in again using another resource
|
// User_1 will log in again using another resource
|
||||||
conn = new XMPPConnection(getHost(), getPort());
|
conn = new XMPPConnection(getHost(), getPort());
|
||||||
|
conn.connect();
|
||||||
conn.login(getUsername(1), getUsername(1), "OtherPlace");
|
conn.login(getUsername(1), getUsername(1), "OtherPlace");
|
||||||
conn.sendPacket(new Presence(Presence.Type.available, null, 1,
|
conn.sendPacket(new Presence(Presence.Type.available, null, 1,
|
||||||
Presence.Mode.available));
|
Presence.Mode.available));
|
||||||
|
@ -119,7 +120,7 @@ public class PresenceTest extends SmackTestCase {
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (conn != null) {
|
if (conn != null) {
|
||||||
conn.close();
|
conn.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,6 +129,7 @@ public class PresenceTest extends SmackTestCase {
|
||||||
* User1 logs from 2 resources but only one is available. User0 sends a message
|
* User1 logs from 2 resources but only one is available. User0 sends a message
|
||||||
* to the full JID of the unavailable resource. User1 in the not available resource
|
* to the full JID of the unavailable resource. User1 in the not available resource
|
||||||
* should receive the message.
|
* should receive the message.
|
||||||
|
* TODO Fix this in Wildfire but before check if XMPP spec requests this feature
|
||||||
*/
|
*/
|
||||||
public void testNotAvailablePresence() throws XMPPException {
|
public void testNotAvailablePresence() throws XMPPException {
|
||||||
// Change the presence to unavailable of User_1
|
// Change the presence to unavailable of User_1
|
||||||
|
@ -135,6 +137,7 @@ public class PresenceTest extends SmackTestCase {
|
||||||
|
|
||||||
// User_1 will log in again using another resource (that is going to be available)
|
// User_1 will log in again using another resource (that is going to be available)
|
||||||
XMPPConnection conn = new XMPPConnection(getHost(), getPort());
|
XMPPConnection conn = new XMPPConnection(getHost(), getPort());
|
||||||
|
conn.connect();
|
||||||
conn.login(getUsername(1), getUsername(1), "OtherPlace");
|
conn.login(getUsername(1), getUsername(1), "OtherPlace");
|
||||||
|
|
||||||
// Create chats between participants
|
// Create chats between participants
|
||||||
|
@ -158,6 +161,7 @@ public class PresenceTest extends SmackTestCase {
|
||||||
public void testMultipleResources() throws Exception {
|
public void testMultipleResources() throws Exception {
|
||||||
// Create another connection for the same user of connection 1
|
// Create another connection for the same user of connection 1
|
||||||
XMPPConnection conn4 = new XMPPConnection(getServiceName());
|
XMPPConnection conn4 = new XMPPConnection(getServiceName());
|
||||||
|
conn4.connect();
|
||||||
conn4.login(getUsername(1), getUsername(1), "Home");
|
conn4.login(getUsername(1), getUsername(1), "Home");
|
||||||
|
|
||||||
// Add a new roster entry
|
// Add a new roster entry
|
||||||
|
@ -188,7 +192,7 @@ public class PresenceTest extends SmackTestCase {
|
||||||
assertTrue("Only one presence was found for user1", presences.hasNext());
|
assertTrue("Only one presence was found for user1", presences.hasNext());
|
||||||
|
|
||||||
// User1 logs out from one resource
|
// User1 logs out from one resource
|
||||||
conn4.close();
|
conn4.disconnect();
|
||||||
|
|
||||||
// Wait up to 1 second
|
// Wait up to 1 second
|
||||||
Thread.sleep(700);
|
Thread.sleep(700);
|
||||||
|
|
|
@ -367,6 +367,7 @@ public class RosterTest extends SmackTestCase {
|
||||||
|
|
||||||
// Log in from another resource so we can test the roster
|
// Log in from another resource so we can test the roster
|
||||||
XMPPConnection con2 = new XMPPConnection(getHost(), getPort());
|
XMPPConnection con2 = new XMPPConnection(getHost(), getPort());
|
||||||
|
con2.connect();
|
||||||
con2.login(getUsername(0), getUsername(0), "MyNewResource");
|
con2.login(getUsername(0), getUsername(0), "MyNewResource");
|
||||||
|
|
||||||
Roster roster2 = con2.getRoster();
|
Roster roster2 = con2.getRoster();
|
||||||
|
@ -386,7 +387,7 @@ public class RosterTest extends SmackTestCase {
|
||||||
assertTrue("NewGroup group was not found", groupNames.contains("NewGroup"));
|
assertTrue("NewGroup group was not found", groupNames.contains("NewGroup"));
|
||||||
|
|
||||||
// Close the new connection
|
// Close the new connection
|
||||||
con2.close();
|
con2.disconnect();
|
||||||
Thread.sleep(500);
|
Thread.sleep(500);
|
||||||
|
|
||||||
cleanUpRoster();
|
cleanUpRoster();
|
||||||
|
@ -480,6 +481,7 @@ public class RosterTest extends SmackTestCase {
|
||||||
|
|
||||||
// Create another connection for the same user of connection 1
|
// Create another connection for the same user of connection 1
|
||||||
XMPPConnection conn4 = new XMPPConnection(getServiceName());
|
XMPPConnection conn4 = new XMPPConnection(getServiceName());
|
||||||
|
conn4.connect();
|
||||||
conn4.login(getUsername(1), getUsername(1), "Home");
|
conn4.login(getUsername(1), getUsername(1), "Home");
|
||||||
|
|
||||||
// Add a new roster entry
|
// Add a new roster entry
|
||||||
|
@ -506,6 +508,7 @@ public class RosterTest extends SmackTestCase {
|
||||||
|
|
||||||
// Check that the right presence is returned for a user+resource
|
// Check that the right presence is returned for a user+resource
|
||||||
presence = roster.getPresenceResource(getFullJID(1));
|
presence = roster.getPresenceResource(getFullJID(1));
|
||||||
|
assertNotNull("Presence not found for user " + getFullJID(1), presence);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"Returned the wrong Presence",
|
"Returned the wrong Presence",
|
||||||
StringUtils.parseResource(presence.getFrom()),
|
StringUtils.parseResource(presence.getFrom()),
|
||||||
|
@ -525,7 +528,7 @@ public class RosterTest extends SmackTestCase {
|
||||||
assertEquals("Wrong number of returned presences", count, 2);
|
assertEquals("Wrong number of returned presences", count, 2);
|
||||||
|
|
||||||
// Close the connection so one presence must go
|
// Close the connection so one presence must go
|
||||||
conn4.close();
|
conn4.disconnect();
|
||||||
|
|
||||||
// Check that the returned presences are correct
|
// Check that the returned presences are correct
|
||||||
presences = roster.getPresences(getBareJID(1));
|
presences = roster.getPresences(getBareJID(1));
|
||||||
|
@ -548,6 +551,7 @@ public class RosterTest extends SmackTestCase {
|
||||||
public void testMultipleResources() throws Exception {
|
public void testMultipleResources() throws Exception {
|
||||||
// Create another connection for the same user of connection 1
|
// Create another connection for the same user of connection 1
|
||||||
XMPPConnection conn4 = new XMPPConnection(getServiceName());
|
XMPPConnection conn4 = new XMPPConnection(getServiceName());
|
||||||
|
conn4.connect();
|
||||||
conn4.login(getUsername(1), getUsername(1), "Home");
|
conn4.login(getUsername(1), getUsername(1), "Home");
|
||||||
|
|
||||||
// Add a new roster entry
|
// Add a new roster entry
|
||||||
|
@ -605,6 +609,7 @@ public class RosterTest extends SmackTestCase {
|
||||||
|
|
||||||
// Create another connection for the same user of connection 0
|
// Create another connection for the same user of connection 0
|
||||||
XMPPConnection conn2 = new XMPPConnection(getServiceName());
|
XMPPConnection conn2 = new XMPPConnection(getServiceName());
|
||||||
|
conn2.connect();
|
||||||
conn2.login(getUsername(0), getUsername(0), "Home");
|
conn2.login(getUsername(0), getUsername(0), "Home");
|
||||||
|
|
||||||
// Retrieve roster and verify that new contact is there and nickname is correct
|
// Retrieve roster and verify that new contact is there and nickname is correct
|
||||||
|
@ -677,6 +682,46 @@ public class RosterTest extends SmackTestCase {
|
||||||
getConnection(2).getRoster().getGroupCount());
|
getConnection(2).getRoster().getGroupCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the creation of a roster and then simulates abrupt termination. Cached presences
|
||||||
|
* must go offline. At reconnection, presences must go back to online.
|
||||||
|
* <ol>
|
||||||
|
* <li> Create some entries
|
||||||
|
* <li> Breack the connection
|
||||||
|
* <li> Check offline presences
|
||||||
|
* <li> Whait for automatic reconnection
|
||||||
|
* <li> Check online presences
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
public void testOfflinePresencesAfterDisconnection() throws Exception {
|
||||||
|
// Add a new roster entry
|
||||||
|
Roster roster = getConnection(0).getRoster();
|
||||||
|
roster.createEntry(getBareJID(1), "gato11", null);
|
||||||
|
roster.createEntry(getBareJID(2), "gato12", null);
|
||||||
|
|
||||||
|
// Wait up to 2 seconds to let the server process presence subscriptions
|
||||||
|
long initial = System.currentTimeMillis();
|
||||||
|
while (System.currentTimeMillis() - initial < 2000 && (
|
||||||
|
roster.getPresence(getBareJID(1)) == null ||
|
||||||
|
roster.getPresence(getBareJID(2)) == null)) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.sleep(200);
|
||||||
|
|
||||||
|
// Brakes the connection
|
||||||
|
getConnection(0).packetReader.notifyConnectionError(new Exception("Simulated Error"));
|
||||||
|
|
||||||
|
Presence presence = roster.getPresence(getBareJID(1));
|
||||||
|
assertNull("Presence should be offline after a connection termination", presence);
|
||||||
|
// Reconnection should occur in 10 seconds
|
||||||
|
Thread.sleep(12200);
|
||||||
|
presence = roster.getPresence(getBareJID(1));
|
||||||
|
assertNotNull("Presence not found for user", presence);
|
||||||
|
assertEquals("Presence should be online after a connection reconnection",
|
||||||
|
Presence.Type.available, presence.getType());
|
||||||
|
}
|
||||||
|
|
||||||
protected int getMaxConnections() {
|
protected int getMaxConnections() {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* $RCSfile$
|
* $RCSfile$
|
||||||
* $Revision$
|
* $Revision$
|
||||||
* $Date: $
|
* $Date$
|
||||||
*
|
*
|
||||||
* Copyright 2003-2005 Jive Software.
|
* Copyright 2003-2005 Jive Software.
|
||||||
*
|
*
|
||||||
|
@ -19,20 +19,18 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smack.test;
|
package org.jivesoftware.smack.test;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import org.jivesoftware.smack.ConnectionConfiguration;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.xmlpull.mxp1.MXParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
|
||||||
import javax.net.SocketFactory;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
|
||||||
import org.jivesoftware.smack.XMPPException;
|
|
||||||
import org.jivesoftware.smack.ConnectionConfiguration;
|
|
||||||
import org.xmlpull.v1.*;
|
|
||||||
import org.xmlpull.mxp1.MXParser;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all the test cases which provides a pre-configured execution context. This
|
* Base class for all the test cases which provides a pre-configured execution context. This
|
||||||
* means that any test case that subclassifies this base class will have access to a pool of
|
* means that any test case that subclassifies this base class will have access to a pool of
|
||||||
|
@ -196,6 +194,7 @@ public abstract class SmackTestCase extends TestCase {
|
||||||
else {
|
else {
|
||||||
connections[i] = new XMPPConnection(config, getSocketFactory());
|
connections[i] = new XMPPConnection(config, getSocketFactory());
|
||||||
}
|
}
|
||||||
|
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
|
||||||
|
@ -232,11 +231,12 @@ public abstract class SmackTestCase extends TestCase {
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
|
|
||||||
for (int i = 0; i < getMaxConnections(); i++) {
|
for (int i = 0; i < getMaxConnections(); i++) {
|
||||||
|
if (getConnection(i).isConnected()) {
|
||||||
// Delete the created account for the test
|
// Delete the created account for the test
|
||||||
getConnection(i).getAccountManager().deleteAccount();
|
getConnection(i).getAccountManager().deleteAccount();
|
||||||
// Close the connection
|
// Close the connection
|
||||||
getConnection(i).close();
|
getConnection(i).disconnect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,10 @@
|
||||||
|
|
||||||
package org.jivesoftware.smackx;
|
package org.jivesoftware.smackx;
|
||||||
|
|
||||||
import org.jivesoftware.smack.test.SmackTestCase;
|
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.ConnectionConfiguration;
|
import org.jivesoftware.smack.test.SmackTestCase;
|
||||||
import org.jivesoftware.smack.SmackConfiguration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that stream compression (JEP-138) is correctly supported by Smack.
|
* Ensure that stream compression (JEP-138) is correctly supported by Smack.
|
||||||
|
@ -50,6 +49,7 @@ public class CompressionTest extends SmackTestCase {
|
||||||
config.setSASLAuthenticationEnabled(true);
|
config.setSASLAuthenticationEnabled(true);
|
||||||
|
|
||||||
XMPPConnection connection = new XMPPConnection(config);
|
XMPPConnection connection = new XMPPConnection(config);
|
||||||
|
connection.connect();
|
||||||
|
|
||||||
// Login with the test account
|
// Login with the test account
|
||||||
connection.login("user0", "user0");
|
connection.login("user0", "user0");
|
||||||
|
@ -57,7 +57,7 @@ public class CompressionTest extends SmackTestCase {
|
||||||
assertTrue("Connection is not using stream compression", connection.isUsingCompression());
|
assertTrue("Connection is not using stream compression", connection.isUsingCompression());
|
||||||
|
|
||||||
// Close connection
|
// Close connection
|
||||||
connection.close();
|
connection.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getMaxConnections() {
|
protected int getMaxConnections() {
|
||||||
|
@ -70,6 +70,7 @@ public class CompressionTest extends SmackTestCase {
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
XMPPConnection setupConnection = new XMPPConnection(getHost(), getPort());
|
XMPPConnection setupConnection = new XMPPConnection(getHost(), getPort());
|
||||||
|
setupConnection.connect();
|
||||||
if (!setupConnection.getAccountManager().supportsAccountCreation())
|
if (!setupConnection.getAccountManager().supportsAccountCreation())
|
||||||
fail("Server does not support account creation");
|
fail("Server does not support account creation");
|
||||||
|
|
||||||
|
@ -90,11 +91,12 @@ public class CompressionTest extends SmackTestCase {
|
||||||
protected void tearDown() throws Exception {
|
protected void tearDown() throws Exception {
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
XMPPConnection setupConnection = new XMPPConnection(getHost(), getPort());
|
XMPPConnection setupConnection = new XMPPConnection(getHost(), getPort());
|
||||||
|
setupConnection.connect();
|
||||||
setupConnection.login("user0", "user0");
|
setupConnection.login("user0", "user0");
|
||||||
// Delete the created account for the test
|
// Delete the created account for the test
|
||||||
setupConnection.getAccountManager().deleteAccount();
|
setupConnection.getAccountManager().deleteAccount();
|
||||||
// Close the setupConnection
|
// Close the setupConnection
|
||||||
setupConnection.close();
|
setupConnection.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,6 +250,7 @@ public class MultiUserChatTest extends SmackTestCase {
|
||||||
try {
|
try {
|
||||||
// Anonymous user joins the new room
|
// Anonymous user joins the new room
|
||||||
XMPPConnection anonConnection = new XMPPConnection(getHost(), getPort());
|
XMPPConnection anonConnection = new XMPPConnection(getHost(), getPort());
|
||||||
|
anonConnection.connect();
|
||||||
anonConnection.loginAnonymously();
|
anonConnection.loginAnonymously();
|
||||||
MultiUserChat muc2 = new MultiUserChat(anonConnection, room);
|
MultiUserChat muc2 = new MultiUserChat(anonConnection, room);
|
||||||
muc2.join("testbot2");
|
muc2.join("testbot2");
|
||||||
|
@ -265,7 +266,7 @@ public class MultiUserChatTest extends SmackTestCase {
|
||||||
|
|
||||||
// Anonymous user leaves the room
|
// Anonymous user leaves the room
|
||||||
muc2.leave();
|
muc2.leave();
|
||||||
anonConnection.close();
|
anonConnection.disconnect();
|
||||||
Thread.sleep(250);
|
Thread.sleep(250);
|
||||||
// User1 checks the presence of Anonymous user in the room
|
// User1 checks the presence of Anonymous user in the room
|
||||||
presence = muc.getOccupantPresence(room + "/testbot2");
|
presence = muc.getOccupantPresence(room + "/testbot2");
|
||||||
|
@ -1766,6 +1767,7 @@ public class MultiUserChatTest extends SmackTestCase {
|
||||||
XMPPConnection[] conns = new XMPPConnection[20];
|
XMPPConnection[] conns = new XMPPConnection[20];
|
||||||
for (int i = 0; i < conns.length; i++) {
|
for (int i = 0; i < conns.length; i++) {
|
||||||
conns[i] = new XMPPConnection(getServiceName());
|
conns[i] = new XMPPConnection(getServiceName());
|
||||||
|
conns[i].connect();
|
||||||
conns[i].login(getUsername(1), getUsername(1), "resource-" + i);
|
conns[i].login(getUsername(1), getUsername(1), "resource-" + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1788,7 +1790,7 @@ public class MultiUserChatTest extends SmackTestCase {
|
||||||
// Each connection leaves the room and closes the connection
|
// Each connection leaves the room and closes the connection
|
||||||
for (int i = 0; i < mucs.length; i++) {
|
for (int i = 0; i < mucs.length; i++) {
|
||||||
mucs[i].leave();
|
mucs[i].leave();
|
||||||
conns[i].close();
|
conns[i].disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
Loading…
Reference in a new issue