1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-26 00:02:06 +01:00

Merge branch '4.2'

This commit is contained in:
Florian Schmaus 2017-02-11 20:55:43 +01:00
commit ca54f65b3e
346 changed files with 7037 additions and 5593 deletions

View file

@ -4,7 +4,6 @@ android:
- android-8 - android-8
jdk: jdk:
- oraclejdk8 - oraclejdk8
- oraclejdk7
sudo: false sudo: false
cache: cache:
directories: directories:

View file

@ -170,7 +170,7 @@ allprojects {
// version 52.0" error messages caused by the errorprone javac. // version 52.0" error messages caused by the errorprone javac.
// See https://github.com/tbroyer/gradle-errorprone-plugin/issues/18 for more information. // See https://github.com/tbroyer/gradle-errorprone-plugin/issues/18 for more information.
configurations.errorprone { configurations.errorprone {
resolutionStrategy.force 'com.google.errorprone:error_prone_core:2.0.5' resolutionStrategy.force 'com.google.errorprone:error_prone_core:2.0.15'
} }
} }

View file

@ -35,10 +35,6 @@
<property name="format" value="^\s+$"/> <property name="format" value="^\s+$"/>
<property name="message" value="Line containing only whitespace character(s)"/> <property name="message" value="Line containing only whitespace character(s)"/>
</module> </module>
<module name="RegexpSingleline">
<property name="format" value="^ +\t+"/>
<property name="message" value="Line containing tab(s) after space"/>
</module>
<module name="RegexpSingleline"> <module name="RegexpSingleline">
<!-- We use {2,} instead of + here to address the typical case where a file was written <!-- We use {2,} instead of + here to address the typical case where a file was written
with tabs but javadoc is causing '\t *' --> with tabs but javadoc is causing '\t *' -->
@ -89,6 +85,10 @@
<property name="message" value="Usage of println"/> <property name="message" value="Usage of println"/>
<property name="ignoreComments" value="true"/> <property name="ignoreComments" value="true"/>
</module> </module>
<module name="RegexpSinglelineJava">
<property name="format" value="^\t+"/>
<property name="message" value="Indent must not use tab characters. Use space instead."/>
</module>
<module name="JavadocMethod"> <module name="JavadocMethod">
<!-- TODO stricten those checks --> <!-- TODO stricten those checks -->
<property name="scope" value="public"/> <property name="scope" value="public"/>

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2014 Florian Schmaus * Copyright © 2014-2017 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -63,36 +63,36 @@ import android.os.SystemClock;
*/ */
public final class ServerPingWithAlarmManager extends Manager { public final class ServerPingWithAlarmManager extends Manager {
private static final Logger LOGGER = Logger.getLogger(ServerPingWithAlarmManager.class private static final Logger LOGGER = Logger.getLogger(ServerPingWithAlarmManager.class
.getName()); .getName());
private static final String PING_ALARM_ACTION = "org.igniterealtime.smackx.ping.ACTION"; private static final String PING_ALARM_ACTION = "org.igniterealtime.smackx.ping.ACTION";
private static final Map<XMPPConnection, ServerPingWithAlarmManager> INSTANCES = new WeakHashMap<XMPPConnection, ServerPingWithAlarmManager>(); private static final Map<XMPPConnection, ServerPingWithAlarmManager> INSTANCES = new WeakHashMap<XMPPConnection, ServerPingWithAlarmManager>();
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override @Override
public void connectionCreated(XMPPConnection connection) { public void connectionCreated(XMPPConnection connection) {
getInstanceFor(connection); getInstanceFor(connection);
} }
}); });
} }
public static synchronized ServerPingWithAlarmManager getInstanceFor(XMPPConnection connection) { public static synchronized ServerPingWithAlarmManager getInstanceFor(XMPPConnection connection) {
ServerPingWithAlarmManager serverPingWithAlarmManager = INSTANCES.get(connection); ServerPingWithAlarmManager serverPingWithAlarmManager = INSTANCES.get(connection);
if (serverPingWithAlarmManager == null) { if (serverPingWithAlarmManager == null) {
serverPingWithAlarmManager = new ServerPingWithAlarmManager(connection); serverPingWithAlarmManager = new ServerPingWithAlarmManager(connection);
INSTANCES.put(connection, serverPingWithAlarmManager); INSTANCES.put(connection, serverPingWithAlarmManager);
} }
return serverPingWithAlarmManager; return serverPingWithAlarmManager;
} }
private boolean mEnabled = true; private boolean mEnabled = true;
private ServerPingWithAlarmManager(XMPPConnection connection) { private ServerPingWithAlarmManager(XMPPConnection connection) {
super(connection); super(connection);
} }
/** /**
* If enabled, ServerPingWithAlarmManager will call {@link PingManager#pingServerIfNecessary()} * If enabled, ServerPingWithAlarmManager will call {@link PingManager#pingServerIfNecessary()}
@ -100,56 +100,56 @@ public final class ServerPingWithAlarmManager extends Manager {
* *
* @param enabled * @param enabled
*/ */
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
mEnabled = enabled; mEnabled = enabled;
} }
public boolean isEnabled() { public boolean isEnabled() {
return mEnabled; return mEnabled;
} }
private static final BroadcastReceiver ALARM_BROADCAST_RECEIVER = new BroadcastReceiver() { private static final BroadcastReceiver ALARM_BROADCAST_RECEIVER = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
LOGGER.fine("Ping Alarm broadcast received"); LOGGER.fine("Ping Alarm broadcast received");
Set<Entry<XMPPConnection, ServerPingWithAlarmManager>> managers; Set<Entry<XMPPConnection, ServerPingWithAlarmManager>> managers;
synchronized (ServerPingWithAlarmManager.class) { synchronized (ServerPingWithAlarmManager.class) {
// Make a copy to avoid ConcurrentModificationException when // Make a copy to avoid ConcurrentModificationException when
// iterating directly over INSTANCES and the Set is modified // iterating directly over INSTANCES and the Set is modified
// concurrently by creating a new ServerPingWithAlarmManager. // concurrently by creating a new ServerPingWithAlarmManager.
managers = new HashSet<>(INSTANCES.entrySet()); managers = new HashSet<>(INSTANCES.entrySet());
} }
for (Entry<XMPPConnection, ServerPingWithAlarmManager> entry : managers) { for (Entry<XMPPConnection, ServerPingWithAlarmManager> entry : managers) {
XMPPConnection connection = entry.getKey(); XMPPConnection connection = entry.getKey();
if (entry.getValue().isEnabled()) { if (entry.getValue().isEnabled()) {
LOGGER.fine("Calling pingServerIfNecessary for connection " LOGGER.fine("Calling pingServerIfNecessary for connection "
+ connection); + connection);
final PingManager pingManager = PingManager.getInstanceFor(connection); final PingManager pingManager = PingManager.getInstanceFor(connection);
// Android BroadcastReceivers have a timeout of 60 seconds. // Android BroadcastReceivers have a timeout of 60 seconds.
// The connections reply timeout may be higher, which causes // The connections reply timeout may be higher, which causes
// timeouts of the broadcast receiver and a subsequent ANR // timeouts of the broadcast receiver and a subsequent ANR
// of the App of the broadcast receiver. We therefore need // of the App of the broadcast receiver. We therefore need
// to call pingServerIfNecessary() in a new thread to avoid // to call pingServerIfNecessary() in a new thread to avoid
// this. It could happen that the device gets back to sleep // this. It could happen that the device gets back to sleep
// until the Thread runs, but that's a risk we are willing // until the Thread runs, but that's a risk we are willing
// to take into account as it's unlikely. // to take into account as it's unlikely.
Async.go(new Runnable() { Async.go(new Runnable() {
@Override @Override
public void run() { public void run() {
pingManager.pingServerIfNecessary(); pingManager.pingServerIfNecessary();
} }
}, "PingServerIfNecessary (" + connection.getConnectionCounter() + ')'); }, "PingServerIfNecessary (" + connection.getConnectionCounter() + ')');
} else { } else {
LOGGER.fine("NOT calling pingServerIfNecessary (disabled) on connection " LOGGER.fine("NOT calling pingServerIfNecessary (disabled) on connection "
+ connection.getConnectionCounter()); + connection.getConnectionCounter());
} }
} }
} }
}; };
private static Context sContext; private static Context sContext;
private static PendingIntent sPendingIntent; private static PendingIntent sPendingIntent;
private static AlarmManager sAlarmManager; private static AlarmManager sAlarmManager;
/** /**
* Register a pending intent with the AlarmManager to be broadcasted every half hour and * Register a pending intent with the AlarmManager to be broadcasted every half hour and
@ -158,21 +158,21 @@ public final class ServerPingWithAlarmManager extends Manager {
* *
* @param context * @param context
*/ */
public static void onCreate(Context context) { public static void onCreate(Context context) {
sContext = context; sContext = context;
context.registerReceiver(ALARM_BROADCAST_RECEIVER, new IntentFilter(PING_ALARM_ACTION)); context.registerReceiver(ALARM_BROADCAST_RECEIVER, new IntentFilter(PING_ALARM_ACTION));
sAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); sAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
sPendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(PING_ALARM_ACTION), 0); sPendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(PING_ALARM_ACTION), 0);
sAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, sAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR, SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
AlarmManager.INTERVAL_HALF_HOUR, sPendingIntent); AlarmManager.INTERVAL_HALF_HOUR, sPendingIntent);
} }
/** /**
* Unregister the alarm broadcast receiver and cancel the alarm. * Unregister the alarm broadcast receiver and cancel the alarm.
*/ */
public static void onDestroy() { public static void onDestroy() {
sContext.unregisterReceiver(ALARM_BROADCAST_RECEIVER); sContext.unregisterReceiver(ALARM_BROADCAST_RECEIVER);
sAlarmManager.cancel(sPendingIntent); sAlarmManager.cancel(sPendingIntent);
} }
} }

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2014 Florian Schmaus * Copyright © 2014-2017 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,12 +28,12 @@ import org.jivesoftware.smack.util.stringencoder.android.AndroidBase64UrlSafeEnc
public class AndroidSmackInitializer implements SmackInitializer { public class AndroidSmackInitializer implements SmackInitializer {
@Override @Override
public List<Exception> initialize() { public List<Exception> initialize() {
SmackConfiguration.setDefaultHostnameVerifier(new StrictHostnameVerifier()); SmackConfiguration.setDefaultHostnameVerifier(new StrictHostnameVerifier());
Base64.setEncoder(AndroidBase64Encoder.getInstance()); Base64.setEncoder(AndroidBase64Encoder.getInstance());
Base64UrlSafeEncoder.setEncoder(AndroidBase64UrlSafeEncoder.getInstance()); Base64UrlSafeEncoder.setEncoder(AndroidBase64UrlSafeEncoder.getInstance());
return null; return null;
} }
} }

View file

@ -55,6 +55,7 @@ public final class BOSHConfiguration extends ConnectionConfiguration {
return proxy != null; return proxy != null;
} }
@Override
public ProxyInfo getProxyInfo() { public ProxyInfo getProxyInfo() {
return proxy; return proxy;
} }

View file

@ -203,11 +203,13 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
saslFeatureReceived.reportSuccess(); saslFeatureReceived.reportSuccess();
} }
@Override
public boolean isSecureConnection() { public boolean isSecureConnection() {
// TODO: Implement SSL usage // TODO: Implement SSL usage
return false; return false;
} }
@Override
public boolean isUsingCompression() { public boolean isUsingCompression() {
// TODO: Implement compression // TODO: Implement compression
return false; return false;
@ -313,16 +315,25 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
/** /**
* Initialize the SmackDebugger which allows to log and debug XML traffic. * Initialize the SmackDebugger which allows to log and debug XML traffic.
*/ */
@Override
protected void initDebugger() { protected void initDebugger() {
// TODO: Maybe we want to extend the SmackDebugger for simplification // TODO: Maybe we want to extend the SmackDebugger for simplification
// and a performance boost. // and a performance boost.
// Initialize a empty writer which discards all data. // Initialize a empty writer which discards all data.
writer = new Writer() { writer = new Writer() {
public void write(char[] cbuf, int off, int len) { /* ignore */} @Override
public void close() { /* ignore */ } public void write(char[] cbuf, int off, int len) {
public void flush() { /* ignore */ } /* ignore */}
};
@Override
public void close() {
/* ignore */ }
@Override
public void flush() {
/* ignore */ }
};
// Initialize a pipe for received raw data. // Initialize a pipe for received raw data.
try { try {
@ -338,6 +349,7 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
// Add listeners for the received and sent raw data. // Add listeners for the received and sent raw data.
client.addBOSHClientResponseListener(new BOSHClientResponseListener() { client.addBOSHClientResponseListener(new BOSHClientResponseListener() {
@Override
public void responseReceived(BOSHMessageEvent event) { public void responseReceived(BOSHMessageEvent event) {
if (event.getBody() != null) { if (event.getBody() != null) {
try { try {
@ -350,6 +362,7 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
} }
}); });
client.addBOSHClientRequestListener(new BOSHClientRequestListener() { client.addBOSHClientRequestListener(new BOSHClientRequestListener() {
@Override
public void requestSent(BOSHMessageEvent event) { public void requestSent(BOSHMessageEvent event) {
if (event.getBody() != null) { if (event.getBody() != null) {
try { try {
@ -366,6 +379,7 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
private Thread thread = this; private Thread thread = this;
private int bufferLength = 1024; private int bufferLength = 1024;
@Override
public void run() { public void run() {
try { try {
char[] cbuf = new char[bufferLength]; char[] cbuf = new char[bufferLength];
@ -406,6 +420,7 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
* Process the connection listeners and try to login if the * Process the connection listeners and try to login if the
* connection was formerly authenticated and is now reconnected. * connection was formerly authenticated and is now reconnected.
*/ */
@Override
public void connectionEvent(BOSHClientConnEvent connEvent) { public void connectionEvent(BOSHClientConnEvent connEvent) {
try { try {
if (connEvent.isConnected()) { if (connEvent.isConnected()) {
@ -463,6 +478,7 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection {
* *
* @param event the BOSH client response which includes the received packet. * @param event the BOSH client response which includes the received packet.
*/ */
@Override
public void responseReceived(BOSHMessageEvent event) { public void responseReceived(BOSHMessageEvent event) {
AbstractBody body = event.getBody(); AbstractBody body = event.getBody();
if (body != null) { if (body != null) {

View file

@ -1494,6 +1494,12 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
final StanzaListener packetListener = new StanzaListener() { final StanzaListener packetListener = new StanzaListener() {
@Override @Override
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException { public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException {
boolean removed = removeAsyncStanzaListener(this);
if (!removed) {
// We lost a race against the "no response" handling runnable. Avoid calling the callback, as the
// exception callback will be invoked (if any).
return;
}
try { try {
XMPPErrorException.ifHasErrorThenThrow(packet); XMPPErrorException.ifHasErrorThenThrow(packet);
callback.processStanza(packet); callback.processStanza(packet);
@ -1503,9 +1509,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
exceptionCallback.processException(e); exceptionCallback.processException(e);
} }
} }
finally {
removeAsyncStanzaListener(this);
}
} }
}; };
removeCallbacksService.schedule(new Runnable() { removeCallbacksService.schedule(new Runnable() {
@ -1613,6 +1616,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
private long lastStanzaReceived; private long lastStanzaReceived;
@Override
public long getLastStanzaReceived() { public long getLastStanzaReceived() {
return lastStanzaReceived; return lastStanzaReceived;
} }

View file

@ -576,14 +576,17 @@ public abstract class ConnectionConfiguration {
} }
/** /**
* Set the resource to use. * Set the resource we are requesting from the server.
* <p> * <p>
* If <code>resource</code> is <code>null</code>, then the server will automatically create a resource for the * If <code>resource</code> is <code>null</code>, the default, then the server will automatically create a
* client. Default resource is "Smack". * resource for the client. Note that XMPP clients only suggest this resource to the server. XMPP servers are
* allowed to ignore the client suggested resource and instead assign a completely different
* resource (see RFC 6120 § 7.7.1).
* </p> * </p>
* *
* @param resource the resource to use. * @param resource the resource to use.
* @return a reference to this builder. * @return a reference to this builder.
* @see <a href="https://tools.ietf.org/html/rfc6120#section-7.7.1">RFC 6120 § 7.7.1</a>
*/ */
public B setResource(Resourcepart resource) { public B setResource(Resourcepart resource) {
this.resource = resource; this.resource = resource;
@ -591,7 +594,7 @@ public abstract class ConnectionConfiguration {
} }
/** /**
* Set the resource to use. * Set the resource we are requesting from the server.
* *
* @param resource the non-null CharSequence to use a resource. * @param resource the non-null CharSequence to use a resource.
* @return a reference ot this builder. * @return a reference ot this builder.

View file

@ -70,6 +70,7 @@ public final class ReconnectionManager {
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) { public void connectionCreated(XMPPConnection connection) {
if (connection instanceof AbstractXMPPConnection) { if (connection instanceof AbstractXMPPConnection) {
ReconnectionManager.getInstanceFor((AbstractXMPPConnection) connection); ReconnectionManager.getInstanceFor((AbstractXMPPConnection) connection);
@ -204,6 +205,7 @@ public final class ReconnectionManager {
/** /**
* The process will try the reconnection until the connection succeed or the user cancel it * The process will try the reconnection until the connection succeed or the user cancel it
*/ */
@Override
public void run() { public void run() {
final AbstractXMPPConnection connection = weakRefConnection.get(); final AbstractXMPPConnection connection = weakRefConnection.get();
if (connection == null) { if (connection == null) {

View file

@ -37,6 +37,7 @@ import org.jivesoftware.smack.sasl.core.SASLXOauth2Mechanism;
import org.jivesoftware.smack.sasl.core.SCRAMSHA1Mechanism; import org.jivesoftware.smack.sasl.core.SCRAMSHA1Mechanism;
import org.jivesoftware.smack.sasl.core.ScramSha1PlusMechanism; import org.jivesoftware.smack.sasl.core.ScramSha1PlusMechanism;
import org.jivesoftware.smack.util.FileUtils; import org.jivesoftware.smack.util.FileUtils;
import org.jivesoftware.smack.util.StringUtils;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory; import org.xmlpull.v1.XmlPullParserFactory;
@ -60,7 +61,7 @@ public final class SmackInitialization {
static { static {
String smackVersion; String smackVersion;
try { try {
BufferedReader reader = new BufferedReader(new InputStreamReader(FileUtils.getStreamForUrl("classpath:org.jivesoftware.smack/version", null))); BufferedReader reader = new BufferedReader(new InputStreamReader(FileUtils.getStreamForUrl("classpath:org.jivesoftware.smack/version", null), StringUtils.UTF8));
smackVersion = reader.readLine(); smackVersion = reader.readLine();
try { try {
reader.close(); reader.close();
@ -232,7 +233,7 @@ public final class SmackInitialization {
} }
} }
if (SmackInitializer.class.isAssignableFrom(initClass)) { if (SmackInitializer.class.isAssignableFrom(initClass)) {
SmackInitializer initializer = (SmackInitializer) initClass.newInstance(); SmackInitializer initializer = (SmackInitializer) initClass.getConstructor().newInstance();
List<Exception> exceptions = initializer.initialize(); List<Exception> exceptions = initializer.initialize();
if (exceptions == null || exceptions.size() == 0) { if (exceptions == null || exceptions.size() == 0) {
LOGGER.log(Level.FINE, "Loaded SmackInitializer " + className); LOGGER.log(Level.FINE, "Loaded SmackInitializer " + className);

View file

@ -49,6 +49,7 @@ public abstract class AbstractDebugger implements SmackDebugger {
// Create a special Reader that wraps the main Reader and logs data to the GUI. // Create a special Reader that wraps the main Reader and logs data to the GUI.
this.reader = new ObservableReader(reader); this.reader = new ObservableReader(reader);
readerListener = new ReaderListener() { readerListener = new ReaderListener() {
@Override
public void read(String str) { public void read(String str) {
log("RECV (" + connection.getConnectionCounter() + "): " + str); log("RECV (" + connection.getConnectionCounter() + "): " + str);
} }
@ -58,6 +59,7 @@ public abstract class AbstractDebugger implements SmackDebugger {
// Create a special Writer that wraps the main Writer and logs data to the GUI. // Create a special Writer that wraps the main Writer and logs data to the GUI.
this.writer = new ObservableWriter(writer); this.writer = new ObservableWriter(writer);
writerListener = new WriterListener() { writerListener = new WriterListener() {
@Override
public void write(String str) { public void write(String str) {
log("SENT (" + connection.getConnectionCounter() + "): " + str); log("SENT (" + connection.getConnectionCounter() + "): " + str);
} }
@ -68,6 +70,7 @@ public abstract class AbstractDebugger implements SmackDebugger {
// the GUI. This is what we call "interpreted" packet data, since it's the packet // the GUI. This is what we call "interpreted" packet data, since it's the packet
// data as Smack sees it and not as it's coming in as raw XML. // data as Smack sees it and not as it's coming in as raw XML.
listener = new StanzaListener() { listener = new StanzaListener() {
@Override
public void processStanza(Stanza packet) { public void processStanza(Stanza packet) {
if (printInterpreted) { if (printInterpreted) {
log("RCV PKT (" + connection.getConnectionCounter() + "): " + packet.toXML()); log("RCV PKT (" + connection.getConnectionCounter() + "): " + packet.toXML());
@ -76,10 +79,12 @@ public abstract class AbstractDebugger implements SmackDebugger {
}; };
connListener = new ConnectionListener() { connListener = new ConnectionListener() {
@Override
public void connected(XMPPConnection connection) { public void connected(XMPPConnection connection) {
log("XMPPConnection connected (" log("XMPPConnection connected ("
+ connection + ")"); + connection + ")");
} }
@Override
public void authenticated(XMPPConnection connection, boolean resumed) { public void authenticated(XMPPConnection connection, boolean resumed) {
String logString = "XMPPConnection authenticated (" + connection + ")"; String logString = "XMPPConnection authenticated (" + connection + ")";
if (resumed) { if (resumed) {
@ -87,6 +92,7 @@ public abstract class AbstractDebugger implements SmackDebugger {
} }
log(logString); log(logString);
} }
@Override
public void connectionClosed() { public void connectionClosed() {
log( log(
"XMPPConnection closed (" + "XMPPConnection closed (" +
@ -94,24 +100,28 @@ public abstract class AbstractDebugger implements SmackDebugger {
")"); ")");
} }
@Override
public void connectionClosedOnError(Exception e) { public void connectionClosedOnError(Exception e) {
log( log(
"XMPPConnection closed due to an exception (" + "XMPPConnection closed due to an exception (" +
connection + connection +
")", e); ")", e);
} }
@Override
public void reconnectionFailed(Exception e) { public void reconnectionFailed(Exception e) {
log( log(
"Reconnection failed due to an exception (" + "Reconnection failed due to an exception (" +
connection + connection +
")", e); ")", e);
} }
@Override
public void reconnectionSuccessful() { public void reconnectionSuccessful() {
log( log(
"XMPPConnection reconnected (" + "XMPPConnection reconnected (" +
connection + connection +
")"); ")");
} }
@Override
public void reconnectingIn(int seconds) { public void reconnectingIn(int seconds) {
log( log(
"XMPPConnection (" + "XMPPConnection (" +
@ -125,6 +135,7 @@ public abstract class AbstractDebugger implements SmackDebugger {
protected abstract void log(String logMessage, Throwable throwable); protected abstract void log(String logMessage, Throwable throwable);
@Override
public Reader newConnectionReader(Reader newReader) { public Reader newConnectionReader(Reader newReader) {
reader.removeReaderListener(readerListener); reader.removeReaderListener(readerListener);
ObservableReader debugReader = new ObservableReader(newReader); ObservableReader debugReader = new ObservableReader(newReader);
@ -133,6 +144,7 @@ public abstract class AbstractDebugger implements SmackDebugger {
return reader; return reader;
} }
@Override
public Writer newConnectionWriter(Writer newWriter) { public Writer newConnectionWriter(Writer newWriter) {
writer.removeWriterListener(writerListener); writer.removeWriterListener(writerListener);
ObservableWriter debugWriter = new ObservableWriter(newWriter); ObservableWriter debugWriter = new ObservableWriter(newWriter);
@ -159,18 +171,22 @@ public abstract class AbstractDebugger implements SmackDebugger {
connection.addConnectionListener(connListener); connection.addConnectionListener(connListener);
} }
@Override
public Reader getReader() { public Reader getReader() {
return reader; return reader;
} }
@Override
public Writer getWriter() { public Writer getWriter() {
return writer; return writer;
} }
@Override
public StanzaListener getReaderListener() { public StanzaListener getReaderListener() {
return listener; return listener;
} }
@Override
public StanzaListener getWriterListener() { public StanzaListener getWriterListener() {
return null; return null;
} }

View file

@ -0,0 +1,72 @@
/**
*
* Copyright 2017 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.filter;
import org.jivesoftware.smack.packet.Stanza;
import org.jxmpp.jid.Jid;
public abstract class AbstractFromToMatchesFilter implements StanzaFilter {
private final Jid address;
/**
* Flag that indicates if the checking will be done against bare JID addresses or full JIDs.
*/
private final boolean ignoreResourcepart;
/**
* Creates a filter matching on the address returned by {@link #getAddressToCompare(Stanza)}. The address must be
* the same as the filter address. The second parameter specifies whether the full or the bare addresses are
* compared.
*
* @param address The address to filter for. If <code>null</code> is given, then
* {@link #getAddressToCompare(Stanza)} must also return <code>null</code> to match.
* @param ignoreResourcepart
*/
protected AbstractFromToMatchesFilter(Jid address, boolean ignoreResourcepart) {
if (address != null && ignoreResourcepart) {
this.address = address.asBareJid();
}
else {
this.address = address;
}
this.ignoreResourcepart = ignoreResourcepart;
}
@Override
public final boolean accept(final Stanza stanza) {
Jid stanzaAddress = getAddressToCompare(stanza);
if (stanzaAddress == null) {
return address == null;
}
if (ignoreResourcepart) {
stanzaAddress = stanzaAddress.asBareJid();
}
return stanzaAddress.equals(address);
}
protected abstract Jid getAddressToCompare(Stanza stanza);
@Override
public final String toString() {
String matchMode = ignoreResourcepart ? "ignoreResourcepart" : "full";
return getClass().getSimpleName() + " (" + matchMode + "): " + address;
}
}

View file

@ -44,6 +44,7 @@ public class AndFilter extends AbstractListFilter implements StanzaFilter {
super(filters); super(filters);
} }
@Override
public boolean accept(Stanza packet) { public boolean accept(Stanza packet) {
for (StanzaFilter filter : filters) { for (StanzaFilter filter : filters) {
if (!filter.accept(packet)) { if (!filter.accept(packet)) {

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2003-2014 Jive Software. * Copyright 2003-2014 Jive Software, 2017 Florian Schmaus.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.jivesoftware.smack.filter; package org.jivesoftware.smack.filter;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
@ -28,14 +27,9 @@ import org.jxmpp.jid.Jid;
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
public class FromMatchesFilter implements StanzaFilter { public final class FromMatchesFilter extends AbstractFromToMatchesFilter {
private final Jid address; public final static FromMatchesFilter MATCH_NO_FROM_SET = create(null);
/**
* Flag that indicates if the checking will be done against bare JID addresses or full JIDs.
*/
private final boolean ignoreResourcepart;
/** /**
* Creates a filter matching on the "from" field. The from address must be the same as the * Creates a filter matching on the "from" field. The from address must be the same as the
@ -47,13 +41,7 @@ public class FromMatchesFilter implements StanzaFilter {
* @param ignoreResourcepart * @param ignoreResourcepart
*/ */
public FromMatchesFilter(Jid address, boolean ignoreResourcepart) { public FromMatchesFilter(Jid address, boolean ignoreResourcepart) {
if (address != null && ignoreResourcepart) { super(address, ignoreResourcepart);
this.address = address.asBareJid();
}
else {
this.address = address;
}
this.ignoreResourcepart = ignoreResourcepart;
} }
/** /**
@ -61,51 +49,38 @@ public class FromMatchesFilter implements StanzaFilter {
* the filter address with the bare from address. Otherwise, compares the filter address * the filter address with the bare from address. Otherwise, compares the filter address
* with the full from address. * with the full from address.
* *
* @param address The address to filter for. If <code>null</code> is given, the stanza(/packet) must not * @param address The address to filter for. If <code>null</code> is given, the stanza must not
* have a from address. * have a from address.
*/ */
public static FromMatchesFilter create(Jid address) { public static FromMatchesFilter create(Jid address) {
return new FromMatchesFilter(address, address.hasNoResource()) ; return new FromMatchesFilter(address, address != null ? address.hasNoResource() : false) ;
} }
/** /**
* Creates a filter matching on the "from" field. Compares the bare version of from and filter * Creates a filter matching on the "from" field. Compares the bare version of from and filter
* address. * address.
* *
* @param address The address to filter for. If <code>null</code> is given, the stanza(/packet) must not * @param address The address to filter for. If <code>null</code> is given, the stanza must not
* have a from address. * have a from address.
*/ */
public static FromMatchesFilter createBare(Jid address) { public static FromMatchesFilter createBare(Jid address) {
address = (address == null) ? null : address;
return new FromMatchesFilter(address, true); return new FromMatchesFilter(address, true);
} }
/** /**
* Creates a filter matching on the "from" field. Compares the full version of from and filter * Creates a filter matching on the "from" field. Compares the full version, if available, of from and filter
* address. * address.
* *
* @param address The address to filter for. If <code>null</code> is given, the stanza(/packet) must not * @param address The address to filter for. If <code>null</code> is given, the stanza must not
* have a from address. * have a from address.
*/ */
public static FromMatchesFilter createFull(Jid address) { public static FromMatchesFilter createFull(Jid address) {
return new FromMatchesFilter(address, false); return new FromMatchesFilter(address, false);
} }
public boolean accept(Stanza packet) { @Override
Jid from = packet.getFrom(); protected Jid getAddressToCompare(Stanza stanza) {
if (from == null) { return stanza.getFrom();
return address == null;
}
if (ignoreResourcepart) {
from = from.asBareJid();
}
return from.equals(address);
} }
public String toString() {
String matchMode = ignoreResourcepart ? "ignoreResourcepart" : "full";
return getClass().getSimpleName() + " (" + matchMode + "): " + address;
}
} }

View file

@ -35,12 +35,12 @@ public final class IQTypeFilter extends FlexibleStanzaTypeFilter<IQ> {
public static final StanzaFilter ERROR = new IQTypeFilter(Type.error); public static final StanzaFilter ERROR = new IQTypeFilter(Type.error);
public static final StanzaFilter GET_OR_SET = new OrFilter(GET, SET); public static final StanzaFilter GET_OR_SET = new OrFilter(GET, SET);
private final IQ.Type type; private final IQ.Type type;
private IQTypeFilter(IQ.Type type) { private IQTypeFilter(IQ.Type type) {
super(IQ.class); super(IQ.class);
this.type = Objects.requireNonNull(type, "Type must not be null"); this.type = Objects.requireNonNull(type, "Type must not be null");
} }
@Override @Override
protected boolean acceptSpecific(IQ iq) { protected boolean acceptSpecific(IQ iq) {

View file

@ -39,6 +39,7 @@ public class NotFilter implements StanzaFilter {
this.filter = Objects.requireNonNull(filter, "Parameter must not be null."); this.filter = Objects.requireNonNull(filter, "Parameter must not be null.");
} }
@Override
public boolean accept(Stanza packet) { public boolean accept(Stanza packet) {
return !filter.accept(packet); return !filter.accept(packet);
} }

View file

@ -67,6 +67,7 @@ public class PacketExtensionFilter implements StanzaFilter {
this(packetExtension.getElementName(), packetExtension.getNamespace()); this(packetExtension.getElementName(), packetExtension.getNamespace());
} }
@Override
public boolean accept(Stanza packet) { public boolean accept(Stanza packet) {
return packet.hasExtension(elementName, namespace); return packet.hasExtension(elementName, namespace);
} }

View file

@ -54,10 +54,12 @@ public class PacketIDFilter implements StanzaFilter {
this.packetID = packetID; this.packetID = packetID;
} }
@Override
public boolean accept(Stanza packet) { public boolean accept(Stanza packet) {
return packetID.equals(packet.getStanzaId()); return packetID.equals(packet.getStanzaId());
} }
@Override
public String toString() { public String toString() {
return getClass().getSimpleName() + ": id=" + packetID; return getClass().getSimpleName() + ": id=" + packetID;
} }

View file

@ -51,6 +51,7 @@ public class PacketTypeFilter implements StanzaFilter {
this.packetType = packetType; this.packetType = packetType;
} }
@Override
public boolean accept(Stanza packet) { public boolean accept(Stanza packet) {
return packetType.isInstance(packet); return packetType.isInstance(packet);
} }

View file

@ -65,6 +65,7 @@ public class StanzaExtensionFilter implements StanzaFilter {
this(packetExtension.getElementName(), packetExtension.getNamespace()); this(packetExtension.getElementName(), packetExtension.getNamespace());
} }
@Override
public boolean accept(Stanza packet) { public boolean accept(Stanza packet) {
return packet.hasExtension(elementName, namespace); return packet.hasExtension(elementName, namespace);
} }

View file

@ -47,10 +47,12 @@ public class StanzaIdFilter implements StanzaFilter {
this.stanzaId = StringUtils.requireNotNullOrEmpty(stanzaID, "Stanza ID must not be null or empty."); this.stanzaId = StringUtils.requireNotNullOrEmpty(stanzaID, "Stanza ID must not be null or empty.");
} }
@Override
public boolean accept(Stanza stanza) { public boolean accept(Stanza stanza) {
return stanzaId.equals(stanza.getStanzaId()); return stanzaId.equals(stanza.getStanzaId());
} }
@Override
public String toString() { public String toString() {
return getClass().getSimpleName() + ": id=" + stanzaId; return getClass().getSimpleName() + ": id=" + stanzaId;
} }

View file

@ -51,6 +51,7 @@ public final class StanzaTypeFilter implements StanzaFilter {
this.packetType = packetType; this.packetType = packetType;
} }
@Override
public boolean accept(Stanza packet) { public boolean accept(Stanza packet) {
return packetType.isInstance(packet); return packetType.isInstance(packet);
} }

View file

@ -19,6 +19,12 @@ package org.jivesoftware.smack.filter;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jxmpp.jid.Jid; import org.jxmpp.jid.Jid;
/**
* Match based on the 'to' attribute of a Stanza.
*
* @deprecated use {@link ToMatchesFilter} instead.
*/
@Deprecated
public class ToFilter implements StanzaFilter { public class ToFilter implements StanzaFilter {
private final Jid to; private final Jid to;

View file

@ -0,0 +1,69 @@
/**
*
* Copyright 2017 Florian Schmaus.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.filter;
import org.jivesoftware.smack.packet.Stanza;
import org.jxmpp.jid.Jid;
public final class ToMatchesFilter extends AbstractFromToMatchesFilter {
public static final ToMatchesFilter MATCH_NO_TO_SET = create(null);
public ToMatchesFilter(Jid address, boolean ignoreResourcepart) {
super(address, ignoreResourcepart);
}
/**
* Creates a filter matching on the "to" field. If the filter address is bare, compares
* the filter address with the bare from address. Otherwise, compares the filter address
* with the full from address.
*
* @param address The address to filter for. If <code>null</code> is given, the stanza must not
* have a from address.
*/
public static ToMatchesFilter create(Jid address) {
return new ToMatchesFilter(address, address != null ? address.hasNoResource() : false) ;
}
/**
* Creates a filter matching on the "to" field. Compares the bare version of to and filter
* address.
*
* @param address The address to filter for. If <code>null</code> is given, the stanza must not
* have a from address.
*/
public static ToMatchesFilter createBare(Jid address) {
return new ToMatchesFilter(address, true);
}
/**
* Creates a filter matching on the "to" field. Compares the full version, if available, of to and filter
* address.
*
* @param address The address to filter for. If <code>null</code> is given, the stanza must not
* have a from address.
*/
public static ToMatchesFilter createFull(Jid address) {
return new ToMatchesFilter(address, false);
}
@Override
protected Jid getAddressToCompare(Stanza stanza) {
return stanza.getTo();
}
}

View file

@ -70,6 +70,7 @@ public class DefaultExtensionElement implements ExtensionElement {
* *
* @return the XML element name of the stanza(/packet) extension. * @return the XML element name of the stanza(/packet) extension.
*/ */
@Override
public String getElementName() { public String getElementName() {
return elementName; return elementName;
} }
@ -79,6 +80,7 @@ public class DefaultExtensionElement implements ExtensionElement {
* *
* @return the XML namespace of the stanza(/packet) extension. * @return the XML namespace of the stanza(/packet) extension.
*/ */
@Override
public String getNamespace() { public String getNamespace() {
return namespace; return namespace;
} }

View file

@ -570,6 +570,7 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
} }
@Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
@ -578,6 +579,7 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
return result; return result;
} }
@Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
@ -632,6 +634,7 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
return message; return message;
} }
@Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
@ -640,6 +643,7 @@ public final class Message extends Stanza implements TypedCloneable<Message> {
return result; return result;
} }
@Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;

View file

@ -78,7 +78,7 @@ public class IntrospectionProvider{
IOException, IllegalArgumentException, InvocationTargetException, IOException, IllegalArgumentException, InvocationTargetException,
ClassNotFoundException { ClassNotFoundException {
ParserUtils.assertAtStartTag(parser); ParserUtils.assertAtStartTag(parser);
Object object = objectClass.newInstance(); Object object = objectClass.getConstructor().newInstance();
outerloop: while (true) { outerloop: while (true) {
int eventType = parser.next(); int eventType = parser.next();
switch (eventType) { switch (eventType) {

View file

@ -83,7 +83,8 @@ public class ProviderFileLoader implements ProviderLoader {
// reflection later to create instances of the class. // reflection later to create instances of the class.
// Add the provider to the map. // Add the provider to the map.
if (IQProvider.class.isAssignableFrom(provider)) { if (IQProvider.class.isAssignableFrom(provider)) {
iqProviders.add(new IQProviderInfo(elementName, namespace, (IQProvider<IQ>) provider.newInstance())); IQProvider<IQ> iqProvider = (IQProvider<IQ>) provider.getConstructor().newInstance();
iqProviders.add(new IQProviderInfo(elementName, namespace, iqProvider));
} }
else { else {
exceptions.add(new IllegalArgumentException(className + " is not a IQProvider")); exceptions.add(new IllegalArgumentException(className + " is not a IQProvider"));
@ -96,7 +97,9 @@ public class ProviderFileLoader implements ProviderLoader {
// then we'll use reflection later to create instances // then we'll use reflection later to create instances
// of the class. // of the class.
if (ExtensionElementProvider.class.isAssignableFrom(provider)) { if (ExtensionElementProvider.class.isAssignableFrom(provider)) {
extProviders.add(new ExtensionProviderInfo(elementName, namespace, (ExtensionElementProvider<ExtensionElement>) provider.newInstance())); ExtensionElementProvider<ExtensionElement> extensionElementProvider = (ExtensionElementProvider<ExtensionElement>) provider.getConstructor().newInstance();
extProviders.add(new ExtensionProviderInfo(elementName, namespace,
extensionElementProvider));
} }
else { else {
exceptions.add(new IllegalArgumentException(className exceptions.add(new IllegalArgumentException(className
@ -104,9 +107,10 @@ public class ProviderFileLoader implements ProviderLoader {
} }
break; break;
case "streamFeatureProvider": case "streamFeatureProvider":
ExtensionElementProvider<ExtensionElement> streamFeatureProvider = (ExtensionElementProvider<ExtensionElement>) provider.getConstructor().newInstance();
sfProviders.add(new StreamFeatureProviderInfo(elementName, sfProviders.add(new StreamFeatureProviderInfo(elementName,
namespace, namespace,
(ExtensionElementProvider<ExtensionElement>) provider.newInstance())); streamFeatureProvider));
break; break;
default: default:
LOGGER.warning("Unknown provider type: " + typeName); LOGGER.warning("Unknown provider type: " + typeName);

View file

@ -23,6 +23,8 @@ import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import org.jivesoftware.smack.util.StringUtils;
/** /**
* Socket factory for socks4 proxy. * Socket factory for socks4 proxy.
* *
@ -89,7 +91,8 @@ public class Socks4ProxySocketConnection implements ProxySocketConnection {
if(user!=null) if(user!=null)
{ {
System.arraycopy(user.getBytes(), 0, buf, index, user.length()); byte[] userBytes = user.getBytes(StringUtils.UTF8);
System.arraycopy(userBytes, 0, buf, index, user.length());
index+=user.length(); index+=user.length();
} }
buf[index++]=0; buf[index++]=0;

View file

@ -22,6 +22,8 @@ import java.io.OutputStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import org.jivesoftware.smack.util.StringUtils;
/** /**
* Socket factory for Socks5 proxy. * Socket factory for Socks5 proxy.
* *
@ -132,11 +134,13 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection {
index=0; index=0;
buf[index++]=1; buf[index++]=1;
buf[index++]=(byte)(user.length()); buf[index++]=(byte)(user.length());
System.arraycopy(user.getBytes(), 0, buf, index, byte[] userBytes = user.getBytes(StringUtils.UTF8);
System.arraycopy(userBytes, 0, buf, index,
user.length()); user.length());
index+=user.length(); index+=user.length();
buf[index++]=(byte)(passwd.length()); byte[] passwordBytes = user.getBytes(StringUtils.UTF8);
System.arraycopy(passwd.getBytes(), 0, buf, index, buf[index++]=(byte)(passwordBytes.length);
System.arraycopy(passwordBytes, 0, buf, index,
passwd.length()); passwd.length());
index+=passwd.length(); index+=passwd.length();
@ -210,7 +214,7 @@ public class Socks5ProxySocketConnection implements ProxySocketConnection {
buf[index++]=1; // CONNECT buf[index++]=1; // CONNECT
buf[index++]=0; buf[index++]=0;
byte[] hostb= host.getBytes(); byte[] hostb= host.getBytes(StringUtils.UTF8);
int len=hostb.length; int len=hostb.length;
buf[index++]=3; // DOMAINNAME buf[index++]=3; // DOMAINNAME
buf[index++]=(byte)(len); buf[index++]=(byte)(len);

View file

@ -265,8 +265,11 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
return null; return null;
} }
@Override
public final int compareTo(SASLMechanism other) { public final int compareTo(SASLMechanism other) {
return getPriority() - other.getPriority(); // Switch to Integer.compare(int, int) once Smack is on Android 19 or higher.
Integer ourPriority = getPriority();
return ourPriority.compareTo(other.getPriority());
} }
/** /**
@ -298,7 +301,7 @@ public abstract class SASLMechanism implements Comparable<SASLMechanism> {
} }
/** /**
* SASLprep the given String. * SASLprep the given String. The resulting String is in UTF-8.
* *
* @param string the String to sasl prep. * @param string the String to sasl prep.
* @return the given String SASL preped * @return the given String SASL preped

View file

@ -30,6 +30,7 @@ public class SASLAnonymous extends SASLMechanism {
public static final String NAME = "ANONYMOUS"; public static final String NAME = "ANONYMOUS";
@Override
public String getName() { public String getName() {
return NAME; return NAME;
} }

View file

@ -16,6 +16,7 @@
*/ */
package org.jivesoftware.smack.sasl.core; package org.jivesoftware.smack.sasl.core;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Collections; import java.util.Collections;
@ -105,7 +106,15 @@ public abstract class ScramMechanism extends SASLMechanism {
@Override @Override
protected byte[] evaluateChallenge(byte[] challenge) throws SmackException { protected byte[] evaluateChallenge(byte[] challenge) throws SmackException {
final String challengeString = new String(challenge); String challengeString;
try {
// TODO: Where is it specified that this is an UTF-8 encoded string?
challengeString = new String(challenge, StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
switch (state) { switch (state) {
case AUTH_TEXT_SENT: case AUTH_TEXT_SENT:
final String serverFirstMessage = challengeString; final String serverFirstMessage = challengeString;
@ -358,14 +367,21 @@ public abstract class ScramMechanism extends SASLMechanism {
* (PRF) and with dkLen == output length of HMAC() == output length of H(). * (PRF) and with dkLen == output length of HMAC() == output length of H().
* </p> * </p>
* *
* @param str * @param normalizedPassword the normalized password.
* @param salt * @param salt
* @param iterations * @param iterations
* @return the result of the Hi function. * @return the result of the Hi function.
* @throws SmackException * @throws SmackException
*/ */
private byte[] hi(String str, byte[] salt, int iterations) throws SmackException { private byte[] hi(String normalizedPassword, byte[] salt, int iterations) throws SmackException {
byte[] key = str.getBytes(); byte[] key;
try {
// According to RFC 5802 § 2.2, the resulting string of the normalization is also in UTF-8.
key = normalizedPassword.getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError();
}
// U1 := HMAC(str, salt + INT(1)) // U1 := HMAC(str, salt + INT(1))
byte[] u = hmac(key, ByteUtils.concact(salt, ONE)); byte[] u = hmac(key, ByteUtils.concact(salt, ONE));
byte[] res = u.clone(); byte[] res = u.clone();

View file

@ -240,6 +240,7 @@ public class ArrayBlockingQueueWithShutdown<E> extends AbstractQueue<E> implemen
* @param e the element to add. * @param e the element to add.
* @throws InterruptedException if interrupted while waiting or if the queue was shut down. * @throws InterruptedException if interrupted while waiting or if the queue was shut down.
*/ */
@Override
public void put(E e) throws InterruptedException { public void put(E e) throws InterruptedException {
checkNotNull(e); checkNotNull(e);
lock.lockInterruptibly(); lock.lockInterruptibly();
@ -452,6 +453,7 @@ public class ArrayBlockingQueueWithShutdown<E> extends AbstractQueue<E> implemen
} }
} }
@Override
public boolean hasNext() { public boolean hasNext() {
return nextIndex >= 0; return nextIndex >= 0;
} }
@ -469,6 +471,7 @@ public class ArrayBlockingQueueWithShutdown<E> extends AbstractQueue<E> implemen
} }
} }
@Override
public E next() { public E next() {
lock.lock(); lock.lock();
try { try {
@ -486,6 +489,7 @@ public class ArrayBlockingQueueWithShutdown<E> extends AbstractQueue<E> implemen
} }
} }
@Override
public void remove() { public void remove() {
lock.lock(); lock.lock();
try { try {

View file

@ -185,7 +185,7 @@ public class DNSUtil {
} }
List<SRVRecord> srvRecords = dnsResolver.lookupSRVRecords(srvDomain, failedAddresses, dnssecMode); List<SRVRecord> srvRecords = dnsResolver.lookupSRVRecords(srvDomain, failedAddresses, dnssecMode);
if (srvRecords != null) { if (srvRecords != null && !srvRecords.isEmpty()) {
if (LOGGER.isLoggable(Level.FINE)) { if (LOGGER.isLoggable(Level.FINE)) {
String logMessage = "Resolved SRV RR for " + srvDomain + ":"; String logMessage = "Resolved SRV RR for " + srvDomain + ":";
for (SRVRecord r : srvRecords) for (SRVRecord r : srvRecords)
@ -194,6 +194,8 @@ public class DNSUtil {
} }
List<HostAddress> sortedRecords = sortSRVRecords(srvRecords); List<HostAddress> sortedRecords = sortSRVRecords(srvRecords);
addresses.addAll(sortedRecords); addresses.addAll(sortedRecords);
} else {
LOGGER.info("Could not resolve DNS SRV resource records for " + srvDomain + ". Consider adding those.");
} }
int defaultPort = -1; int defaultPort = -1;

View file

@ -87,7 +87,8 @@ public final class FileUtils {
public static boolean addLines(String url, Set<String> set) throws MalformedURLException, IOException { public static boolean addLines(String url, Set<String> set) throws MalformedURLException, IOException {
InputStream is = getStreamForUrl(url, null); InputStream is = getStreamForUrl(url, null);
if (is == null) return false; if (is == null) return false;
BufferedReader br = new BufferedReader(new InputStreamReader(is)); InputStreamReader sr = new InputStreamReader(is, StringUtils.UTF8);
BufferedReader br = new BufferedReader(sr);
String line; String line;
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
set.add(line); set.add(line);
@ -102,6 +103,7 @@ public final class FileUtils {
* @return the content of file or null in case of an error * @return the content of file or null in case of an error
* @throws IOException * @throws IOException
*/ */
@SuppressWarnings("DefaultCharset")
public static String readFileOrThrow(File file) throws FileNotFoundException, IOException { public static String readFileOrThrow(File file) throws FileNotFoundException, IOException {
Reader reader = null; Reader reader = null;
try { try {
@ -132,6 +134,7 @@ public final class FileUtils {
return null; return null;
} }
@SuppressWarnings("DefaultCharset")
public static void writeFileOrThrow(File file, CharSequence content) throws IOException { public static void writeFileOrThrow(File file, CharSequence content) throws IOException {
FileWriter writer = new FileWriter(file, false); FileWriter writer = new FileWriter(file, false);
try { try {

View file

@ -37,6 +37,7 @@ public class ObservableReader extends Reader {
this.wrappedReader = wrappedReader; this.wrappedReader = wrappedReader;
} }
@Override
public int read(char[] cbuf, int off, int len) throws IOException { public int read(char[] cbuf, int off, int len) throws IOException {
int count = wrappedReader.read(cbuf, off, len); int count = wrappedReader.read(cbuf, off, len);
if (count > 0) { if (count > 0) {
@ -54,34 +55,42 @@ public class ObservableReader extends Reader {
return count; return count;
} }
@Override
public void close() throws IOException { public void close() throws IOException {
wrappedReader.close(); wrappedReader.close();
} }
@Override
public int read() throws IOException { public int read() throws IOException {
return wrappedReader.read(); return wrappedReader.read();
} }
@Override
public int read(char[] cbuf) throws IOException { public int read(char[] cbuf) throws IOException {
return wrappedReader.read(cbuf); return wrappedReader.read(cbuf);
} }
@Override
public long skip(long n) throws IOException { public long skip(long n) throws IOException {
return wrappedReader.skip(n); return wrappedReader.skip(n);
} }
@Override
public boolean ready() throws IOException { public boolean ready() throws IOException {
return wrappedReader.ready(); return wrappedReader.ready();
} }
@Override
public boolean markSupported() { public boolean markSupported() {
return wrappedReader.markSupported(); return wrappedReader.markSupported();
} }
@Override
public void mark(int readAheadLimit) throws IOException { public void mark(int readAheadLimit) throws IOException {
wrappedReader.mark(readAheadLimit); wrappedReader.mark(readAheadLimit);
} }
@Override
public void reset() throws IOException { public void reset() throws IOException {
wrappedReader.reset(); wrappedReader.reset();
} }

View file

@ -38,36 +38,43 @@ public class ObservableWriter extends Writer {
this.wrappedWriter = wrappedWriter; this.wrappedWriter = wrappedWriter;
} }
@Override
public void write(char[] cbuf, int off, int len) throws IOException { public void write(char[] cbuf, int off, int len) throws IOException {
wrappedWriter.write(cbuf, off, len); wrappedWriter.write(cbuf, off, len);
String str = new String(cbuf, off, len); String str = new String(cbuf, off, len);
maybeNotifyListeners(str); maybeNotifyListeners(str);
} }
@Override
public void flush() throws IOException { public void flush() throws IOException {
notifyListeners(); notifyListeners();
wrappedWriter.flush(); wrappedWriter.flush();
} }
@Override
public void close() throws IOException { public void close() throws IOException {
wrappedWriter.close(); wrappedWriter.close();
} }
@Override
public void write(int c) throws IOException { public void write(int c) throws IOException {
wrappedWriter.write(c); wrappedWriter.write(c);
} }
@Override
public void write(char[] cbuf) throws IOException { public void write(char[] cbuf) throws IOException {
wrappedWriter.write(cbuf); wrappedWriter.write(cbuf);
String str = new String(cbuf); String str = new String(cbuf);
maybeNotifyListeners(str); maybeNotifyListeners(str);
} }
@Override
public void write(String str) throws IOException { public void write(String str) throws IOException {
wrappedWriter.write(str); wrappedWriter.write(str);
maybeNotifyListeners(str); maybeNotifyListeners(str);
} }
@Override
public void write(String str, int off, int len) throws IOException { public void write(String str, int off, int len) throws IOException {
wrappedWriter.write(str, off, len); wrappedWriter.write(str, off, len);
str = str.substring(off, off + len); str = str.substring(off, off + len);

View file

@ -290,8 +290,6 @@ public class PacketParserUtils {
break outerloop; break outerloop;
} }
break; break;
case XmlPullParser.TEXT:
throw new IllegalStateException("Invalid Stanza: Must not contain text or mixed content as direct child of <message/>");
} }
} }
@ -592,8 +590,6 @@ public class PacketParserUtils {
break outerloop; break outerloop;
} }
break; break;
case XmlPullParser.TEXT:
throw new IllegalStateException("Invalid Stanza: Must not contain text or mixed content as direct child of <presence/>");
} }
} }
return presence; return presence;
@ -650,8 +646,6 @@ public class PacketParserUtils {
break outerloop; break outerloop;
} }
break; break;
case XmlPullParser.TEXT:
throw new IllegalStateException("Invalid Stanza: Must not contain text or mixed content as direct child of <iq/>");
} }
} }
// Decide what to do when an IQ packet was not understood // Decide what to do when an IQ packet was not understood

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2014 Florian Schmaus * Copyright © 2014-2017 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -26,6 +26,7 @@ import java.util.Locale;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid; import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.EntityJid;
import org.jxmpp.jid.Jid; import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Resourcepart; import org.jxmpp.jid.parts.Resourcepart;
@ -98,6 +99,24 @@ public class ParserUtils {
return JidCreate.entityFullFrom(jidString); return JidCreate.entityFullFrom(jidString);
} }
public static EntityJid getEntityJidAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
final String jidString = parser.getAttributeValue("", name);
if (jidString == null) {
return null;
}
Jid jid = JidCreate.from(jidString);
if (!jid.hasLocalpart()) return null;
EntityFullJid fullJid = jid.asEntityFullJidIfPossible();
if (fullJid != null) {
return fullJid;
}
EntityBareJid bareJid = jid.asEntityBareJidIfPossible();
return bareJid;
}
public static Resourcepart getResourcepartAttribute(XmlPullParser parser, String name) throws XmppStringprepException { public static Resourcepart getResourcepartAttribute(XmlPullParser parser, String name) throws XmppStringprepException {
final String resourcepartString = parser.getAttributeValue("", name); final String resourcepartString = parser.getAttributeValue("", name);
if (resourcepartString == null) { if (resourcepartString == null) {

View file

@ -20,6 +20,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.logging.Logger;
import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode; import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode;
@ -29,6 +30,8 @@ import org.jivesoftware.smack.ConnectionConfiguration.DnssecMode;
*/ */
public abstract class DNSResolver { public abstract class DNSResolver {
protected static final Logger LOGGER = Logger.getLogger(DNSResolver.class.getName());
private final boolean supportsDnssec; private final boolean supportsDnssec;
protected DNSResolver(boolean supportsDnssec) { protected DNSResolver(boolean supportsDnssec) {

View file

@ -20,6 +20,9 @@ package org.jivesoftware.smack.util.stringencoder;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.jivesoftware.smack.util.StringUtils;
/** /**
* Base32 string encoding is useful for when filenames case-insensitive filesystems are encoded. * Base32 string encoding is useful for when filenames case-insensitive filesystems are encoded.
@ -53,7 +56,13 @@ public class Base32 {
public static String decode(String str) { public static String decode(String str) {
ByteArrayOutputStream bs = new ByteArrayOutputStream(); ByteArrayOutputStream bs = new ByteArrayOutputStream();
byte[] raw = str.getBytes(); byte[] raw;
try {
raw = str.getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
for (int i = 0; i < raw.length; i++) { for (int i = 0; i < raw.length; i++) {
char c = (char) raw[i]; char c = (char) raw[i];
if (!Character.isWhitespace(c)) { if (!Character.isWhitespace(c)) {
@ -106,11 +115,24 @@ public class Base32 {
} }
} }
return new String(bs.toByteArray()); String res;
try {
res = new String(bs.toByteArray(), StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
return res;
} }
public static String encode(String str) { public static String encode(String str) {
byte[] b = str.getBytes(); byte[] b;
try {
b = str.getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
ByteArrayOutputStream os = new ByteArrayOutputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream();
for (int i = 0; i < (b.length + 4) / 5; i++) { for (int i = 0; i < (b.length + 4) / 5; i++) {
@ -153,7 +175,14 @@ public class Base32 {
os.write(c); os.write(c);
} }
} }
return new String(os.toByteArray()); String res;
try {
res = new String(os.toByteArray(), StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
return res;
} }
private static int lenToPadding(int blocklen) { private static int lenToPadding(int blocklen) {

View file

@ -180,6 +180,7 @@ public class DummyConnection extends AbstractXMPPConnection {
* *
* @param packet the stanza(/packet) to process. * @param packet the stanza(/packet) to process.
*/ */
@Override
public void processStanza(Stanza packet) { public void processStanza(Stanza packet) {
invokeStanzaCollectorsAndNotifyRecvListeners(packet); invokeStanzaCollectorsAndNotifyRecvListeners(packet);
} }

View file

@ -26,190 +26,190 @@ import org.junit.Test;
public class StanzaCollectorTest public class StanzaCollectorTest
{ {
@Test @Test
public void verifyRollover() throws InterruptedException public void verifyRollover() throws InterruptedException
{ {
TestStanzaCollector collector = new TestStanzaCollector(null, new OKEverything(), 5); TestStanzaCollector collector = new TestStanzaCollector(null, new OKEverything(), 5);
for (int i=0; i<6; i++) for (int i=0; i<6; i++)
{ {
Stanza testPacket = new TestPacket(i); Stanza testPacket = new TestPacket(i);
collector.processStanza(testPacket); collector.processStanza(testPacket);
} }
// Assert that '0' has rolled off // Assert that '0' has rolled off
assertEquals("1", collector.nextResultBlockForever().getStanzaId()); assertEquals("1", collector.nextResultBlockForever().getStanzaId());
assertEquals("2", collector.nextResultBlockForever().getStanzaId()); assertEquals("2", collector.nextResultBlockForever().getStanzaId());
assertEquals("3", collector.nextResultBlockForever().getStanzaId()); assertEquals("3", collector.nextResultBlockForever().getStanzaId());
assertEquals("4", collector.nextResultBlockForever().getStanzaId()); assertEquals("4", collector.nextResultBlockForever().getStanzaId());
assertEquals("5", collector.pollResult().getStanzaId()); assertEquals("5", collector.pollResult().getStanzaId());
assertNull(collector.pollResult()); assertNull(collector.pollResult());
for (int i=10; i<15; i++) for (int i=10; i<15; i++)
{ {
Stanza testPacket = new TestPacket(i); Stanza testPacket = new TestPacket(i);
collector.processStanza(testPacket); collector.processStanza(testPacket);
} }
assertEquals("10", collector.nextResultBlockForever().getStanzaId()); assertEquals("10", collector.nextResultBlockForever().getStanzaId());
assertEquals("11", collector.nextResultBlockForever().getStanzaId()); assertEquals("11", collector.nextResultBlockForever().getStanzaId());
assertEquals("12", collector.nextResultBlockForever().getStanzaId()); assertEquals("12", collector.nextResultBlockForever().getStanzaId());
assertEquals("13", collector.nextResultBlockForever().getStanzaId()); assertEquals("13", collector.nextResultBlockForever().getStanzaId());
assertEquals("14", collector.pollResult().getStanzaId()); assertEquals("14", collector.pollResult().getStanzaId());
assertNull(collector.pollResult()); assertNull(collector.pollResult());
assertNull(collector.nextResult(1000)); assertNull(collector.nextResult(1000));
} }
/** /**
* Although this doesn't guarentee anything due to the nature of threading, it can potentially * Although this doesn't guarentee anything due to the nature of threading, it can potentially
* catch problems. * catch problems.
*/ */
@Test @Test
public void verifyThreadSafety() public void verifyThreadSafety()
{ {
int insertCount = 500; int insertCount = 500;
final TestStanzaCollector collector = new TestStanzaCollector(null, new OKEverything(), insertCount); final TestStanzaCollector collector = new TestStanzaCollector(null, new OKEverything(), insertCount);
Thread consumer1 = new Thread(new Runnable() Thread consumer1 = new Thread(new Runnable()
{ {
@Override @Override
public void run() public void run()
{ {
try try
{ {
while (true) while (true)
{ {
try try
{ {
Thread.sleep(3); Thread.sleep(3);
} }
catch (InterruptedException e) catch (InterruptedException e)
{ {
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
Stanza packet = collector.nextResultBlockForever(); Stanza packet = collector.nextResultBlockForever();
// System.out.println(Thread.currentThread().getName() + " packet: " + packet); // System.out.println(Thread.currentThread().getName() + " packet: " + packet);
} }
} }
catch (InterruptedException e) { catch (InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
}); });
consumer1.setName("consumer 1"); consumer1.setName("consumer 1");
Thread consumer2 = new Thread(new Runnable() Thread consumer2 = new Thread(new Runnable()
{ {
@Override @Override
public void run() public void run()
{ {
Stanza p = null; Stanza p = null;
do do
{ {
try try
{ {
Thread.sleep(3); Thread.sleep(3);
} }
catch (InterruptedException e) catch (InterruptedException e)
{ {
} }
try { try {
p = collector.nextResult(1); p = collector.nextResult(1);
} }
catch (InterruptedException e) { catch (InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
// System.out.println(Thread.currentThread().getName() + " packet: " + p); // System.out.println(Thread.currentThread().getName() + " packet: " + p);
} }
while (p != null); while (p != null);
} }
}); });
consumer2.setName("consumer 2"); consumer2.setName("consumer 2");
Thread consumer3 = new Thread(new Runnable() Thread consumer3 = new Thread(new Runnable()
{ {
@Override @Override
public void run() public void run()
{ {
Stanza p = null; Stanza p = null;
do do
{ {
try try
{ {
Thread.sleep(3); Thread.sleep(3);
} }
catch (InterruptedException e) catch (InterruptedException e)
{ {
} }
p = collector.pollResult(); p = collector.pollResult();
// System.out.println(Thread.currentThread().getName() + " packet: " + p); // System.out.println(Thread.currentThread().getName() + " packet: " + p);
} }
while (p != null); while (p != null);
} }
}); });
consumer3.setName("consumer 3"); consumer3.setName("consumer 3");
consumer1.start(); consumer1.start();
consumer2.start(); consumer2.start();
consumer3.start(); consumer3.start();
for(int i=0; i<insertCount; i++) for(int i=0; i<insertCount; i++)
{ {
collector.processStanza(new TestPacket(i)); collector.processStanza(new TestPacket(i));
} }
try try
{ {
Thread.sleep(5000); Thread.sleep(5000);
consumer3.join(); consumer3.join();
consumer2.join(); consumer2.join();
consumer1.interrupt(); consumer1.interrupt();
} }
catch (InterruptedException e) catch (InterruptedException e)
{ {
} }
//We cannot guarantee that this is going to pass due to the possible issue of timing between consumer 1 //We cannot guarantee that this is going to pass due to the possible issue of timing between consumer 1
// and main, but the probability is extremely remote. // and main, but the probability is extremely remote.
assertNull(collector.pollResult()); assertNull(collector.pollResult());
} }
class OKEverything implements StanzaFilter static class OKEverything implements StanzaFilter
{ {
@Override @Override
public boolean accept(Stanza packet) public boolean accept(Stanza packet)
{ {
return true; return true;
} }
} }
class TestStanzaCollector extends StanzaCollector static class TestStanzaCollector extends StanzaCollector
{ {
protected TestStanzaCollector(XMPPConnection conection, StanzaFilter packetFilter, int size) protected TestStanzaCollector(XMPPConnection conection, StanzaFilter packetFilter, int size)
{ {
super(conection, StanzaCollector.newConfiguration().setStanzaFilter(packetFilter).setSize(size)); super(conection, StanzaCollector.newConfiguration().setStanzaFilter(packetFilter).setSize(size));
} }
} }
class TestPacket extends Stanza static class TestPacket extends Stanza
{ {
public TestPacket(int i) public TestPacket(int i)
{ {
setStanzaId(String.valueOf(i)); setStanzaId(String.valueOf(i));
} }
@Override @Override
public String toXML() public String toXML()
{ {
return "<packetId>" + getStanzaId() + "</packetId>"; return "<packetId>" + getStanzaId() + "</packetId>";
} }
@Override @Override
public String toString() { public String toString() {
return toXML(); return toXML();
} }
} }
} }

View file

@ -19,6 +19,7 @@ package org.jivesoftware.smack.sasl;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -38,14 +39,14 @@ public class DigestMd5SaslTest extends AbstractSaslTest {
super(saslMechanism); super(saslMechanism);
} }
protected void runTest(boolean useAuthzid) throws NotConnectedException, SmackException, InterruptedException, XmppStringprepException { protected void runTest(boolean useAuthzid) throws NotConnectedException, SmackException, InterruptedException, XmppStringprepException, UnsupportedEncodingException {
EntityBareJid authzid = null; EntityBareJid authzid = null;
if (useAuthzid) { if (useAuthzid) {
authzid = JidCreate.entityBareFrom("shazbat@xmpp.org"); authzid = JidCreate.entityBareFrom("shazbat@xmpp.org");
} }
saslMechanism.authenticate("florian", "irrelevant", JidCreate.domainBareFrom("xmpp.org"), "secret", authzid, null); saslMechanism.authenticate("florian", "irrelevant", JidCreate.domainBareFrom("xmpp.org"), "secret", authzid, null);
byte[] response = saslMechanism.evaluateChallenge(challengeBytes); byte[] response = saslMechanism.evaluateChallenge(challengeBytes);
String responseString = new String(response); String responseString = new String(response, StringUtils.UTF8);
String[] responseParts = responseString.split(","); String[] responseParts = responseString.split(",");
Map<String, String> responsePairs = new HashMap<String, String>(); Map<String, String> responsePairs = new HashMap<String, String>();
for (String part : responseParts) { for (String part : responseParts) {

View file

@ -710,8 +710,8 @@ public class PacketParserUtilsTest {
try { try {
PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl)); PacketParserUtils.parseMessage(PacketParserUtils.getParserFor(invalidControl));
fail("Exception should be thrown"); fail("Exception should be thrown");
} catch(IllegalStateException e) { } catch(XmlPullParserException e) {
assertTrue(e.getMessage().contains("Invalid Stanza")); assertTrue(e.getMessage().contains("end tag name </body>"));
} }
invalidControl = validControl.replace("Good Message Body", "Bad </message> Body"); invalidControl = validControl.replace("Good Message Body", "Bad </message> Body");
@ -851,6 +851,7 @@ public class PacketParserUtilsTest {
XmlUnitUtils.assertSimilar(saslFailureString, saslFailure.toXML()); XmlUnitUtils.assertSimilar(saslFailureString, saslFailure.toXML());
} }
@SuppressWarnings("ReferenceEquality")
private static String determineNonDefaultLanguage() { private static String determineNonDefaultLanguage() {
String otherLanguage = "jp"; String otherLanguage = "jp";
Locale[] availableLocales = Locale.getAvailableLocales(); Locale[] availableLocales = Locale.getAvailableLocales();

View file

@ -28,7 +28,7 @@ import org.junit.Test;
*/ */
public class SHA1Test { public class SHA1Test {
@Test @Test
public void testHash() { public void testHash() {
// Test null // Test null
// @TODO - should the StringUtils.hash(String) method be fixed to handle null input? // @TODO - should the StringUtils.hash(String) method be fixed to handle null input?

View file

@ -21,13 +21,15 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
import org.junit.Test; import org.junit.Test;
/** /**
* A test case for the StringUtils class. * A test case for the StringUtils class.
*/ */
public class StringUtilsTest { public class StringUtilsTest {
@Test @Test
public void testEscapeForXml() { public void testEscapeForXml() {
String input = null; String input = null;
@ -67,24 +69,24 @@ public class StringUtilsTest {
assertCharSequenceEquals("It&apos;s a good day today", StringUtils.escapeForXml(input)); assertCharSequenceEquals("It&apos;s a good day today", StringUtils.escapeForXml(input));
} }
public static void assertCharSequenceEquals(CharSequence expected, CharSequence actual) { public static void assertCharSequenceEquals(CharSequence expected, CharSequence actual) {
assertEquals(expected.toString(), actual.toString()); assertEquals(expected.toString(), actual.toString());
} }
@Test @Test
public void testEncodeHex() { public void testEncodeHex() throws UnsupportedEncodingException {
String input = ""; String input = "";
String output = ""; String output = "";
assertEquals(new String(StringUtils.encodeHex(input.getBytes())), assertEquals(new String(StringUtils.encodeHex(input.getBytes(StringUtils.UTF8))),
new String(output.getBytes())); output);
input = "foo bar 123"; input = "foo bar 123";
output = "666f6f2062617220313233"; output = "666f6f2062617220313233";
assertEquals(new String(StringUtils.encodeHex(input.getBytes())), assertEquals(new String(StringUtils.encodeHex(input.getBytes(StringUtils.UTF8))),
new String(output.getBytes())); output);
} }
@Test @Test
public void testRandomString() { public void testRandomString() {
// Boundary test // Boundary test
String result = StringUtils.randomString(-1); String result = StringUtils.randomString(-1);

View file

@ -40,22 +40,27 @@ class SLF4JLoggingConnectionListener implements ConnectionListener {
logger.debug("({}) Connection authenticated as {}", connection.hashCode(), connection.getUser()); logger.debug("({}) Connection authenticated as {}", connection.hashCode(), connection.getUser());
} }
@Override
public void connectionClosed() { public void connectionClosed() {
logger.debug("({}) Connection closed", connection.hashCode()); logger.debug("({}) Connection closed", connection.hashCode());
} }
@Override
public void connectionClosedOnError(Exception e) { public void connectionClosedOnError(Exception e) {
logger.debug("({}) Connection closed due to an exception: {}", connection.hashCode(), e); logger.debug("({}) Connection closed due to an exception: {}", connection.hashCode(), e);
} }
@Override
public void reconnectionFailed(Exception e) { public void reconnectionFailed(Exception e) {
logger.debug("({}) Reconnection failed due to an exception: {}", connection.hashCode(), e); logger.debug("({}) Reconnection failed due to an exception: {}", connection.hashCode(), e);
} }
@Override
public void reconnectionSuccessful() { public void reconnectionSuccessful() {
logger.debug("({}) Connection reconnected", connection.hashCode()); logger.debug("({}) Connection reconnected", connection.hashCode());
} }
@Override
public void reconnectingIn(int seconds) { public void reconnectingIn(int seconds) {
logger.debug("({}) Connection will reconnect in {}", connection.hashCode(), seconds); logger.debug("({}) Connection will reconnect in {}", connection.hashCode(), seconds);
} }

View file

@ -31,6 +31,7 @@ class SLF4JLoggingPacketListener implements StanzaListener {
this.prefix = Validate.notNull(prefix); this.prefix = Validate.notNull(prefix);
} }
@Override
public void processStanza(Stanza packet) { public void processStanza(Stanza packet) {
if (SLF4JSmackDebugger.printInterpreted.get() && logger.isDebugEnabled()) { if (SLF4JSmackDebugger.printInterpreted.get() && logger.isDebugEnabled()) {
logger.debug("{}: PKT [{}] '{}'", prefix, packet.getClass().getName(), packet.toXML()); logger.debug("{}: PKT [{}] '{}'", prefix, packet.getClass().getName(), packet.toXML());

View file

@ -28,10 +28,12 @@ class SLF4JRawXmlListener implements ReaderListener, WriterListener {
this.logger = Validate.notNull(logger); this.logger = Validate.notNull(logger);
} }
@Override
public void read(String str) { public void read(String str) {
logger.debug("{}: {}", SLF4JSmackDebugger.RECEIVED_TAG, str); logger.debug("{}: {}", SLF4JSmackDebugger.RECEIVED_TAG, str);
} }
@Override
public void write(String str) { public void write(String str) {
logger.debug("{}: {}", SLF4JSmackDebugger.SENT_TAG, str); logger.debug("{}: {}", SLF4JSmackDebugger.SENT_TAG, str);
} }

View file

@ -208,8 +208,10 @@ public class EnhancedDebugger implements SmackDebugger {
packetReaderListener = new StanzaListener() { packetReaderListener = new StanzaListener() {
SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss:SS"); SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss:SS");
@Override
public void processStanza(final Stanza packet) { public void processStanza(final Stanza packet) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
addReadPacketToTable(dateFormatter, packet); addReadPacketToTable(dateFormatter, packet);
} }
@ -223,8 +225,10 @@ public class EnhancedDebugger implements SmackDebugger {
packetWriterListener = new StanzaListener() { packetWriterListener = new StanzaListener() {
SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss:SS"); SimpleDateFormat dateFormatter = new SimpleDateFormat("HH:mm:ss:SS");
@Override
public void processStanza(final Stanza packet) { public void processStanza(final Stanza packet) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
addSentPacketToTable(dateFormatter, packet); addSentPacketToTable(dateFormatter, packet);
} }
@ -235,8 +239,10 @@ public class EnhancedDebugger implements SmackDebugger {
// Create a thread that will listen for any connection closed event // Create a thread that will listen for any connection closed event
connListener = new AbstractConnectionListener() { connListener = new AbstractConnectionListener() {
@Override
public void connectionClosed() { public void connectionClosed() {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
statusField.setValue("Closed"); statusField.setValue("Closed");
EnhancedDebuggerWindow.connectionClosed(EnhancedDebugger.this); EnhancedDebuggerWindow.connectionClosed(EnhancedDebugger.this);
@ -245,8 +251,10 @@ public class EnhancedDebugger implements SmackDebugger {
} }
@Override
public void connectionClosedOnError(final Exception e) { public void connectionClosedOnError(final Exception e) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
statusField.setValue("Closed due to an exception"); statusField.setValue("Closed due to an exception");
EnhancedDebuggerWindow.connectionClosedOnError(EnhancedDebugger.this, e); EnhancedDebuggerWindow.connectionClosedOnError(EnhancedDebugger.this, e);
@ -254,16 +262,20 @@ public class EnhancedDebugger implements SmackDebugger {
}); });
} }
@Override
public void reconnectingIn(final int seconds){ public void reconnectingIn(final int seconds){
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
statusField.setValue("Attempt to reconnect in " + seconds + " seconds"); statusField.setValue("Attempt to reconnect in " + seconds + " seconds");
} }
}); });
} }
@Override
public void reconnectionSuccessful() { public void reconnectionSuccessful() {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
statusField.setValue("Reconnection stablished"); statusField.setValue("Reconnection stablished");
EnhancedDebuggerWindow.connectionEstablished(EnhancedDebugger.this); EnhancedDebuggerWindow.connectionEstablished(EnhancedDebugger.this);
@ -271,8 +283,10 @@ public class EnhancedDebugger implements SmackDebugger {
}); });
} }
@Override
public void reconnectionFailed(Exception e) { public void reconnectionFailed(Exception e) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
statusField.setValue("Reconnection failed"); statusField.setValue("Reconnection failed");
} }
@ -291,11 +305,13 @@ public class EnhancedDebugger implements SmackDebugger {
0) { 0) {
// CHECKSTYLE:OFF // CHECKSTYLE:OFF
private static final long serialVersionUID = 8136121224474217264L; private static final long serialVersionUID = 8136121224474217264L;
public boolean isCellEditable(int rowIndex, int mColIndex) { @Override
public boolean isCellEditable(int rowIndex, int mColIndex) {
// CHECKSTYLE:ON // CHECKSTYLE:ON
return false; return false;
} }
@Override
public Class<?> getColumnClass(int columnIndex) { public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 2 || columnIndex == 3) { if (columnIndex == 2 || columnIndex == 3) {
return Icon.class; return Icon.class;
@ -344,6 +360,7 @@ public class EnhancedDebugger implements SmackDebugger {
JPopupMenu menu = new JPopupMenu(); JPopupMenu menu = new JPopupMenu();
JMenuItem menuItem1 = new JMenuItem("Copy"); JMenuItem menuItem1 = new JMenuItem("Copy");
menuItem1.addActionListener(new ActionListener() { menuItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// Get the clipboard // Get the clipboard
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
@ -391,6 +408,7 @@ public class EnhancedDebugger implements SmackDebugger {
menu = new JPopupMenu(); menu = new JPopupMenu();
menuItem1 = new JMenuItem("Copy"); menuItem1 = new JMenuItem("Copy");
menuItem1.addActionListener(new ActionListener() { menuItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// Get the clipboard // Get the clipboard
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
@ -401,6 +419,7 @@ public class EnhancedDebugger implements SmackDebugger {
JMenuItem menuItem2 = new JMenuItem("Clear"); JMenuItem menuItem2 = new JMenuItem("Clear");
menuItem2.addActionListener(new ActionListener() { menuItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
sentText.setText(""); sentText.setText("");
} }
@ -426,6 +445,7 @@ public class EnhancedDebugger implements SmackDebugger {
menu = new JPopupMenu(); menu = new JPopupMenu();
menuItem1 = new JMenuItem("Copy"); menuItem1 = new JMenuItem("Copy");
menuItem1.addActionListener(new ActionListener() { menuItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// Get the clipboard // Get the clipboard
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
@ -436,6 +456,7 @@ public class EnhancedDebugger implements SmackDebugger {
menuItem2 = new JMenuItem("Clear"); menuItem2 = new JMenuItem("Clear");
menuItem2.addActionListener(new ActionListener() { menuItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
receivedText.setText(""); receivedText.setText("");
} }
@ -449,8 +470,10 @@ public class EnhancedDebugger implements SmackDebugger {
// Create a special Reader that wraps the main Reader and logs data to the GUI. // Create a special Reader that wraps the main Reader and logs data to the GUI.
ObservableReader debugReader = new ObservableReader(reader); ObservableReader debugReader = new ObservableReader(reader);
readerListener = new ReaderListener() { readerListener = new ReaderListener() {
@Override
public void read(final String str) { public void read(final String str) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
if (EnhancedDebuggerWindow.PERSISTED_DEBUGGER && if (EnhancedDebuggerWindow.PERSISTED_DEBUGGER &&
!EnhancedDebuggerWindow.getInstance().isVisible()) { !EnhancedDebuggerWindow.getInstance().isVisible()) {
@ -487,8 +510,10 @@ public class EnhancedDebugger implements SmackDebugger {
// Create a special Writer that wraps the main Writer and logs data to the GUI. // Create a special Writer that wraps the main Writer and logs data to the GUI.
ObservableWriter debugWriter = new ObservableWriter(writer); ObservableWriter debugWriter = new ObservableWriter(writer);
writerListener = new WriterListener() { writerListener = new WriterListener() {
@Override
public void write(final String str) { public void write(final String str) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
if (EnhancedDebuggerWindow.PERSISTED_DEBUGGER && if (EnhancedDebuggerWindow.PERSISTED_DEBUGGER &&
!EnhancedDebuggerWindow.getInstance().isVisible()) { !EnhancedDebuggerWindow.getInstance().isVisible()) {
@ -536,6 +561,7 @@ public class EnhancedDebugger implements SmackDebugger {
JPopupMenu menu = new JPopupMenu(); JPopupMenu menu = new JPopupMenu();
JMenuItem menuItem = new JMenuItem("Message"); JMenuItem menuItem = new JMenuItem("Message");
menuItem.addActionListener(new ActionListener() { menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
adhocMessages.setText( adhocMessages.setText(
"<message to=\"\" id=\"" "<message to=\"\" id=\""
@ -547,6 +573,7 @@ public class EnhancedDebugger implements SmackDebugger {
menuItem = new JMenuItem("IQ Get"); menuItem = new JMenuItem("IQ Get");
menuItem.addActionListener(new ActionListener() { menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
adhocMessages.setText( adhocMessages.setText(
"<iq type=\"get\" to=\"\" id=\"" "<iq type=\"get\" to=\"\" id=\""
@ -558,6 +585,7 @@ public class EnhancedDebugger implements SmackDebugger {
menuItem = new JMenuItem("IQ Set"); menuItem = new JMenuItem("IQ Set");
menuItem.addActionListener(new ActionListener() { menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
adhocMessages.setText( adhocMessages.setText(
"<iq type=\"set\" to=\"\" id=\"" "<iq type=\"set\" to=\"\" id=\""
@ -569,6 +597,7 @@ public class EnhancedDebugger implements SmackDebugger {
menuItem = new JMenuItem("Presence"); menuItem = new JMenuItem("Presence");
menuItem.addActionListener(new ActionListener() { menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
adhocMessages.setText( adhocMessages.setText(
"<presence to=\"\" id=\"" + StringUtils.randomString(5) + "-X\"/>"); "<presence to=\"\" id=\"" + StringUtils.randomString(5) + "-X\"/>");
@ -579,6 +608,7 @@ public class EnhancedDebugger implements SmackDebugger {
menuItem = new JMenuItem("Send"); menuItem = new JMenuItem("Send");
menuItem.addActionListener(new ActionListener() { menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (!"".equals(adhocMessages.getText())) { if (!"".equals(adhocMessages.getText())) {
AdHocPacket packetToSend = new AdHocPacket(adhocMessages.getText()); AdHocPacket packetToSend = new AdHocPacket(adhocMessages.getText());
@ -595,6 +625,7 @@ public class EnhancedDebugger implements SmackDebugger {
menuItem = new JMenuItem("Clear"); menuItem = new JMenuItem("Clear");
menuItem.addActionListener(new ActionListener() { menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
adhocMessages.setText(null); adhocMessages.setText(null);
} }
@ -709,7 +740,8 @@ public class EnhancedDebugger implements SmackDebugger {
new Object[]{"Type", "Received", "Sent"}) { new Object[]{"Type", "Received", "Sent"}) {
// CHECKSTYLE:OFF // CHECKSTYLE:OFF
private static final long serialVersionUID = -6793886085109589269L; private static final long serialVersionUID = -6793886085109589269L;
public boolean isCellEditable(int rowIndex, int mColIndex) { @Override
public boolean isCellEditable(int rowIndex, int mColIndex) {
// CHECKSTYLE:ON // CHECKSTYLE:ON
return false; return false;
} }
@ -726,6 +758,7 @@ public class EnhancedDebugger implements SmackDebugger {
tabbedPane.setToolTipTextAt(4, "Information and statistics about the debugged connection"); tabbedPane.setToolTipTextAt(4, "Information and statistics about the debugged connection");
} }
@Override
public Reader newConnectionReader(Reader newReader) { public Reader newConnectionReader(Reader newReader) {
((ObservableReader) reader).removeReaderListener(readerListener); ((ObservableReader) reader).removeReaderListener(readerListener);
ObservableReader debugReader = new ObservableReader(newReader); ObservableReader debugReader = new ObservableReader(newReader);
@ -734,6 +767,7 @@ public class EnhancedDebugger implements SmackDebugger {
return reader; return reader;
} }
@Override
public Writer newConnectionWriter(Writer newWriter) { public Writer newConnectionWriter(Writer newWriter) {
((ObservableWriter) writer).removeWriterListener(writerListener); ((ObservableWriter) writer).removeWriterListener(writerListener);
ObservableWriter debugWriter = new ObservableWriter(newWriter); ObservableWriter debugWriter = new ObservableWriter(newWriter);
@ -746,6 +780,7 @@ public class EnhancedDebugger implements SmackDebugger {
public void userHasLogged(final EntityFullJid user) { public void userHasLogged(final EntityFullJid user) {
final EnhancedDebugger debugger = this; final EnhancedDebugger debugger = this;
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
userField.setText(user.toString()); userField.setText(user.toString());
EnhancedDebuggerWindow.userHasLogged(debugger, user.toString()); EnhancedDebuggerWindow.userHasLogged(debugger, user.toString());
@ -757,18 +792,22 @@ public class EnhancedDebugger implements SmackDebugger {
} }
@Override
public Reader getReader() { public Reader getReader() {
return reader; return reader;
} }
@Override
public Writer getWriter() { public Writer getWriter() {
return writer; return writer;
} }
@Override
public StanzaListener getReaderListener() { public StanzaListener getReaderListener() {
return packetReaderListener; return packetReaderListener;
} }
@Override
public StanzaListener getWriterListener() { public StanzaListener getWriterListener() {
return packetWriterListener; return packetWriterListener;
} }
@ -801,6 +840,7 @@ public class EnhancedDebugger implements SmackDebugger {
*/ */
private void addReadPacketToTable(final SimpleDateFormat dateFormatter, final Stanza packet) { private void addReadPacketToTable(final SimpleDateFormat dateFormatter, final Stanza packet) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
String messageType; String messageType;
Jid from = packet.getFrom(); Jid from = packet.getFrom();
@ -862,6 +902,7 @@ public class EnhancedDebugger implements SmackDebugger {
*/ */
private void addSentPacketToTable(final SimpleDateFormat dateFormatter, final Stanza packet) { private void addSentPacketToTable(final SimpleDateFormat dateFormatter, final Stanza packet) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() { public void run() {
String messageType; String messageType;
Jid to = packet.getTo(); Jid to = packet.getTo();
@ -978,9 +1019,9 @@ public class EnhancedDebugger implements SmackDebugger {
* The whole text to send must be passed to the constructor. This implies that the client of * The whole text to send must be passed to the constructor. This implies that the client of
* this class is responsible for sending a valid text to the constructor. * this class is responsible for sending a valid text to the constructor.
*/ */
private class AdHocPacket extends Stanza { private static class AdHocPacket extends Stanza {
private String text; private final String text;
/** /**
* Create a new AdHocPacket with the text to send. The passed text must be a valid text to * Create a new AdHocPacket with the text to send. The passed text must be a valid text to
@ -992,6 +1033,7 @@ public class EnhancedDebugger implements SmackDebugger {
this.text = text; this.text = text;
} }
@Override
public String toXML() { public String toXML() {
return text; return text;
} }
@ -1006,7 +1048,7 @@ public class EnhancedDebugger implements SmackDebugger {
/** /**
* Listens for debug window popup dialog events. * Listens for debug window popup dialog events.
*/ */
private class PopupListener extends MouseAdapter { private static class PopupListener extends MouseAdapter {
JPopupMenu popup; JPopupMenu popup;
@ -1014,10 +1056,12 @@ public class EnhancedDebugger implements SmackDebugger {
popup = popupMenu; popup = popupMenu;
} }
@Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
maybeShowPopup(e); maybeShowPopup(e);
} }
@Override
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
maybeShowPopup(e); maybeShowPopup(e);
} }
@ -1039,6 +1083,7 @@ public class EnhancedDebugger implements SmackDebugger {
this.table = table; this.table = table;
} }
@Override
public void valueChanged(ListSelectionEvent e) { public void valueChanged(ListSelectionEvent e) {
if (table.getSelectedRow() == -1) { if (table.getSelectedRow() == -1) {
// Clear the messageTextArea since there is none packet selected // Clear the messageTextArea since there is none packet selected

View file

@ -203,13 +203,14 @@ public final class EnhancedDebuggerWindow {
* a tab panel for each connection that is being debugged. * a tab panel for each connection that is being debugged.
*/ */
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
private void createDebug() { private void createDebug() {
frame = new JFrame("Smack Debug Window"); frame = new JFrame("Smack Debug Window");
if (!PERSISTED_DEBUGGER) { if (!PERSISTED_DEBUGGER) {
// Add listener for window closing event // Add listener for window closing event
frame.addWindowListener(new WindowAdapter() { frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent evt) { public void windowClosing(WindowEvent evt) {
rootWindowClosing(evt); rootWindowClosing(evt);
} }
@ -280,6 +281,7 @@ public final class EnhancedDebuggerWindow {
// Add a menu item that allows to close the current selected tab // Add a menu item that allows to close the current selected tab
JMenuItem menuItem = new JMenuItem("Close"); JMenuItem menuItem = new JMenuItem("Close");
menuItem.addActionListener(new ActionListener() { menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// Remove the selected tab pane if it's not the Smack info pane // Remove the selected tab pane if it's not the Smack info pane
if (tabbedPane.getSelectedIndex() < tabbedPane.getComponentCount() - 1) { if (tabbedPane.getSelectedIndex() < tabbedPane.getComponentCount() - 1) {
@ -301,6 +303,7 @@ public final class EnhancedDebuggerWindow {
// Add a menu item that allows to close all the tabs that have their connections closed // Add a menu item that allows to close all the tabs that have their connections closed
menuItem = new JMenuItem("Close All Not Active"); menuItem = new JMenuItem("Close All Not Active");
menuItem.addActionListener(new ActionListener() { menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
ArrayList<EnhancedDebugger> debuggersToRemove = new ArrayList<EnhancedDebugger>(); 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
@ -348,7 +351,7 @@ public final class EnhancedDebuggerWindow {
debugger.cancel(); debugger.cancel();
} }
// Release any reference to the debuggers // Release any reference to the debuggers
debuggers.removeAll(debuggers); debuggers.clear();
// Release the default instance // Release the default instance
instance = null; instance = null;
} }
@ -356,7 +359,7 @@ public final class EnhancedDebuggerWindow {
/** /**
* Listens for debug window popup dialog events. * Listens for debug window popup dialog events.
*/ */
private class PopupListener extends MouseAdapter { private static class PopupListener extends MouseAdapter {
JPopupMenu popup; JPopupMenu popup;
@ -364,10 +367,12 @@ public final class EnhancedDebuggerWindow {
popup = popupMenu; popup = popupMenu;
} }
@Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
maybeShowPopup(e); maybeShowPopup(e);
} }
@Override
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
maybeShowPopup(e); maybeShowPopup(e);
} }

View file

@ -86,6 +86,7 @@ public class LiteDebugger implements SmackDebugger {
// Add listener for window closing event // Add listener for window closing event
frame.addWindowListener(new WindowAdapter() { frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent evt) { public void windowClosing(WindowEvent evt) {
rootWindowClosing(evt); rootWindowClosing(evt);
} }
@ -114,6 +115,7 @@ public class LiteDebugger implements SmackDebugger {
JPopupMenu menu = new JPopupMenu(); JPopupMenu menu = new JPopupMenu();
JMenuItem menuItem1 = new JMenuItem("Copy"); JMenuItem menuItem1 = new JMenuItem("Copy");
menuItem1.addActionListener(new ActionListener() { menuItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// Get the clipboard // Get the clipboard
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
@ -124,6 +126,7 @@ public class LiteDebugger implements SmackDebugger {
JMenuItem menuItem2 = new JMenuItem("Clear"); JMenuItem menuItem2 = new JMenuItem("Clear");
menuItem2.addActionListener(new ActionListener() { menuItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
sentText1.setText(""); sentText1.setText("");
sentText2.setText(""); sentText2.setText("");
@ -151,6 +154,7 @@ public class LiteDebugger implements SmackDebugger {
menu = new JPopupMenu(); menu = new JPopupMenu();
menuItem1 = new JMenuItem("Copy"); menuItem1 = new JMenuItem("Copy");
menuItem1.addActionListener(new ActionListener() { menuItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// Get the clipboard // Get the clipboard
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
@ -161,6 +165,7 @@ public class LiteDebugger implements SmackDebugger {
menuItem2 = new JMenuItem("Clear"); menuItem2 = new JMenuItem("Clear");
menuItem2.addActionListener(new ActionListener() { menuItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
receivedText1.setText(""); receivedText1.setText("");
receivedText2.setText(""); receivedText2.setText("");
@ -188,6 +193,7 @@ public class LiteDebugger implements SmackDebugger {
menu = new JPopupMenu(); menu = new JPopupMenu();
menuItem1 = new JMenuItem("Copy"); menuItem1 = new JMenuItem("Copy");
menuItem1.addActionListener(new ActionListener() { menuItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// Get the clipboard // Get the clipboard
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
@ -198,6 +204,7 @@ public class LiteDebugger implements SmackDebugger {
menuItem2 = new JMenuItem("Clear"); menuItem2 = new JMenuItem("Clear");
menuItem2.addActionListener(new ActionListener() { menuItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
interpretedText1.setText(""); interpretedText1.setText("");
interpretedText2.setText(""); interpretedText2.setText("");
@ -219,6 +226,7 @@ public class LiteDebugger implements SmackDebugger {
// Create a special Reader that wraps the main Reader and logs data to the GUI. // Create a special Reader that wraps the main Reader and logs data to the GUI.
ObservableReader debugReader = new ObservableReader(reader); ObservableReader debugReader = new ObservableReader(reader);
readerListener = new ReaderListener() { readerListener = new ReaderListener() {
@Override
public void read(String str) { public void read(String str) {
int index = str.lastIndexOf(">"); int index = str.lastIndexOf(">");
if (index != -1) { if (index != -1) {
@ -242,6 +250,7 @@ public class LiteDebugger implements SmackDebugger {
// Create a special Writer that wraps the main Writer and logs data to the GUI. // Create a special Writer that wraps the main Writer and logs data to the GUI.
ObservableWriter debugWriter = new ObservableWriter(writer); ObservableWriter debugWriter = new ObservableWriter(writer);
writerListener = new WriterListener() { writerListener = new WriterListener() {
@Override
public void write(String str) { public void write(String str) {
sentText1.append(str); sentText1.append(str);
sentText2.append(str); sentText2.append(str);
@ -262,6 +271,7 @@ public class LiteDebugger implements SmackDebugger {
// the GUI. This is what we call "interpreted" packet data, since it's the packet // the GUI. This is what we call "interpreted" packet data, since it's the packet
// data as Smack sees it and not as it's coming in as raw XML. // data as Smack sees it and not as it's coming in as raw XML.
listener = new StanzaListener() { listener = new StanzaListener() {
@Override
public void processStanza(Stanza packet) { public void processStanza(Stanza packet) {
interpretedText1.append(packet.toXML().toString()); interpretedText1.append(packet.toXML().toString());
interpretedText2.append(packet.toXML().toString()); interpretedText2.append(packet.toXML().toString());
@ -286,17 +296,19 @@ public class LiteDebugger implements SmackDebugger {
/** /**
* Listens for debug window popup dialog events. * Listens for debug window popup dialog events.
*/ */
private class PopupListener extends MouseAdapter { private static class PopupListener extends MouseAdapter {
JPopupMenu popup; JPopupMenu popup;
PopupListener(JPopupMenu popupMenu) { PopupListener(JPopupMenu popupMenu) {
popup = popupMenu; popup = popupMenu;
} }
@Override
public void mousePressed(MouseEvent e) { public void mousePressed(MouseEvent e) {
maybeShowPopup(e); maybeShowPopup(e);
} }
@Override
public void mouseReleased(MouseEvent e) { public void mouseReleased(MouseEvent e) {
maybeShowPopup(e); maybeShowPopup(e);
} }
@ -308,6 +320,7 @@ public class LiteDebugger implements SmackDebugger {
} }
} }
@Override
public Reader newConnectionReader(Reader newReader) { public Reader newConnectionReader(Reader newReader) {
((ObservableReader)reader).removeReaderListener(readerListener); ((ObservableReader)reader).removeReaderListener(readerListener);
ObservableReader debugReader = new ObservableReader(newReader); ObservableReader debugReader = new ObservableReader(newReader);
@ -316,6 +329,7 @@ public class LiteDebugger implements SmackDebugger {
return reader; return reader;
} }
@Override
public Writer newConnectionWriter(Writer newWriter) { public Writer newConnectionWriter(Writer newWriter) {
((ObservableWriter)writer).removeWriterListener(writerListener); ((ObservableWriter)writer).removeWriterListener(writerListener);
ObservableWriter debugWriter = new ObservableWriter(newWriter); ObservableWriter debugWriter = new ObservableWriter(newWriter);
@ -332,18 +346,22 @@ public class LiteDebugger implements SmackDebugger {
frame.setTitle(title); frame.setTitle(title);
} }
@Override
public Reader getReader() { public Reader getReader() {
return reader; return reader;
} }
@Override
public Writer getWriter() { public Writer getWriter() {
return writer; return writer;
} }
@Override
public StanzaListener getReaderListener() { public StanzaListener getReaderListener() {
return listener; return listener;
} }
@Override
public StanzaListener getWriterListener() { public StanzaListener getWriterListener() {
return null; return null;
} }

View file

@ -0,0 +1,33 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.carbons;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension.Direction;
public interface CarbonCopyReceivedListener {
/**
* Invoked when a new carbon copy was received.
*
* @param direction the direction of the carbon copy.
* @param carbonCopy the carbon copy itself.
* @param wrappingMessage the message wrapping the carbon copy.
*/
void onCarbonCopyReceived(Direction direction, Message carbonCopy, Message wrappingMessage);
}

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2013-2014 Georg Lukas * Copyright 2013-2014 Georg Lukas, 2017 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,37 +17,54 @@
package org.jivesoftware.smackx.carbons; package org.jivesoftware.smackx.carbons;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import org.jivesoftware.smack.ExceptionCallback;
import org.jivesoftware.smack.AbstractConnectionListener; import org.jivesoftware.smack.AbstractConnectionListener;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.ExceptionCallback;
import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.StanzaListener; import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPConnectionRegistry; import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromMatchesFilter;
import org.jivesoftware.smack.filter.OrFilter;
import org.jivesoftware.smack.filter.StanzaExtensionFilter;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.filter.StanzaTypeFilter;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
import org.jivesoftware.smackx.carbons.packet.Carbon; import org.jivesoftware.smackx.carbons.packet.Carbon;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension.Direction;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension.Private; import org.jivesoftware.smackx.carbons.packet.CarbonExtension.Private;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.forward.packet.Forwarded;
import org.jxmpp.jid.EntityFullJid;
/** /**
* Stanza(/Packet) extension for XEP-0280: Message Carbons. This class implements * Manager for XEP-0280: Message Carbons. This class implements the manager for registering {@link CarbonExtension}
* the manager for registering {@link CarbonExtension} support, enabling and disabling * support, enabling and disabling message carbons, and for {@link CarbonCopyReceivedListener}.
* message carbons. * <p>
* * Note that <b>it is important to match the 'from' attribute of the message wrapping a carbon copy</b>, as otherwise it would
* You should call enableCarbons() before sending your first undirected * may be possible for others to impersonate users. Smack's CarbonManager takes care of that in
* presence. * {@link CarbonCopyReceivedListener}s which where registered with
* {@link #addCarbonCopyReceivedListener(CarbonCopyReceivedListener)}.
* </p>
* <p>
* You should call enableCarbons() before sending your first undirected presence (aka. the "initial presence").
* </p>
* *
* @author Georg Lukas * @author Georg Lukas
* @author Florian Schmaus
*/ */
public final class CarbonManager extends Manager { public final class CarbonManager extends Manager {
@ -55,18 +72,49 @@ public final class CarbonManager extends Manager {
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) { public void connectionCreated(XMPPConnection connection) {
getInstanceFor(connection); getInstanceFor(connection);
} }
}); });
} }
private static final StanzaFilter CARBON_EXTENSION_FILTER =
// @formatter:off
new AndFilter(
new OrFilter(
new StanzaExtensionFilter(CarbonExtension.Direction.sent.name(), CarbonExtension.NAMESPACE),
new StanzaExtensionFilter(CarbonExtension.Direction.received.name(), CarbonExtension.NAMESPACE)
),
StanzaTypeFilter.MESSAGE
);
// @formatter:on
private final Set<CarbonCopyReceivedListener> listeners = new CopyOnWriteArraySet<>();
private volatile boolean enabled_state = false; private volatile boolean enabled_state = false;
private final StanzaListener carbonsListener;
private CarbonManager(XMPPConnection connection) { private CarbonManager(XMPPConnection connection) {
super(connection); super(connection);
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
sdm.addFeature(CarbonExtension.NAMESPACE); sdm.addFeature(CarbonExtension.NAMESPACE);
carbonsListener = new StanzaListener() {
@Override
public void processStanza(final Stanza stanza) throws NotConnectedException, InterruptedException {
final Message wrappingMessage = (Message) stanza;
final CarbonExtension carbonExtension = CarbonExtension.from(wrappingMessage);
final Direction direction = carbonExtension.getDirection();
final Forwarded forwarded = carbonExtension.getForwarded();
final Message carbonCopy = (Message) forwarded.getForwardedStanza();
for (CarbonCopyReceivedListener listener : listeners) {
listener.onCarbonCopyReceived(direction, carbonCopy, wrappingMessage);
}
}
};
connection.addConnectionListener(new AbstractConnectionListener() { connection.addConnectionListener(new AbstractConnectionListener() {
@Override @Override
public void connectionClosed() { public void connectionClosed() {
@ -74,6 +122,8 @@ public final class CarbonManager extends Manager {
// because we also reset in authenticated() if the stream got not resumed, but for maximum correctness, // because we also reset in authenticated() if the stream got not resumed, but for maximum correctness,
// also reset here. // also reset here.
enabled_state = false; enabled_state = false;
boolean removed = connection().removeSyncStanzaListener(carbonsListener);
assert(removed);
} }
@Override @Override
public void authenticated(XMPPConnection connection, boolean resumed) { public void authenticated(XMPPConnection connection, boolean resumed) {
@ -81,8 +131,27 @@ public final class CarbonManager extends Manager {
// Non-resumed XMPP sessions always start with disabled carbons // Non-resumed XMPP sessions always start with disabled carbons
enabled_state = false; enabled_state = false;
} }
addCarbonsListener(connection);
} }
}); });
addCarbonsListener(connection);
}
private void addCarbonsListener(XMPPConnection connection) {
EntityFullJid localAddress = connection.getUser();
if (localAddress == null) {
// We where not connected yet and thus we don't know our XMPP address at the moment, which we need to match incoming
// carbons securely. Abort here. The ConnectionListener above will eventually setup the carbons listener.
return;
}
// XEP-0280 § 11. Security Considerations "Any forwarded copies received by a Carbons-enabled client MUST be
// from that user's bare JID; any copies that do not meet this requirement MUST be ignored." Otherwise, if
// those copies do not get ignored, malicious users may be able to impersonate other users. That is why the
// 'from' matcher is important here.
connection.addSyncStanzaListener(carbonsListener, new AndFilter(CARBON_EXTENSION_FILTER,
FromMatchesFilter.createBare(localAddress)));
} }
/** /**
@ -113,6 +182,28 @@ public final class CarbonManager extends Manager {
return request; return request;
} }
/**
* Add a carbon copy received listener.
*
* @param listener the listener to register.
* @return <code>true</code> if the filter was not already registered.
* @since 4.2
*/
public boolean addCarbonCopyReceivedListener(CarbonCopyReceivedListener listener) {
return listeners.add(listener);
}
/**
* Remove a carbon copy received listener.
*
* @param listener the listener to register.
* @return <code>true</code> if the filter was registered.
* @since 4.2
*/
public boolean removeCarbonCopyReceivedListener(CarbonCopyReceivedListener listener) {
return listeners.remove(listener);
}
/** /**
* Returns true if XMPP Carbons are supported by the server. * Returns true if XMPP Carbons are supported by the server.
* *
@ -181,6 +272,7 @@ public final class CarbonManager extends Manager {
try { try {
connection().sendIqWithResponseCallback(setIQ, new StanzaListener() { connection().sendIqWithResponseCallback(setIQ, new StanzaListener() {
@Override
public void processStanza(Stanza packet) { public void processStanza(Stanza packet) {
enabled_state = use; enabled_state = use;
} }

View file

@ -44,6 +44,7 @@ public abstract class AbstractHttpOverXmpp extends IQ {
this.version = Objects.requireNonNull(builder.version, "version must not be null"); this.version = Objects.requireNonNull(builder.version, "version must not be null");
} }
@Override
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
IQChildElementXmlStringBuilder builder = getIQHoxtChildElementBuilder(xml); IQChildElementXmlStringBuilder builder = getIQHoxtChildElementBuilder(xml);
builder.optAppend(headers); builder.optAppend(headers);

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2016 Florian Schmaus * Copyright © 2016-2017 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
*/ */
package org.jivesoftware.smackx.iot.control.element; package org.jivesoftware.smackx.iot.control.element;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -31,7 +32,21 @@ public class IoTSetRequest extends IQ {
public IoTSetRequest(Collection<? extends SetData> setData) { public IoTSetRequest(Collection<? extends SetData> setData) {
super(ELEMENT, NAMESPACE); super(ELEMENT, NAMESPACE);
setType(Type.set); setType(Type.set);
this.setData = Collections.unmodifiableCollection(setData);
/*
* Ugly workaround for the following error prone false positive:
*
* IoTSetRequest.java:34: error: incompatible types: Collection<CAP#1> cannot be converted to Collection<SetData>
* this.setData = Collections.unmodifiableCollection(setDataA);
* ^
* where CAP#1 is a fresh type-variable:
* CAP#1 extends SetData from capture of ? extends SetData
*/
Collection<SetData> tmp = new ArrayList<>(setData.size());
for (SetData data : setData) {
tmp.add(data);
}
this.setData = Collections.unmodifiableCollection(tmp);
} }
public Collection<SetData> getSetData() { public Collection<SetData> getSetData() {

View file

@ -30,7 +30,7 @@ public abstract class SetData implements NamedElement {
DOUBLE, DOUBLE,
; ;
private String toStringCache; private final String toStringCache;
private Type() { private Type() {
toStringCache = this.name().toLowerCase(Locale.US); toStringCache = this.name().toLowerCase(Locale.US);

View file

@ -61,6 +61,7 @@ public final class IoTDataManager extends IoTManager {
// Ensure a IoTDataManager exists for every connection. // Ensure a IoTDataManager exists for every connection.
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) { public void connectionCreated(XMPPConnection connection) {
if (!isAutoEnableActive()) return; if (!isAutoEnableActive()) return;
getInstanceFor(connection); getInstanceFor(connection);

View file

@ -74,6 +74,7 @@ public final class IoTDiscoveryManager extends Manager {
// Ensure a IoTProvisioningManager exists for every connection. // Ensure a IoTProvisioningManager exists for every connection.
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) { public void connectionCreated(XMPPConnection connection) {
if (!IoTManager.isAutoEnableActive()) return; if (!IoTManager.isAutoEnableActive()) return;
getInstanceFor(connection); getInstanceFor(connection);

View file

@ -62,6 +62,7 @@ public final class NodeInfo {
} }
@Override @Override
@SuppressWarnings("ReferenceEquality")
public int hashCode() { public int hashCode() {
if (this == EMPTY) { if (this == EMPTY) {
return 0; return 0;

View file

@ -82,6 +82,7 @@ public final class IoTProvisioningManager extends Manager {
// Ensure a IoTProvisioningManager exists for every connection. // Ensure a IoTProvisioningManager exists for every connection.
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) { public void connectionCreated(XMPPConnection connection) {
if (!IoTManager.isAutoEnableActive()) return; if (!IoTManager.isAutoEnableActive()) return;
getInstanceFor(connection); getInstanceFor(connection);

View file

@ -267,7 +267,7 @@ public class MultiUserChatLight {
try { try {
connection.createStanzaCollectorAndSend(createMUCLightIQ).nextResultOrThrow(); connection.createStanzaCollectorAndSend(createMUCLightIQ).nextResultOrThrow();
} catch (InterruptedException | NoResponseException | XMPPErrorException e) { } catch (NotConnectedException | InterruptedException | NoResponseException | XMPPErrorException e) {
removeConnectionCallbacks(); removeConnectionCallbacks();
throw e; throw e;
} }

View file

@ -53,6 +53,7 @@ import org.jxmpp.jid.Jid;
* *
* @see <a href="https://xmpp.org/extensions/xep-0296.html">XEP-0296: Best Practices for Resource Locking</a> * @see <a href="https://xmpp.org/extensions/xep-0296.html">XEP-0296: Best Practices for Resource Locking</a>
*/ */
@SuppressWarnings("FunctionalInterfaceClash")
public final class ChatManager extends Manager { public final class ChatManager extends Manager {
private static final Map<XMPPConnection, ChatManager> INSTANCES = new WeakHashMap<>(); private static final Map<XMPPConnection, ChatManager> INSTANCES = new WeakHashMap<>();
@ -69,7 +70,7 @@ public final class ChatManager extends Manager {
// @FORMATTER:OFF // @FORMATTER:OFF
private static final StanzaFilter MESSAGE_FILTER = new AndFilter( private static final StanzaFilter MESSAGE_FILTER = new AndFilter(
MessageTypeFilter.NORMAL_OR_CHAT, MessageTypeFilter.NORMAL_OR_CHAT,
new OrFilter(MessageWithBodiesFilter.INSTANCE), new StanzaExtensionFilter(XHTMLExtension.ELEMENT, XHTMLExtension.NAMESPACE) new OrFilter(MessageWithBodiesFilter.INSTANCE, new StanzaExtensionFilter(XHTMLExtension.ELEMENT, XHTMLExtension.NAMESPACE))
); );
private static final StanzaFilter OUTGOING_MESSAGE_FILTER = new AndFilter( private static final StanzaFilter OUTGOING_MESSAGE_FILTER = new AndFilter(
@ -188,22 +189,84 @@ public final class ChatManager extends Manager {
return true; return true;
} }
public boolean addListener(IncomingChatMessageListener listener) { /**
* Add a new listener for incoming chat messages.
*
* @param listener the listener to add.
* @return <code>true</code> if the listener was not already added.
*/
public boolean addIncomingListener(IncomingChatMessageListener listener) {
return incomingListeners.add(listener); return incomingListeners.add(listener);
} }
/**
* Add a new listener for incoming chat messages.
*
* @param listener the listener to add.
* @return <code>true</code> if the listener was not already added.
*/
@Deprecated
@SuppressWarnings("FunctionalInterfaceClash")
public boolean addListener(IncomingChatMessageListener listener) {
return addIncomingListener(listener);
}
/**
* Remove an incoming chat message listener.
*
* @param listener the listener to remove.
* @return <code>true</code> if the listener was active and got removed.
*/
@SuppressWarnings("FunctionalInterfaceClash")
public boolean removeListener(IncomingChatMessageListener listener) { public boolean removeListener(IncomingChatMessageListener listener) {
return incomingListeners.remove(listener); return incomingListeners.remove(listener);
} }
public boolean addListener(OutgoingChatMessageListener listener) { /**
* Add a new listener for outgoing chat messages.
*
* @param listener the listener to add.
* @return <code>true</code> if the listener was not already added.
*/
public boolean addOutgoingListener(OutgoingChatMessageListener listener) {
return outgoingListeners.add(listener); return outgoingListeners.add(listener);
} }
public boolean removeOutoingLIstener(OutgoingChatMessageListener listener) { /**
* Add a new listener for incoming chat messages.
*
* @param listener the listener to add.
* @return <code>true</code> if the listener was not already added.
* @deprecated use {@link #addOutgoingListener(OutgoingChatMessageListener)} instead.
*/
@Deprecated
@SuppressWarnings("FunctionalInterfaceClash")
public boolean addListener(OutgoingChatMessageListener listener) {
return addOutgoingListener(listener);
}
/**
* Remove an outgoing chat message listener.
*
* @param listener the listener to remove.
* @return <code>true</code> if the listener was active and got removed.
*/
public boolean removeListener(OutgoingChatMessageListener listener) {
return outgoingListeners.remove(listener); return outgoingListeners.remove(listener);
} }
/**
* Remove an outgoing chat message listener.
*
* @param listener the listener to remove.
* @return <code>true</code> if the listener was active and got removed.
* @deprecated use {@link #removeListener(OutgoingChatMessageListener)} instead.
*/
@Deprecated
public boolean removeOutoingLIstener(OutgoingChatMessageListener listener) {
return removeListener(listener);
}
/** /**
* Start a new or retrieve the existing chat with <code>jid</code>. * Start a new or retrieve the existing chat with <code>jid</code>.
* *

View file

@ -40,6 +40,7 @@ public class AMPManager {
// The ServiceDiscoveryManager class should have been already initialized // The ServiceDiscoveryManager class should have been already initialized
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) { public void connectionCreated(XMPPConnection connection) {
AMPManager.setServiceEnabled(connection, true); AMPManager.setServiceEnabled(connection, true);
} }

View file

@ -47,6 +47,7 @@ public class AttentionExtension implements ExtensionElement {
* *
* @see org.jivesoftware.smack.packet.PacketExtension#getElementName() * @see org.jivesoftware.smack.packet.PacketExtension#getElementName()
*/ */
@Override
public String getElementName() { public String getElementName() {
return ELEMENT_NAME; return ELEMENT_NAME;
} }
@ -56,6 +57,7 @@ public class AttentionExtension implements ExtensionElement {
* *
* @see org.jivesoftware.smack.packet.PacketExtension#getNamespace() * @see org.jivesoftware.smack.packet.PacketExtension#getNamespace()
*/ */
@Override
public String getNamespace() { public String getNamespace() {
return NAMESPACE; return NAMESPACE;
} }
@ -65,6 +67,7 @@ public class AttentionExtension implements ExtensionElement {
* *
* @see org.jivesoftware.smack.packet.PacketExtension#toXML() * @see org.jivesoftware.smack.packet.PacketExtension#toXML()
*/ */
@Override
public String toXML() { public String toXML() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append('<').append(getElementName()).append(" xmlns=\"").append( sb.append('<').append(getElementName()).append(" xmlns=\"").append(

View file

@ -0,0 +1,23 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.blocking;
public interface AllJidsUnblockedListener {
void onAllJidsUnblocked();
}

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2016 Fernando Ramirez, Florian Schmaus * Copyright 2016-2017 Fernando Ramirez, Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,7 +20,9 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import org.jivesoftware.smack.AbstractConnectionListener; import org.jivesoftware.smack.AbstractConnectionListener;
import org.jivesoftware.smack.ConnectionCreationListener; import org.jivesoftware.smack.ConnectionCreationListener;
@ -82,6 +84,12 @@ public final class BlockingCommandManager extends Manager {
return blockingCommandManager; return blockingCommandManager;
} }
private final Set<AllJidsUnblockedListener> allJidsUnblockedListeners = new CopyOnWriteArraySet<>();
private final Set<JidsBlockedListener> jidsBlockedListeners = new CopyOnWriteArraySet<>();
private final Set<JidsUnblockedListener> jidsUnblockedListeners = new CopyOnWriteArraySet<>();
private BlockingCommandManager(XMPPConnection connection) { private BlockingCommandManager(XMPPConnection connection) {
super(connection); super(connection);
@ -99,6 +107,10 @@ public final class BlockingCommandManager extends Manager {
List<Jid> blockedJids = blockContactIQ.getJids(); List<Jid> blockedJids = blockContactIQ.getJids();
blockListCached.addAll(blockedJids); blockListCached.addAll(blockedJids);
for (JidsBlockedListener listener : jidsBlockedListeners) {
listener.onJidsBlocked(blockedJids);
}
return IQ.createResultIQ(blockContactIQ); return IQ.createResultIQ(blockContactIQ);
} }
}); });
@ -117,8 +129,14 @@ public final class BlockingCommandManager extends Manager {
List<Jid> unblockedJids = unblockContactIQ.getJids(); List<Jid> unblockedJids = unblockContactIQ.getJids();
if (unblockedJids == null) { // remove all if (unblockedJids == null) { // remove all
blockListCached.clear(); blockListCached.clear();
for (AllJidsUnblockedListener listener : allJidsUnblockedListeners) {
listener.onAllJidsUnblocked();
}
} else { // remove only some } else { // remove only some
blockListCached.removeAll(unblockedJids); blockListCached.removeAll(unblockedJids);
for (JidsUnblockedListener listener : jidsUnblockedListeners) {
listener.onJidsUnblocked(unblockedJids);
}
} }
return IQ.createResultIQ(unblockContactIQ); return IQ.createResultIQ(unblockContactIQ);
@ -216,4 +234,27 @@ public final class BlockingCommandManager extends Manager {
connection().createStanzaCollectorAndSend(unblockContactIQ).nextResultOrThrow(); connection().createStanzaCollectorAndSend(unblockContactIQ).nextResultOrThrow();
} }
public void addJidsBlockedListener(JidsBlockedListener jidsBlockedListener) {
jidsBlockedListeners.add(jidsBlockedListener);
}
public void removeJidsBlockedListener(JidsBlockedListener jidsBlockedListener) {
jidsBlockedListeners.remove(jidsBlockedListener);
}
public void addJidsUnblockedListener(JidsUnblockedListener jidsUnblockedListener) {
jidsUnblockedListeners.add(jidsUnblockedListener);
}
public void removeJidsUnblockedListener(JidsUnblockedListener jidsUnblockedListener) {
jidsUnblockedListeners.remove(jidsUnblockedListener);
}
public void addAllJidsUnblockedListener(AllJidsUnblockedListener allJidsUnblockedListener) {
allJidsUnblockedListeners.add(allJidsUnblockedListener);
}
public void removeAllJidsUnblockedListener(AllJidsUnblockedListener allJidsUnblockedListener) {
allJidsUnblockedListeners.remove(allJidsUnblockedListener);
}
} }

View file

@ -0,0 +1,27 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.blocking;
import java.util.List;
import org.jxmpp.jid.Jid;
public interface JidsBlockedListener {
void onJidsBlocked(List<Jid> blockedJids);
}

View file

@ -0,0 +1,27 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.blocking;
import java.util.List;
import org.jxmpp.jid.Jid;
public interface JidsUnblockedListener {
void onJidsUnblocked(List<Jid> unblockedJids);
}

View file

@ -16,6 +16,7 @@
*/ */
package org.jivesoftware.smackx.blocking.element; package org.jivesoftware.smackx.blocking.element;
import java.util.Collections;
import java.util.List; import java.util.List;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
@ -51,7 +52,7 @@ public class BlockContactsIQ extends IQ {
public BlockContactsIQ(List<Jid> jids) { public BlockContactsIQ(List<Jid> jids) {
super(ELEMENT, NAMESPACE); super(ELEMENT, NAMESPACE);
this.setType(Type.set); this.setType(Type.set);
this.jids = jids; this.jids = Collections.unmodifiableList(jids);
} }
/** /**

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2016 Fernando Ramirez, Florian Schmaus * Copyright 2016-2017 Fernando Ramirez, Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
*/ */
package org.jivesoftware.smackx.blocking.element; package org.jivesoftware.smackx.blocking.element;
import java.util.Collections;
import java.util.List; import java.util.List;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
@ -52,7 +53,11 @@ public class UnblockContactsIQ extends IQ {
public UnblockContactsIQ(List<Jid> jids) { public UnblockContactsIQ(List<Jid> jids) {
super(ELEMENT, NAMESPACE); super(ELEMENT, NAMESPACE);
this.setType(Type.set); this.setType(Type.set);
this.jids = jids; if (jids != null) {
this.jids = Collections.unmodifiableList(jids);
} else {
this.jids = null;
}
} }
/** /**
@ -63,9 +68,9 @@ public class UnblockContactsIQ extends IQ {
} }
/** /**
* Get the JIDs. * Get the JIDs. This may return null, which means that all JIDs should be or where unblocked.
* *
* @return the list of JIDs * @return the list of JIDs or <code>null</code>.
*/ */
public List<Jid> getJids() { public List<Jid> getJids() {
return jids; return jids;
@ -73,14 +78,16 @@ public class UnblockContactsIQ extends IQ {
@Override @Override
protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
xml.rightAngleBracket(); if (jids == null) {
xml.setEmptyElement();
return xml;
}
if (jids != null) { xml.rightAngleBracket();
for (Jid jid : jids) { for (Jid jid : jids) {
xml.halfOpenElement("item"); xml.halfOpenElement("item");
xml.attribute("jid", jid); xml.attribute("jid", jid);
xml.closeEmptyElement(); xml.closeEmptyElement();
}
} }
return xml; return xml;

View file

@ -20,9 +20,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.jivesoftware.smack.provider.IQProvider; import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smackx.blocking.element.BlockContactsIQ; import org.jivesoftware.smackx.blocking.element.BlockContactsIQ;
import org.jxmpp.jid.Jid; import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
/** /**
@ -36,7 +36,7 @@ public class BlockContactsIQProvider extends IQProvider<BlockContactsIQ> {
@Override @Override
public BlockContactsIQ parse(XmlPullParser parser, int initialDepth) throws Exception { public BlockContactsIQ parse(XmlPullParser parser, int initialDepth) throws Exception {
List<Jid> jids = null; List<Jid> jids = new ArrayList<>();
outerloop: while (true) { outerloop: while (true) {
int eventType = parser.next(); int eventType = parser.next();
@ -45,10 +45,8 @@ public class BlockContactsIQProvider extends IQProvider<BlockContactsIQ> {
case XmlPullParser.START_TAG: case XmlPullParser.START_TAG:
if (parser.getName().equals("item")) { if (parser.getName().equals("item")) {
if (jids == null) { Jid jid = ParserUtils.getJidAttribute(parser);
jids = new ArrayList<>(); jids.add(jid);
}
jids.add(JidCreate.from(parser.getAttributeValue("", "jid")));
} }
break; break;

View file

@ -131,6 +131,7 @@ public class BookmarkedConference implements SharedBookmark {
this.isShared = isShared; this.isShared = isShared;
} }
@Override
public boolean isShared() { public boolean isShared() {
return isShared; return isShared;
} }

View file

@ -102,6 +102,7 @@ public class BookmarkedURL implements SharedBookmark {
this.isShared = shared; this.isShared = shared;
} }
@Override
public boolean isShared() { public boolean isShared() {
return isShared; return isShared;
} }

View file

@ -151,6 +151,7 @@ public class Bookmarks implements PrivateData {
* *
* @return the element name. * @return the element name.
*/ */
@Override
public String getElementName() { public String getElementName() {
return ELEMENT; return ELEMENT;
} }
@ -160,6 +161,7 @@ public class Bookmarks implements PrivateData {
* *
* @return the namespace. * @return the namespace.
*/ */
@Override
public String getNamespace() { public String getNamespace() {
return NAMESPACE; return NAMESPACE;
} }
@ -218,6 +220,7 @@ public class Bookmarks implements PrivateData {
super(); super();
} }
@Override
public PrivateData parsePrivateData(XmlPullParser parser) throws XmlPullParserException, IOException { public PrivateData parsePrivateData(XmlPullParser parser) throws XmlPullParserException, IOException {
Bookmarks storage = new Bookmarks(); Bookmarks storage = new Bookmarks();

View file

@ -34,6 +34,7 @@ public abstract class InBandBytestreamListener implements BytestreamListener {
@Override
public void incomingBytestreamRequest(BytestreamRequest request) { public void incomingBytestreamRequest(BytestreamRequest request) {
incomingBytestreamRequest((InBandBytestreamRequest) request); incomingBytestreamRequest((InBandBytestreamRequest) request);
} }

View file

@ -103,6 +103,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
*/ */
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(final XMPPConnection connection) { public void connectionCreated(final XMPPConnection connection) {
// create the manager for this connection // create the manager for this connection
InBandBytestreamManager.getByteStreamManager(connection); InBandBytestreamManager.getByteStreamManager(connection);
@ -236,6 +237,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
* *
* @param listener the listener to register * @param listener the listener to register
*/ */
@Override
public void addIncomingBytestreamListener(BytestreamListener listener) { public void addIncomingBytestreamListener(BytestreamListener listener) {
this.allRequestListeners.add(listener); this.allRequestListeners.add(listener);
} }
@ -246,6 +248,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
* *
* @param listener the listener to remove * @param listener the listener to remove
*/ */
@Override
public void removeIncomingBytestreamListener(BytestreamListener listener) { public void removeIncomingBytestreamListener(BytestreamListener listener) {
this.allRequestListeners.remove(listener); this.allRequestListeners.remove(listener);
} }
@ -268,6 +271,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
* @param listener the listener to register * @param listener the listener to register
* @param initiatorJID the JID of the user that wants to establish an In-Band Bytestream * @param initiatorJID the JID of the user that wants to establish an In-Band Bytestream
*/ */
@Override
public void addIncomingBytestreamListener(BytestreamListener listener, Jid initiatorJID) { public void addIncomingBytestreamListener(BytestreamListener listener, Jid initiatorJID) {
this.userListeners.put(initiatorJID, listener); this.userListeners.put(initiatorJID, listener);
} }
@ -277,6 +281,9 @@ public final class InBandBytestreamManager implements BytestreamManager {
* *
* @param initiatorJID the JID of the user the listener should be removed * @param initiatorJID the JID of the user the listener should be removed
*/ */
@Override
// TODO: Change argument to Jid in Smack 4.3.
@SuppressWarnings("CollectionIncompatibleType")
public void removeIncomingBytestreamListener(String initiatorJID) { public void removeIncomingBytestreamListener(String initiatorJID) {
this.userListeners.remove(initiatorJID); this.userListeners.remove(initiatorJID);
} }
@ -402,6 +409,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
* @throws SmackException if there was no response from the server. * @throws SmackException if there was no response from the server.
* @throws InterruptedException * @throws InterruptedException
*/ */
@Override
public InBandBytestreamSession establishSession(Jid targetJID) throws XMPPException, SmackException, InterruptedException { public InBandBytestreamSession establishSession(Jid targetJID) throws XMPPException, SmackException, InterruptedException {
String sessionID = getNextSessionID(); String sessionID = getNextSessionID();
return establishSession(targetJID, sessionID); return establishSession(targetJID, sessionID);
@ -420,6 +428,7 @@ public final class InBandBytestreamManager implements BytestreamManager {
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
@Override
public InBandBytestreamSession establishSession(Jid targetJID, String sessionID) public InBandBytestreamSession establishSession(Jid targetJID, String sessionID)
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
Open byteStreamRequest = new Open(sessionID, this.defaultBlockSize, this.stanza); Open byteStreamRequest = new Open(sessionID, this.defaultBlockSize, this.stanza);

View file

@ -50,6 +50,7 @@ public class InBandBytestreamRequest implements BytestreamRequest {
* *
* @return the sender of the In-Band Bytestream open request * @return the sender of the In-Band Bytestream open request
*/ */
@Override
public Jid getFrom() { public Jid getFrom() {
return this.byteStreamRequest.getFrom(); return this.byteStreamRequest.getFrom();
} }
@ -59,6 +60,7 @@ public class InBandBytestreamRequest implements BytestreamRequest {
* *
* @return the session ID of the In-Band Bytestream open request * @return the session ID of the In-Band Bytestream open request
*/ */
@Override
public String getSessionID() { public String getSessionID() {
return this.byteStreamRequest.getSessionID(); return this.byteStreamRequest.getSessionID();
} }
@ -71,6 +73,7 @@ public class InBandBytestreamRequest implements BytestreamRequest {
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
@Override
public InBandBytestreamSession accept() throws NotConnectedException, InterruptedException { public InBandBytestreamSession accept() throws NotConnectedException, InterruptedException {
XMPPConnection connection = this.manager.getConnection(); XMPPConnection connection = this.manager.getConnection();
@ -92,6 +95,7 @@ public class InBandBytestreamRequest implements BytestreamRequest {
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
@Override
public void reject() throws NotConnectedException, InterruptedException { public void reject() throws NotConnectedException, InterruptedException {
this.manager.replyRejectPacket(this.byteStreamRequest); this.manager.replyRejectPacket(this.byteStreamRequest);
} }

View file

@ -109,18 +109,22 @@ public class InBandBytestreamSession implements BytestreamSession {
} }
@Override
public InputStream getInputStream() { public InputStream getInputStream() {
return this.inputStream; return this.inputStream;
} }
@Override
public OutputStream getOutputStream() { public OutputStream getOutputStream() {
return this.outputStream; return this.outputStream;
} }
@Override
public int getReadTimeout() { public int getReadTimeout() {
return this.inputStream.readTimeout; return this.inputStream.readTimeout;
} }
@Override
public void setReadTimeout(int timeout) { public void setReadTimeout(int timeout) {
if (timeout < 0) { if (timeout < 0) {
throw new IllegalArgumentException("Timeout must be >= 0"); throw new IllegalArgumentException("Timeout must be >= 0");
@ -151,6 +155,7 @@ public class InBandBytestreamSession implements BytestreamSession {
this.closeBothStreamsEnabled = closeBothStreamsEnabled; this.closeBothStreamsEnabled = closeBothStreamsEnabled;
} }
@Override
public void close() throws IOException { public void close() throws IOException {
closeByLocal(true); // close input stream closeByLocal(true); // close input stream
closeByLocal(false); // close output stream closeByLocal(false); // close output stream
@ -224,7 +229,9 @@ public class InBandBytestreamSession implements BytestreamSession {
this.inputStream.cleanup(); this.inputStream.cleanup();
// remove session from manager // remove session from manager
InBandBytestreamManager.getByteStreamManager(this.connection).getSessions().remove(this); // Thanks Google Error Prone for finding the bug where remove() was called with 'this' as argument. Changed
// now to remove(byteStreamRequest.getSessionID).
InBandBytestreamManager.getByteStreamManager(this.connection).getSessions().remove(byteStreamRequest.getSessionID());
} }
} }
@ -283,6 +290,7 @@ public class InBandBytestreamSession implements BytestreamSession {
*/ */
protected abstract StanzaFilter getDataPacketFilter(); protected abstract StanzaFilter getDataPacketFilter();
@Override
public synchronized int read() throws IOException { public synchronized int read() throws IOException {
checkClosed(); checkClosed();
@ -298,6 +306,7 @@ public class InBandBytestreamSession implements BytestreamSession {
return buffer[bufferPointer++] & 0xff; return buffer[bufferPointer++] & 0xff;
} }
@Override
public synchronized int read(byte[] b, int off, int len) throws IOException { public synchronized int read(byte[] b, int off, int len) throws IOException {
if (b == null) { if (b == null) {
throw new NullPointerException(); throw new NullPointerException();
@ -331,6 +340,7 @@ public class InBandBytestreamSession implements BytestreamSession {
return len; return len;
} }
@Override
public synchronized int read(byte[] b) throws IOException { public synchronized int read(byte[] b) throws IOException {
return read(b, 0, b.length); return read(b, 0, b.length);
} }
@ -405,10 +415,12 @@ public class InBandBytestreamSession implements BytestreamSession {
} }
} }
@Override
public boolean markSupported() { public boolean markSupported() {
return false; return false;
} }
@Override
public void close() throws IOException { public void close() throws IOException {
if (closeInvoked) { if (closeInvoked) {
return; return;
@ -444,11 +456,13 @@ public class InBandBytestreamSession implements BytestreamSession {
*/ */
private class IQIBBInputStream extends IBBInputStream { private class IQIBBInputStream extends IBBInputStream {
@Override
protected StanzaListener getDataPacketListener() { protected StanzaListener getDataPacketListener() {
return new StanzaListener() { return new StanzaListener() {
private long lastSequence = -1; private long lastSequence = -1;
@Override
public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException { public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException {
// get data packet extension // get data packet extension
DataPacketExtension data = ((Data) packet).getDataPacketExtension(); DataPacketExtension data = ((Data) packet).getDataPacketExtension();
@ -491,6 +505,7 @@ public class InBandBytestreamSession implements BytestreamSession {
}; };
} }
@Override
protected StanzaFilter getDataPacketFilter() { protected StanzaFilter getDataPacketFilter() {
/* /*
* filter all IQ stanzas having type 'SET' (represented by Data class), containing a * filter all IQ stanzas having type 'SET' (represented by Data class), containing a
@ -507,9 +522,11 @@ public class InBandBytestreamSession implements BytestreamSession {
*/ */
private class MessageIBBInputStream extends IBBInputStream { private class MessageIBBInputStream extends IBBInputStream {
@Override
protected StanzaListener getDataPacketListener() { protected StanzaListener getDataPacketListener() {
return new StanzaListener() { return new StanzaListener() {
@Override
public void processStanza(Stanza packet) { public void processStanza(Stanza packet) {
// get data packet extension // get data packet extension
DataPacketExtension data = (DataPacketExtension) packet.getExtension( DataPacketExtension data = (DataPacketExtension) packet.getExtension(
@ -555,6 +572,7 @@ public class InBandBytestreamSession implements BytestreamSession {
*/ */
private class IBBDataPacketFilter implements StanzaFilter { private class IBBDataPacketFilter implements StanzaFilter {
@Override
public boolean accept(Stanza packet) { public boolean accept(Stanza packet) {
// sender equals remote peer // sender equals remote peer
if (!packet.getFrom().equals(remoteJID)) { if (!packet.getFrom().equals(remoteJID)) {
@ -619,6 +637,7 @@ public class InBandBytestreamSession implements BytestreamSession {
*/ */
protected abstract void writeToXML(DataPacketExtension data) throws IOException, NotConnectedException, InterruptedException; protected abstract void writeToXML(DataPacketExtension data) throws IOException, NotConnectedException, InterruptedException;
@Override
public synchronized void write(int b) throws IOException { public synchronized void write(int b) throws IOException {
if (this.isClosed) { if (this.isClosed) {
throw new IOException("Stream is closed"); throw new IOException("Stream is closed");
@ -632,6 +651,7 @@ public class InBandBytestreamSession implements BytestreamSession {
buffer[bufferPointer++] = (byte) b; buffer[bufferPointer++] = (byte) b;
} }
@Override
public synchronized void write(byte[] b, int off, int len) throws IOException { public synchronized void write(byte[] b, int off, int len) throws IOException {
if (b == null) { if (b == null) {
throw new NullPointerException(); throw new NullPointerException();
@ -662,6 +682,7 @@ public class InBandBytestreamSession implements BytestreamSession {
} }
} }
@Override
public synchronized void write(byte[] b) throws IOException { public synchronized void write(byte[] b) throws IOException {
write(b, 0, b.length); write(b, 0, b.length);
} }
@ -698,6 +719,7 @@ public class InBandBytestreamSession implements BytestreamSession {
bufferPointer += len - available; bufferPointer += len - available;
} }
@Override
public synchronized void flush() throws IOException { public synchronized void flush() throws IOException {
if (this.isClosed) { if (this.isClosed) {
throw new IOException("Stream is closed"); throw new IOException("Stream is closed");
@ -735,6 +757,7 @@ public class InBandBytestreamSession implements BytestreamSession {
} }
@Override
public void close() throws IOException { public void close() throws IOException {
if (isClosed) { if (isClosed) {
return; return;

View file

@ -66,6 +66,7 @@ class InitiationListener extends AbstractIqRequestHandler {
public IQ handleIQRequest(final IQ packet) { public IQ handleIQRequest(final IQ packet) {
initiationListenerExecutor.execute(new Runnable() { initiationListenerExecutor.execute(new Runnable() {
@Override
public void run() { public void run() {
try { try {
processRequest(packet); processRequest(packet);

View file

@ -126,10 +126,12 @@ public class DataPacketExtension implements ExtensionElement {
return this.decodedData; return this.decodedData;
} }
@Override
public String getElementName() { public String getElementName() {
return ELEMENT; return ELEMENT;
} }
@Override
public String getNamespace() { public String getNamespace() {
return NAMESPACE; return NAMESPACE;
} }

View file

@ -62,6 +62,7 @@ final class InitiationListener extends AbstractIqRequestHandler {
public IQ handleIQRequest(final IQ packet) { public IQ handleIQRequest(final IQ packet) {
initiationListenerExecutor.execute(new Runnable() { initiationListenerExecutor.execute(new Runnable() {
@Override
public void run() { public void run() {
try { try {
processRequest(packet); processRequest(packet);

View file

@ -32,6 +32,7 @@ import org.jivesoftware.smackx.bytestreams.BytestreamRequest;
*/ */
public abstract class Socks5BytestreamListener implements BytestreamListener { public abstract class Socks5BytestreamListener implements BytestreamListener {
@Override
public void incomingBytestreamRequest(BytestreamRequest request) { public void incomingBytestreamRequest(BytestreamRequest request) {
incomingBytestreamRequest((Socks5BytestreamRequest) request); incomingBytestreamRequest((Socks5BytestreamRequest) request);
} }

View file

@ -98,6 +98,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(final XMPPConnection connection) { public void connectionCreated(final XMPPConnection connection) {
// create the manager for this connection // create the manager for this connection
Socks5BytestreamManager.getBytestreamManager(connection); Socks5BytestreamManager.getBytestreamManager(connection);
@ -198,6 +199,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
* *
* @param listener the listener to register * @param listener the listener to register
*/ */
@Override
public void addIncomingBytestreamListener(BytestreamListener listener) { public void addIncomingBytestreamListener(BytestreamListener listener) {
this.allRequestListeners.add(listener); this.allRequestListeners.add(listener);
} }
@ -208,6 +210,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
* *
* @param listener the listener to remove * @param listener the listener to remove
*/ */
@Override
public void removeIncomingBytestreamListener(BytestreamListener listener) { public void removeIncomingBytestreamListener(BytestreamListener listener) {
this.allRequestListeners.remove(listener); this.allRequestListeners.remove(listener);
} }
@ -230,6 +233,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
* @param listener the listener to register * @param listener the listener to register
* @param initiatorJID the JID of the user that wants to establish a SOCKS5 Bytestream * @param initiatorJID the JID of the user that wants to establish a SOCKS5 Bytestream
*/ */
@Override
public void addIncomingBytestreamListener(BytestreamListener listener, Jid initiatorJID) { public void addIncomingBytestreamListener(BytestreamListener listener, Jid initiatorJID) {
this.userListeners.put(initiatorJID, listener); this.userListeners.put(initiatorJID, listener);
} }
@ -239,6 +243,9 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
* *
* @param initiatorJID the JID of the user the listener should be removed * @param initiatorJID the JID of the user the listener should be removed
*/ */
// TODO: Change parameter to Jid in Smack 4.3.
@Override
@SuppressWarnings("CollectionIncompatibleType")
public void removeIncomingBytestreamListener(String initiatorJID) { public void removeIncomingBytestreamListener(String initiatorJID) {
this.userListeners.remove(initiatorJID); this.userListeners.remove(initiatorJID);
} }
@ -386,6 +393,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
* @throws InterruptedException if the current thread was interrupted while waiting * @throws InterruptedException if the current thread was interrupted while waiting
* @throws SmackException if there was no response from the server. * @throws SmackException if there was no response from the server.
*/ */
@Override
public Socks5BytestreamSession establishSession(Jid targetJID) throws XMPPException, public Socks5BytestreamSession establishSession(Jid targetJID) throws XMPPException,
IOException, InterruptedException, SmackException { IOException, InterruptedException, SmackException {
String sessionID = getNextSessionID(); String sessionID = getNextSessionID();
@ -405,6 +413,7 @@ public final class Socks5BytestreamManager extends Manager implements Bytestream
* @throws SmackException if the target does not support SOCKS5. * @throws SmackException if the target does not support SOCKS5.
* @throws XMPPException * @throws XMPPException
*/ */
@Override
public Socks5BytestreamSession establishSession(Jid targetJID, String sessionID) public Socks5BytestreamSession establishSession(Jid targetJID, String sessionID)
throws IOException, InterruptedException, NoResponseException, SmackException, XMPPException{ throws IOException, InterruptedException, NoResponseException, SmackException, XMPPException{
XMPPConnection connection = connection(); XMPPConnection connection = connection();

View file

@ -170,6 +170,7 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
* *
* @return the sender of the SOCKS5 Bytestream initialization request. * @return the sender of the SOCKS5 Bytestream initialization request.
*/ */
@Override
public Jid getFrom() { public Jid getFrom() {
return this.bytestreamRequest.getFrom(); return this.bytestreamRequest.getFrom();
} }
@ -179,6 +180,7 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
* *
* @return the session ID of the SOCKS5 Bytestream initialization request. * @return the session ID of the SOCKS5 Bytestream initialization request.
*/ */
@Override
public String getSessionID() { public String getSessionID() {
return this.bytestreamRequest.getSessionID(); return this.bytestreamRequest.getSessionID();
} }
@ -195,6 +197,7 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
* @throws XMPPErrorException * @throws XMPPErrorException
* @throws SmackException * @throws SmackException
*/ */
@Override
public Socks5BytestreamSession accept() throws InterruptedException, XMPPErrorException, SmackException { public Socks5BytestreamSession accept() throws InterruptedException, XMPPErrorException, SmackException {
Collection<StreamHost> streamHosts = this.bytestreamRequest.getStreamHosts(); Collection<StreamHost> streamHosts = this.bytestreamRequest.getStreamHosts();
@ -264,6 +267,7 @@ public class Socks5BytestreamRequest implements BytestreamRequest {
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
@Override
public void reject() throws NotConnectedException, InterruptedException { public void reject() throws NotConnectedException, InterruptedException {
this.manager.replyRejectPacket(this.bytestreamRequest); this.manager.replyRejectPacket(this.bytestreamRequest);
} }

View file

@ -64,14 +64,17 @@ public class Socks5BytestreamSession implements BytestreamSession {
return !this.isDirect; return !this.isDirect;
} }
@Override
public InputStream getInputStream() throws IOException { public InputStream getInputStream() throws IOException {
return this.socket.getInputStream(); return this.socket.getInputStream();
} }
@Override
public OutputStream getOutputStream() throws IOException { public OutputStream getOutputStream() throws IOException {
return this.socket.getOutputStream(); return this.socket.getOutputStream();
} }
@Override
public int getReadTimeout() throws IOException { public int getReadTimeout() throws IOException {
try { try {
return this.socket.getSoTimeout(); return this.socket.getSoTimeout();
@ -81,6 +84,7 @@ public class Socks5BytestreamSession implements BytestreamSession {
} }
} }
@Override
public void setReadTimeout(int timeout) throws IOException { public void setReadTimeout(int timeout) throws IOException {
try { try {
this.socket.setSoTimeout(timeout); this.socket.setSoTimeout(timeout);
@ -90,6 +94,7 @@ public class Socks5BytestreamSession implements BytestreamSession {
} }
} }
@Override
public void close() throws IOException { public void close() throws IOException {
this.socket.close(); this.socket.close();
} }

View file

@ -19,6 +19,7 @@ package org.jivesoftware.smackx.bytestreams.socks5;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.net.SocketAddress; import java.net.SocketAddress;
@ -34,6 +35,7 @@ import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost; import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost;
/** /**
@ -82,6 +84,7 @@ class Socks5Client {
// wrap connecting in future for timeout // wrap connecting in future for timeout
FutureTask<Socket> futureTask = new FutureTask<Socket>(new Callable<Socket>() { FutureTask<Socket> futureTask = new FutureTask<Socket>(new Callable<Socket>() {
@Override
public Socket call() throws IOException, SmackException { public Socket call() throws IOException, SmackException {
// initialize socket // initialize socket
@ -199,7 +202,13 @@ class Socks5Client {
* @return SOCKS5 connection request message * @return SOCKS5 connection request message
*/ */
private byte[] createSocks5ConnectRequest() { private byte[] createSocks5ConnectRequest() {
byte[] addr = this.digest.getBytes(); byte[] addr;
try {
addr = digest.getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
byte[] data = new byte[7 + addr.length]; byte[] data = new byte[7 + addr.length];
data[0] = (byte) 0x05; // version (SOCKS5) data[0] = (byte) 0x05; // version (SOCKS5)

View file

@ -69,6 +69,7 @@ class Socks5ClientForInitiator extends Socks5Client {
this.target = target; this.target = target;
} }
@Override
public Socket getSocket(int timeout) throws IOException, InterruptedException, public Socket getSocket(int timeout) throws IOException, InterruptedException,
TimeoutException, XMPPException, SmackException { TimeoutException, XMPPException, SmackException {
Socket socket = null; Socket socket = null;

View file

@ -38,6 +38,7 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.util.StringUtils;
/** /**
* The Socks5Proxy class represents a local SOCKS5 proxy server. It can be enabled/disabled by * The Socks5Proxy class represents a local SOCKS5 proxy server. It can be enabled/disabled by
@ -381,6 +382,7 @@ public final class Socks5Proxy {
*/ */
private class Socks5ServerProcess implements Runnable { private class Socks5ServerProcess implements Runnable {
@Override
public void run() { public void run() {
while (true) { while (true) {
Socket socket = null; Socket socket = null;
@ -470,7 +472,7 @@ public final class Socks5Proxy {
byte[] connectionRequest = Socks5Utils.receiveSocks5Message(in); byte[] connectionRequest = Socks5Utils.receiveSocks5Message(in);
// extract digest // extract digest
String responseDigest = new String(connectionRequest, 5, connectionRequest[4]); String responseDigest = new String(connectionRequest, 5, connectionRequest[4], StringUtils.UTF8);
// return error if digest is not allowed // return error if digest is not allowed
if (!Socks5Proxy.this.allowedConnections.contains(responseDigest)) { if (!Socks5Proxy.this.allowedConnections.contains(responseDigest)) {

View file

@ -317,6 +317,7 @@ public class Bytestream extends IQ {
return port; return port;
} }
@Override
public String getElementName() { public String getElementName() {
return ELEMENTNAME; return ELEMENTNAME;
} }
@ -366,6 +367,7 @@ public class Bytestream extends IQ {
return JID; return JID;
} }
@Override
public String getElementName() { public String getElementName() {
return ELEMENTNAME; return ELEMENTNAME;
} }
@ -408,6 +410,7 @@ public class Bytestream extends IQ {
return target; return target;
} }
@Override
public String getElementName() { public String getElementName() {
return ELEMENTNAME; return ELEMENTNAME;
} }

View file

@ -65,6 +65,7 @@ import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -113,6 +114,7 @@ public final class EntityCapsManager extends Manager {
static { static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() { XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) { public void connectionCreated(XMPPConnection connection) {
getInstanceFor(connection); getInstanceFor(connection);
} }
@ -346,6 +348,7 @@ public final class EntityCapsManager extends Manager {
// XEP-0115 specifies that a client SHOULD include entity capabilities // XEP-0115 specifies that a client SHOULD include entity capabilities
// with every presence notification it sends. // with every presence notification it sends.
StanzaListener packetInterceptor = new StanzaListener() { StanzaListener packetInterceptor = new StanzaListener() {
@Override
public void processStanza(Stanza packet) { public void processStanza(Stanza packet) {
if (!entityCapsEnabled) { if (!entityCapsEnabled) {
// Be sure to not send stanzas with the caps extension if it's not enabled // Be sure to not send stanzas with the caps extension if it's not enabled
@ -403,7 +406,11 @@ public final class EntityCapsManager extends Manager {
* @param user * @param user
* the user (Full JID) * the user (Full JID)
*/ */
// TODO: Change parameter type to Jid in Smack 4.3.
@SuppressWarnings("CollectionIncompatibleType")
public static void removeUserCapsNode(String user) { public static void removeUserCapsNode(String user) {
// While JID_TO_NODEVER_CHACHE has the generic types <Jid, NodeVerHash>, it is ok to call remove with String
// arguments, since the same Jid and String representations would be equal and have the same hash code.
JID_TO_NODEVER_CACHE.remove(user); JID_TO_NODEVER_CACHE.remove(user);
} }
@ -658,6 +665,7 @@ public final class EntityCapsManager extends Manager {
// XEP-0128 data forms, sort the forms by the FORM_TYPE (i.e., // XEP-0128 data forms, sort the forms by the FORM_TYPE (i.e.,
// by the XML character data of the <value/> element). // by the XML character data of the <value/> element).
SortedSet<FormField> fs = new TreeSet<FormField>(new Comparator<FormField>() { SortedSet<FormField> fs = new TreeSet<FormField>(new Comparator<FormField>() {
@Override
public int compare(FormField f1, FormField f2) { public int compare(FormField f1, FormField f2) {
return f1.getVariable().compareTo(f2.getVariable()); return f1.getVariable().compareTo(f2.getVariable());
} }
@ -701,9 +709,16 @@ public final class EntityCapsManager extends Manager {
// encoded using Base64 as specified in Section 4 of RFC 4648 // encoded using Base64 as specified in Section 4 of RFC 4648
// (note: the Base64 output MUST NOT include whitespace and MUST set // (note: the Base64 output MUST NOT include whitespace and MUST set
// padding bits to zero). // padding bits to zero).
byte[] bytes;
try {
bytes = sb.toString().getBytes(StringUtils.UTF8);
}
catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
byte[] digest; byte[] digest;
synchronized(md) { synchronized(md) {
digest = md.digest(sb.toString().getBytes()); digest = md.digest(bytes);
} }
String version = Base64.encodeToString(digest); String version = Base64.encodeToString(digest);
return new CapsVersionAndHash(version, hash); return new CapsVersionAndHash(version, hash);

View file

@ -35,10 +35,12 @@ public class CapsExtension implements ExtensionElement {
this.hash = hash; this.hash = hash;
} }
@Override
public String getElementName() { public String getElementName() {
return ELEMENT; return ELEMENT;
} }
@Override
public String getNamespace() { public String getNamespace() {
return NAMESPACE; return NAMESPACE;
} }

View file

@ -27,6 +27,7 @@ import org.xmlpull.v1.XmlPullParserException;
public class CapsExtensionProvider extends ExtensionElementProvider<CapsExtension> { public class CapsExtensionProvider extends ExtensionElementProvider<CapsExtension> {
@Override
public CapsExtension parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException, public CapsExtension parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException,
SmackException { SmackException {
String hash = null; String hash = null;

View file

@ -119,6 +119,7 @@ public final class ChatStateManager extends Manager {
} }
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
@ -129,6 +130,7 @@ public final class ChatStateManager extends Manager {
} }
@Override
public int hashCode() { public int hashCode() {
return connection().hashCode(); return connection().hashCode();
} }
@ -164,12 +166,14 @@ public final class ChatStateManager extends Manager {
} }
} }
private class IncomingMessageInterceptor implements ChatManagerListener, ChatMessageListener { private static class IncomingMessageInterceptor implements ChatManagerListener, ChatMessageListener {
@Override
public void chatCreated(final org.jivesoftware.smack.chat.Chat chat, boolean createdLocally) { public void chatCreated(final org.jivesoftware.smack.chat.Chat chat, boolean createdLocally) {
chat.addMessageListener(this); chat.addMessageListener(this);
} }
@Override
public void processMessage(org.jivesoftware.smack.chat.Chat chat, Message message) { public void processMessage(org.jivesoftware.smack.chat.Chat chat, Message message) {
ExtensionElement extension = message.getExtension(NAMESPACE); ExtensionElement extension = message.getExtension(NAMESPACE);
if (extension == null) { if (extension == null) {

View file

@ -19,9 +19,7 @@ package org.jivesoftware.smackx.chatstates.packet;
import org.jivesoftware.smackx.chatstates.ChatState; import org.jivesoftware.smackx.chatstates.ChatState;
import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
import org.xmlpull.v1.XmlPullParser;
/** /**
* Represents a chat state which is an extension to message packets which is used to indicate * Represents a chat state which is an extension to message packets which is used to indicate
@ -66,18 +64,4 @@ public class ChatStateExtension implements ExtensionElement {
return xml; return xml;
} }
public static class Provider extends ExtensionElementProvider<ChatStateExtension> {
@Override
public ChatStateExtension parse(XmlPullParser parser, int initialDepth) {
ChatState state;
try {
state = ChatState.valueOf(parser.getName());
}
catch (Exception ex) {
state = ChatState.active;
}
return new ChatStateExtension(state);
}
}
} }

View file

@ -0,0 +1,34 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.chatstates.provider;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smackx.chatstates.ChatState;
import org.jivesoftware.smackx.chatstates.packet.ChatStateExtension;
import org.xmlpull.v1.XmlPullParser;
public class ChatStateExtensionProvider extends ExtensionElementProvider<ChatStateExtension> {
@Override
public ChatStateExtension parse(XmlPullParser parser, int initialDepth) throws Exception {
String chatStateString = parser.getName();
ChatState state = ChatState.valueOf(chatStateString);
return new ChatStateExtension(state);
}
}

View file

@ -0,0 +1,21 @@
/**
*
* Copyright 2017 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Provider classes for Chat State Notifications (XEP-0085).
*/
package org.jivesoftware.smackx.chatstates.provider;

Some files were not shown because too many files have changed in this diff Show more