1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-23 20:42:06 +01:00

Merge remote-tracking branch 'upstream/master' into jingle3

This commit is contained in:
vanitasvitae 2017-08-13 17:22:41 +02:00
commit 5895ca8b07
11 changed files with 355 additions and 183 deletions

View file

@ -67,8 +67,8 @@ Donate
If you find Smack useful and feel like donating, then you can use one of the following systems: If you find Smack useful and feel like donating, then you can use one of the following systems:
- Donate via Bitcoin: 1LiU78z3498wu3jwRPKbvovKAHjTcpVbuK
- [Donate via Flattr](https://flattr.com/thing/3480125) - [Donate via Flattr](https://flattr.com/thing/3480125)
- Donate via Bitcoin: 1D4k11bsPxRB6rS51fxDty8QYfRVUt5JMB
Ignite Realtime Ignite Realtime
=============== ===============

View file

@ -49,6 +49,7 @@ import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.SmackException.ResourceBindingNotOfferedException; import org.jivesoftware.smack.SmackException.ResourceBindingNotOfferedException;
import org.jivesoftware.smack.SmackException.SecurityRequiredByClientException; import org.jivesoftware.smack.SmackException.SecurityRequiredByClientException;
import org.jivesoftware.smack.SmackException.SecurityRequiredException; import org.jivesoftware.smack.SmackException.SecurityRequiredException;
import org.jivesoftware.smack.SmackFuture.InternalSmackFuture;
import org.jivesoftware.smack.XMPPException.StreamErrorException; import org.jivesoftware.smack.XMPPException.StreamErrorException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.compress.packet.Compress; import org.jivesoftware.smack.compress.packet.Compress;
@ -323,12 +324,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
return config; return config;
} }
@SuppressWarnings("deprecation")
@Override
public DomainBareJid getServiceName() {
return getXMPPServiceDomain();
}
@Override @Override
public DomainBareJid getXMPPServiceDomain() { public DomainBareJid getXMPPServiceDomain() {
if (xmppServiceDomain != null) { if (xmppServiceDomain != null) {
@ -665,12 +660,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
} }
@Deprecated
@Override
public void sendPacket(Stanza packet) throws NotConnectedException, InterruptedException {
sendStanza(packet);
}
@Override @Override
public void sendStanza(Stanza stanza) throws NotConnectedException, InterruptedException { public void sendStanza(Stanza stanza) throws NotConnectedException, InterruptedException {
Objects.requireNonNull(stanza, "Stanza must not be null"); Objects.requireNonNull(stanza, "Stanza must not be null");
@ -803,18 +792,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
collectors.remove(collector); collectors.remove(collector);
} }
@Override
@Deprecated
public void addPacketListener(StanzaListener packetListener, StanzaFilter packetFilter) {
addAsyncStanzaListener(packetListener, packetFilter);
}
@Override
@Deprecated
public boolean removePacketListener(StanzaListener packetListener) {
return removeAsyncStanzaListener(packetListener);
}
@Override @Override
public void addSyncStanzaListener(StanzaListener packetListener, StanzaFilter packetFilter) { public void addSyncStanzaListener(StanzaListener packetListener, StanzaFilter packetFilter) {
if (packetListener == null) { if (packetListener == null) {
@ -976,18 +953,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} }
} }
@SuppressWarnings("deprecation")
@Override
public long getPacketReplyTimeout() {
return getReplyTimeout();
}
@SuppressWarnings("deprecation")
@Override
public void setPacketReplyTimeout(long timeout) {
setReplyTimeout(timeout);
}
@Override @Override
public long getReplyTimeout() { public long getReplyTimeout() {
return replyTimeout; return replyTimeout;
@ -1525,6 +1490,87 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
getReplyTimeout()); getReplyTimeout());
} }
@Override
public SmackFuture<IQ, Exception> sendIqRequestAsync(IQ request) {
return sendIqRequestAsync(request, getReplyTimeout());
}
@Override
public SmackFuture<IQ, Exception> sendIqRequestAsync(IQ request, long timeout) {
StanzaFilter replyFilter = new IQReplyFilter(request, this);
return sendAsync(request, replyFilter, timeout);
}
@Override
public <S extends Stanza> SmackFuture<S, Exception> sendAsync(S stanza, final StanzaFilter replyFilter) {
return sendAsync(stanza, replyFilter, getReplyTimeout());
}
@SuppressWarnings("FutureReturnValueIgnored")
@Override
public <S extends Stanza> SmackFuture<S, Exception> sendAsync(S stanza, final StanzaFilter replyFilter, long timeout) {
Objects.requireNonNull(stanza, "stanza must not be null");
// While Smack allows to add PacketListeners with a PacketFilter value of 'null', we
// disallow it here in the async API as it makes no sense
Objects.requireNonNull(replyFilter, "replyFilter must not be null");
final InternalSmackFuture<S, Exception> future = new InternalSmackFuture<>();
final StanzaListener stanzaListener = new StanzaListener() {
@Override
public void processStanza(Stanza stanza) 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 {
XMPPErrorException.ifHasErrorThenThrow(stanza);
@SuppressWarnings("unchecked")
S s = (S) stanza;
future.setResult(s);
}
catch (XMPPErrorException exception) {
future.setException(exception);
}
}
};
removeCallbacksService.schedule(new Runnable() {
@Override
public void run() {
boolean removed = removeAsyncStanzaListener(stanzaListener);
if (!removed) {
// We lost a race against the stanza listener, he already removed itself because he received a
// reply. There is nothing more to do here.
return;
}
// If the packetListener got removed, then it was never run and
// we never received a response, inform the exception callback
Exception exception;
if (!isConnected()) {
// If the connection is no longer connected, throw a not connected exception.
exception = new NotConnectedException(AbstractXMPPConnection.this, replyFilter);
}
else {
exception = NoResponseException.newWith(AbstractXMPPConnection.this, replyFilter);
}
future.setException(exception);
}
}, timeout, TimeUnit.MILLISECONDS);
addAsyncStanzaListener(stanzaListener, replyFilter);
try {
sendStanza(stanza);
}
catch (NotConnectedException | InterruptedException exception) {
future.setException(exception);
}
return future;
}
@SuppressWarnings("FutureReturnValueIgnored") @SuppressWarnings("FutureReturnValueIgnored")
@Override @Override
public void sendStanzaWithResponseCallback(Stanza stanza, final StanzaFilter replyFilter, public void sendStanzaWithResponseCallback(Stanza stanza, final StanzaFilter replyFilter,

View file

@ -16,25 +16,34 @@
*/ */
package org.jivesoftware.smack; package org.jivesoftware.smack;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.util.CallbackRecipient;
import org.jivesoftware.smack.util.ExceptionCallback;
import org.jivesoftware.smack.util.SuccessCallback;
public abstract class SmackFuture<V> implements Future<V> { public abstract class SmackFuture<V, E extends Exception> implements Future<V>, CallbackRecipient<V, E> {
private boolean cancelled; private boolean cancelled;
private V result; protected V result;
protected Exception exception; protected E exception;
private SuccessCallback<V> successCallback; private SuccessCallback<V> successCallback;
private ExceptionCallback exceptionCallback; private ExceptionCallback<E> exceptionCallback;
@Override @Override
public synchronized final boolean cancel(boolean mayInterruptIfRunning) { public synchronized final boolean cancel(boolean mayInterruptIfRunning) {
@ -43,6 +52,11 @@ public abstract class SmackFuture<V> implements Future<V> {
} }
cancelled = true; cancelled = true;
if (mayInterruptIfRunning) {
notifyAll();
}
return true; return true;
} }
@ -56,37 +70,62 @@ public abstract class SmackFuture<V> implements Future<V> {
return result != null; return result != null;
} }
public void onSuccessOrError(SuccessCallback<V> successCallback, ExceptionCallback exceptionCallback) { @Override
public CallbackRecipient<V, E> onSuccess(SuccessCallback<V> successCallback) {
this.successCallback = successCallback; this.successCallback = successCallback;
this.exceptionCallback = exceptionCallback;
maybeInvokeCallbacks(); maybeInvokeCallbacks();
return this;
} }
public void onSuccess(SuccessCallback<V> successCallback) { @Override
onSuccessOrError(successCallback, null); public CallbackRecipient<V, E> onError(ExceptionCallback<E> exceptionCallback) {
this.exceptionCallback = exceptionCallback;
maybeInvokeCallbacks();
return this;
} }
public void onError(ExceptionCallback exceptionCallback) { private final V getOrThrowExecutionException() throws ExecutionException {
onSuccessOrError(null, exceptionCallback); assert (result != null || exception != null || cancelled);
}
private final V getResultOrThrow() throws ExecutionException {
assert (result != null || exception != null);
if (result != null) { if (result != null) {
return result; return result;
} }
if (exception != null) {
throw new ExecutionException(exception); throw new ExecutionException(exception);
} }
assert (cancelled);
throw new CancellationException();
}
@Override @Override
public synchronized final V get() throws InterruptedException, ExecutionException { public synchronized final V get() throws InterruptedException, ExecutionException {
while (result == null && exception == null) { while (result == null && exception == null && !cancelled) {
wait(); wait();
} }
return getResultOrThrow(); return getOrThrowExecutionException();
}
public synchronized final V getOrThrow() throws E {
while (result == null && exception == null && !cancelled) {
try {
wait();
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if (exception != null) {
throw exception;
}
if (cancelled) {
throw new CancellationException();
}
assert result != null;
return result;
} }
@Override @Override
@ -100,45 +139,101 @@ public abstract class SmackFuture<V> implements Future<V> {
} }
} }
if (cancelled) {
throw new CancellationException();
}
if (result == null || exception == null) { if (result == null || exception == null) {
throw new TimeoutException(); throw new TimeoutException();
} }
return getResultOrThrow(); return getOrThrowExecutionException();
} }
private static final ExecutorService EXECUTOR_SERVICE;
static {
ThreadFactory threadFactory = new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setDaemon(true);
thread.setName("SmackFuture Thread");
return thread;
}
};
BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(128);
RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
r.run();
}
};
int cores = Runtime.getRuntime().availableProcessors();
int maximumPoolSize = cores <= 4 ? 2 : cores;
ExecutorService executorService = new ThreadPoolExecutor(0, maximumPoolSize, 60L, TimeUnit.SECONDS,
blockingQueue, threadFactory, rejectedExecutionHandler);
EXECUTOR_SERVICE = executorService;
}
@SuppressWarnings("FutureReturnValueIgnored")
protected final synchronized void maybeInvokeCallbacks() { protected final synchronized void maybeInvokeCallbacks() {
if (cancelled) {
return;
}
if (result != null && successCallback != null) { if (result != null && successCallback != null) {
EXECUTOR_SERVICE.submit(new Runnable() {
@Override
public void run() {
successCallback.onSuccess(result); successCallback.onSuccess(result);
} else if (exception != null && exceptionCallback != null) { }
});
}
else if (exception != null && exceptionCallback != null) {
EXECUTOR_SERVICE.submit(new Runnable() {
@Override
public void run() {
exceptionCallback.processException(exception); exceptionCallback.processException(exception);
} }
});
}
} }
/** public static class InternalSmackFuture<V, E extends Exception> extends SmackFuture<V, E> {
* This method checks if the given exception is <b>not</b> fatal. If this method returns <code>false</code>, then public final synchronized void setResult(V result) {
* the future will automatically set the given exception as failure reason and notify potential waiting threads.
*
* @param exception the exception to check.
* @return <code>true</code> if the exception is not fatal, <code>false</code> otherwise.
*/
protected abstract boolean isNonFatalException(Exception exception);
protected abstract void handleStanza(Stanza stanza) throws NotConnectedException, InterruptedException;
protected final void setResult(V result) {
assert (Thread.holdsLock(this));
this.result = result; this.result = result;
this.notifyAll(); this.notifyAll();
maybeInvokeCallbacks(); maybeInvokeCallbacks();
} }
public static abstract class InternalSmackFuture<V> extends SmackFuture<V> implements StanzaListener, ExceptionCallback { public final synchronized void setException(E exception) {
this.exception = exception;
this.notifyAll();
maybeInvokeCallbacks();
}
}
public static abstract class InternalProcessStanzaSmackFuture<V, E extends Exception> extends InternalSmackFuture<V, E>
implements StanzaListener, ExceptionCallback<E> {
/**
* This method checks if the given exception is <b>not</b> fatal. If this method returns <code>false</code>,
* then the future will automatically set the given exception as failure reason and notify potential waiting
* threads.
*
* @param exception the exception to check.
* @return <code>true</code> if the exception is not fatal, <code>false</code> otherwise.
*/
protected abstract boolean isNonFatalException(E exception);
protected abstract void handleStanza(Stanza stanza);
@Override @Override
public synchronized final void processException(Exception exception) { public synchronized final void processException(E exception) {
if (!isNonFatalException(exception)) { if (!isNonFatalException(exception)) {
this.exception = exception; this.exception = exception;
this.notifyAll(); this.notifyAll();
@ -151,20 +246,29 @@ public abstract class SmackFuture<V> implements Future<V> {
* Wrapper method for {@link #handleStanza(Stanza)}. Note that this method is <code>synchronized</code>. * Wrapper method for {@link #handleStanza(Stanza)}. Note that this method is <code>synchronized</code>.
*/ */
@Override @Override
public synchronized final void processStanza(Stanza stanza) throws NotConnectedException, InterruptedException { public synchronized final void processStanza(Stanza stanza) {
handleStanza(stanza); handleStanza(stanza);
} }
} }
/** /**
* A simple version of InternalSmackFuture which implements {@link #isNonFatalException(Exception)} as always returning <code>false</code> method. * A simple version of InternalSmackFuture which implements isNonFatalException(E) as always returning
* <code>false</code> method.
* *
* @param <V> * @param <V>
*/ */
public static abstract class SimpleInternalSmackFuture<V> extends InternalSmackFuture<V> { public static abstract class SimpleInternalProcessStanzaSmackFuture<V, E extends Exception>
extends InternalProcessStanzaSmackFuture<V, E> {
@Override @Override
protected boolean isNonFatalException(Exception exception) { protected boolean isNonFatalException(E exception) {
return false; return false;
} }
} }
public static <V, E extends Exception> SmackFuture<V, E> from(V result) {
InternalSmackFuture<V, E> future = new InternalSmackFuture<>();
future.setResult(result);
return future;
}
} }

View file

@ -72,18 +72,6 @@ import org.jxmpp.jid.EntityFullJid;
*/ */
public interface XMPPConnection { public interface XMPPConnection {
/**
* Returns the name of the service provided by the XMPP server for this connection.
* This is also called XMPP domain of the connected server. After
* authenticating with the server the returned value may be different.
*
* @return the name of the service provided by the XMPP server.
// TODO remove this once the java bugs are fixed, causing a warning
// * @deprecated use {@link #getXMPPServiceDomain()} instead.
*/
// @Deprecated
public DomainBareJid getServiceName();
/** /**
* Returns the XMPP Domain of the service provided by the XMPP server and used for this connection. After * Returns the XMPP Domain of the service provided by the XMPP server and used for this connection. After
* authenticating with the server the returned value may be different. * authenticating with the server the returned value may be different.
@ -165,18 +153,6 @@ public interface XMPPConnection {
*/ */
public boolean isUsingCompression(); public boolean isUsingCompression();
/**
* Sends the specified stanza(/packet) to the server.
*
* @param packet the stanza(/packet) to send.
* @throws NotConnectedException
* @throws InterruptedException
* @deprecated use {@link #sendStanza(Stanza)} instead.
*/
// TODO Remove in 4.3.
@Deprecated
public void sendPacket(Stanza packet) throws NotConnectedException, InterruptedException;
/** /**
* Sends the specified stanza to the server. * Sends the specified stanza to the server.
* *
@ -281,35 +257,6 @@ public interface XMPPConnection {
*/ */
public void removeStanzaCollector(StanzaCollector collector); public void removeStanzaCollector(StanzaCollector collector);
/**
* Registers a stanza(/packet) listener with this connection.
* <p>
* This method has been deprecated. It is important to differentiate between using an asynchronous stanza(/packet) listener
* (preferred where possible) and a synchronous stanza(/packet) lister. Refer
* {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)} and
* {@link #addSyncStanzaListener(StanzaListener, StanzaFilter)} for more information.
* </p>
*
* @param packetListener the stanza(/packet) listener to notify of new received packets.
* @param packetFilter the stanza(/packet) filter to use.
* @deprecated use {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)} or
* {@link #addSyncStanzaListener(StanzaListener, StanzaFilter)}.
*/
// TODO Remove in 4.3.
@Deprecated
public void addPacketListener(StanzaListener packetListener, StanzaFilter packetFilter);
/**
* Removes a stanza(/packet) listener for received packets from this connection.
*
* @param packetListener the stanza(/packet) listener to remove.
* @return true if the stanza(/packet) listener was removed
* @deprecated use {@link #removeAsyncStanzaListener(StanzaListener)} or {@link #removeSyncStanzaListener(StanzaListener)}.
*/
// TODO Remove in 4.3.
@Deprecated
public boolean removePacketListener(StanzaListener packetListener);
/** /**
* Registers a <b>synchronous</b> stanza(/packet) listener with this connection. A stanza(/packet) listener will be invoked only when * Registers a <b>synchronous</b> stanza(/packet) listener with this connection. A stanza(/packet) listener will be invoked only when
* an incoming stanza(/packet) is received. A stanza(/packet) filter determines which packets will be delivered to the listener. If * an incoming stanza(/packet) is received. A stanza(/packet) filter determines which packets will be delivered to the listener. If
@ -405,28 +352,6 @@ public interface XMPPConnection {
*/ */
public void removePacketInterceptor(StanzaListener packetInterceptor); public void removePacketInterceptor(StanzaListener packetInterceptor);
/**
* Returns the current value of the reply timeout in milliseconds for request for this
* XMPPConnection instance.
*
* @return the stanza(/packet) reply timeout in milliseconds
* @deprecated use {@link #getReplyTimeout()} instead.
*/
@Deprecated
// TODO Remove in Smack 4.3
public long getPacketReplyTimeout();
/**
* Set the stanza(/packet) reply timeout in milliseconds. In most cases, Smack will throw a
* {@link NoResponseException} if no reply to a request was received within the timeout period.
*
* @param timeout the stanza(/packet) reply timeout in milliseconds
* @deprecated use {@link #setReplyTimeout(long)} instead.
*/
@Deprecated
// TODO Remove in Smack 4.3
public void setPacketReplyTimeout(long timeout);
/** /**
* Returns the current value of the reply timeout in milliseconds for request for this * Returns the current value of the reply timeout in milliseconds for request for this
* XMPPConnection instance. * XMPPConnection instance.
@ -503,6 +428,43 @@ public interface XMPPConnection {
*/ */
public boolean hasFeature(String element, String namespace); public boolean hasFeature(String element, String namespace);
/**
* Send an IQ request asynchronously. The connection's default reply timeout will be used.
*
* @param request the IQ request to send.
* @return a SmackFuture for the response.
*/
public SmackFuture<IQ, Exception> sendIqRequestAsync(IQ request);
/**
* Send an IQ request asynchronously.
*
* @param request the IQ request to send.
* @param timeout the reply timeout in milliseconds.
* @return a SmackFuture for the response.
*/
public SmackFuture<IQ, Exception> sendIqRequestAsync(IQ request, long timeout);
/**
* Send a stanza asynchronously, waiting for exactly one response stanza using the given reply filter. The connection's default reply timeout will be used.
*
* @param stanza the stanza to send.
* @param replyFilter the filter used for the response stanza.
* @return a SmackFuture for the response.
*/
public <S extends Stanza> SmackFuture<S, Exception> sendAsync(S stanza, StanzaFilter replyFilter);
/**
* Send a stanza asynchronously, waiting for exactly one response stanza using the given reply filter.
*
* @param stanza the stanza to send.
* @param replyFilter the filter used for the response stanza.
* @param timeout the reply timeout in milliseconds.
* @return a SmackFuture for the response.
*/
public <S extends Stanza> SmackFuture<S, Exception> sendAsync(S stanza, StanzaFilter replyFilter, long timeout);
/** /**
* Send a stanza and wait asynchronously for a response by using <code>replyFilter</code>. * Send a stanza and wait asynchronously for a response by using <code>replyFilter</code>.
* <p> * <p>
@ -517,6 +479,7 @@ public interface XMPPConnection {
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
// TODO: Mark deprecated in favor of the new SmackFuture based async API.
public void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter, public void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter,
StanzaListener callback) throws NotConnectedException, InterruptedException; StanzaListener callback) throws NotConnectedException, InterruptedException;
@ -535,6 +498,7 @@ public interface XMPPConnection {
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
// TODO: Mark deprecated in favor of the new SmackFuture based async API. And do not forget to mark smack.ExceptionCallback deprecated too.
public void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter, StanzaListener callback, public void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter, StanzaListener callback,
ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException; ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException;
@ -554,6 +518,7 @@ public interface XMPPConnection {
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
// TODO: Mark deprecated in favor of the new SmackFuture based async API.
public void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter, public void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter,
final StanzaListener callback, final ExceptionCallback exceptionCallback, final StanzaListener callback, final ExceptionCallback exceptionCallback,
long timeout) throws NotConnectedException, InterruptedException; long timeout) throws NotConnectedException, InterruptedException;
@ -568,6 +533,7 @@ public interface XMPPConnection {
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
// TODO: Mark deprecated in favor of the new SmackFuture based async API.
public void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback) throws NotConnectedException, InterruptedException; public void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback) throws NotConnectedException, InterruptedException;
/** /**
@ -584,6 +550,7 @@ public interface XMPPConnection {
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
// TODO: Mark deprecated in favor of the new SmackFuture based async API.
public void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback, public void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback,
ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException; ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException;
@ -602,6 +569,7 @@ public interface XMPPConnection {
* @throws NotConnectedException * @throws NotConnectedException
* @throws InterruptedException * @throws InterruptedException
*/ */
// TODO: Mark deprecated in favor of the new SmackFuture based async API.
public void sendIqWithResponseCallback(IQ iqRequest, final StanzaListener callback, public void sendIqWithResponseCallback(IQ iqRequest, final StanzaListener callback,
final ExceptionCallback exceptionCallback, long timeout) final ExceptionCallback exceptionCallback, long timeout)
throws NotConnectedException, InterruptedException; throws NotConnectedException, InterruptedException;

View file

@ -0,0 +1,25 @@
/**
*
* 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.util;
public interface CallbackRecipient<V,E> {
CallbackRecipient<V, E> onSuccess(SuccessCallback<V> successCallback);
CallbackRecipient<V, E> onError(ExceptionCallback<E> exceptionCallback);
}

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.smack.util;
public interface ExceptionCallback<E> {
public void processException(E exception);
}

View file

@ -14,7 +14,7 @@
* 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; package org.jivesoftware.smack.util;
public interface SuccessCallback<T> { public interface SuccessCallback<T> {

View file

@ -22,9 +22,8 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackFuture.InternalProcessStanzaSmackFuture;
import org.jivesoftware.smack.SmackFuture.InternalSmackFuture; import org.jivesoftware.smack.SmackFuture.SimpleInternalProcessStanzaSmackFuture;
import org.jivesoftware.smack.SmackFuture.SimpleInternalSmackFuture;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.junit.Test; import org.junit.Test;
@ -32,10 +31,10 @@ import org.junit.Test;
public class SmackFutureTest { public class SmackFutureTest {
@Test @Test
public void simpleSmackFutureSuccessTest() throws NotConnectedException, InterruptedException, ExecutionException { public void simpleSmackFutureSuccessTest() throws InterruptedException, ExecutionException {
InternalSmackFuture<Boolean> future = new SimpleInternalSmackFuture<Boolean>() { InternalProcessStanzaSmackFuture<Boolean, Exception> future = new SimpleInternalProcessStanzaSmackFuture<Boolean, Exception>() {
@Override @Override
protected void handleStanza(Stanza stanza) throws NotConnectedException, InterruptedException { protected void handleStanza(Stanza stanza) {
setResult(true); setResult(true);
} }
}; };
@ -47,9 +46,9 @@ public class SmackFutureTest {
@Test(expected = TimeoutException.class) @Test(expected = TimeoutException.class)
public void simpleSmackFutureTimeoutTest() throws InterruptedException, ExecutionException, TimeoutException { public void simpleSmackFutureTimeoutTest() throws InterruptedException, ExecutionException, TimeoutException {
InternalSmackFuture<Boolean> future = new SimpleInternalSmackFuture<Boolean>() { InternalProcessStanzaSmackFuture<Boolean, Exception> future = new SimpleInternalProcessStanzaSmackFuture<Boolean, Exception>() {
@Override @Override
protected void handleStanza(Stanza stanza) throws NotConnectedException, InterruptedException { protected void handleStanza(Stanza stanza) {
} }
}; };

View file

@ -62,7 +62,7 @@ public class ServiceAdministrationManager extends Manager {
} }
public RemoteCommand addUser() { public RemoteCommand addUser() {
return addUser(connection().getServiceName()); return addUser(connection().getXMPPServiceDomain());
} }
public RemoteCommand addUser(Jid service) { public RemoteCommand addUser(Jid service) {
@ -90,7 +90,7 @@ public class ServiceAdministrationManager extends Manager {
} }
public RemoteCommand deleteUser() { public RemoteCommand deleteUser() {
return deleteUser(connection().getServiceName()); return deleteUser(connection().getXMPPServiceDomain());
} }
public RemoteCommand deleteUser(Jid service) { public RemoteCommand deleteUser(Jid service) {

View file

@ -33,9 +33,8 @@ 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.SmackException.NotLoggedInException;
import org.jivesoftware.smack.SmackFuture; import org.jivesoftware.smack.SmackFuture;
import org.jivesoftware.smack.SmackFuture.InternalSmackFuture; import org.jivesoftware.smack.SmackFuture.InternalProcessStanzaSmackFuture;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPConnectionRegistry; import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.XMPPException.XMPPErrorException;
@ -45,7 +44,9 @@ import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.IQ.Type; import org.jivesoftware.smack.packet.IQ.Type;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.XMPPError; import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.util.ExceptionCallback;
import org.jivesoftware.smack.util.SmackExecutorThreadFactory; import org.jivesoftware.smack.util.SmackExecutorThreadFactory;
import org.jivesoftware.smack.util.SuccessCallback;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.ping.packet.Ping; import org.jivesoftware.smackx.ping.packet.Ping;
@ -151,7 +152,7 @@ public final class PingManager extends Manager {
private boolean isValidErrorPong(Jid destinationJid, XMPPErrorException xmppErrorException) { private boolean isValidErrorPong(Jid destinationJid, XMPPErrorException xmppErrorException) {
// If it is an error error response and the destination was our own service, then this must mean that the // If it is an error error response and the destination was our own service, then this must mean that the
// service responded, i.e. is up and pingable. // service responded, i.e. is up and pingable.
if (destinationJid.equals(connection().getServiceName())) { if (destinationJid.equals(connection().getXMPPServiceDomain())) {
return true; return true;
} }
@ -178,14 +179,14 @@ public final class PingManager extends Manager {
return type == XMPPError.Type.CANCEL && condition == XMPPError.Condition.feature_not_implemented; return type == XMPPError.Type.CANCEL && condition == XMPPError.Condition.feature_not_implemented;
} }
public SmackFuture<Boolean> pingAsync(Jid jid) { public SmackFuture<Boolean, Exception> pingAsync(Jid jid) {
return pingAsync(jid, connection().getReplyTimeout()); return pingAsync(jid, connection().getReplyTimeout());
} }
public SmackFuture<Boolean> pingAsync(final Jid jid, long pongTimeout) { public SmackFuture<Boolean, Exception> pingAsync(final Jid jid, long pongTimeout) {
final InternalSmackFuture<Boolean> future = new InternalSmackFuture<Boolean>() { final InternalProcessStanzaSmackFuture<Boolean, Exception> future = new InternalProcessStanzaSmackFuture<Boolean, Exception>() {
@Override @Override
public void handleStanza(Stanza packet) throws NotConnectedException, InterruptedException { public void handleStanza(Stanza packet) {
setResult(true); setResult(true);
} }
@Override @Override
@ -202,13 +203,19 @@ public final class PingManager extends Manager {
}; };
Ping ping = new Ping(jid); Ping ping = new Ping(jid);
try { connection().sendIqRequestAsync(ping, pongTimeout)
XMPPConnection connection = getAuthenticatedConnectionOrThrow(); .onSuccess(new SuccessCallback<IQ>() {
connection.sendIqWithResponseCallback(ping, future, future, pongTimeout); @Override
public void onSuccess(IQ result) {
future.processStanza(result);
} }
catch (NotLoggedInException | NotConnectedException | InterruptedException e) { })
future.processException(e); .onError(new ExceptionCallback<Exception>() {
@Override
public void processException(Exception exception) {
future.processException(exception);
} }
});
return future; return future;
} }

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2015-2016 Florian Schmaus * Copyright 2015-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.
@ -74,7 +74,7 @@ public class IntTestUtil {
ServiceAdministrationManager adminManager = ServiceAdministrationManager.getInstanceFor(connection); ServiceAdministrationManager adminManager = ServiceAdministrationManager.getInstanceFor(connection);
EntityBareJid userJid = JidCreate.entityBareFrom(Localpart.from(username), connection.getServiceName()); EntityBareJid userJid = JidCreate.entityBareFrom(Localpart.from(username), connection.getXMPPServiceDomain());
adminManager.addUser(userJid, password); adminManager.addUser(userJid, password);
connection.disconnect(); connection.disconnect();