use of org.jivesoftware.smack.packet.ErrorIQ in project Smack by igniterealtime.
the class AbstractXMPPConnection method invokeStanzaCollectorsAndNotifyRecvListeners.
/**
* Invoke {@link StanzaCollector#processStanza(Stanza)} for every
* StanzaCollector with the given packet. Also notify the receive listeners with a matching stanza(/packet) filter about the packet.
*
* @param packet the stanza(/packet) to notify the StanzaCollectors and receive listeners about.
*/
protected void invokeStanzaCollectorsAndNotifyRecvListeners(final Stanza packet) {
if (packet instanceof IQ) {
final IQ iq = (IQ) packet;
final IQ.Type type = iq.getType();
switch(type) {
case set:
case get:
final String key = XmppStringUtils.generateKey(iq.getChildElementName(), iq.getChildElementNamespace());
IQRequestHandler iqRequestHandler = null;
switch(type) {
case set:
synchronized (setIqRequestHandler) {
iqRequestHandler = setIqRequestHandler.get(key);
}
break;
case get:
synchronized (getIqRequestHandler) {
iqRequestHandler = getIqRequestHandler.get(key);
}
break;
default:
throw new IllegalStateException("Should only encounter IQ type 'get' or 'set'");
}
if (iqRequestHandler == null) {
if (!replyToUnkownIq) {
return;
}
// If the IQ stanza is of type "get" or "set" with no registered IQ request handler, then answer an
// IQ of type 'error' with condition 'service-unavailable'.
ErrorIQ errorIQ = IQ.createErrorResponse(iq, XMPPError.getBuilder((XMPPError.Condition.service_unavailable)));
try {
sendStanza(errorIQ);
} catch (InterruptedException | NotConnectedException e) {
LOGGER.log(Level.WARNING, "Exception while sending error IQ to unkown IQ request", e);
}
} else {
ExecutorService executorService = null;
switch(iqRequestHandler.getMode()) {
case sync:
executorService = singleThreadedExecutorService;
break;
case async:
executorService = cachedExecutorService;
break;
}
final IQRequestHandler finalIqRequestHandler = iqRequestHandler;
executorService.execute(new Runnable() {
@Override
public void run() {
IQ response = finalIqRequestHandler.handleIQRequest(iq);
if (response == null) {
// e.g. to avoid presence leaks.
return;
}
try {
sendStanza(response);
} catch (InterruptedException | NotConnectedException e) {
LOGGER.log(Level.WARNING, "Exception while sending response to IQ request", e);
}
}
});
// desired behavior.
return;
}
break;
default:
break;
}
}
// First handle the async recv listeners. Note that this code is very similar to what follows a few lines below,
// the only difference is that asyncRecvListeners is used here and that the packet listeners are started in
// their own thread.
final Collection<StanzaListener> listenersToNotify = new LinkedList<StanzaListener>();
synchronized (asyncRecvListeners) {
for (ListenerWrapper listenerWrapper : asyncRecvListeners.values()) {
if (listenerWrapper.filterMatches(packet)) {
listenersToNotify.add(listenerWrapper.getListener());
}
}
}
for (final StanzaListener listener : listenersToNotify) {
asyncGo(new Runnable() {
@Override
public void run() {
try {
listener.processStanza(packet);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Exception in async packet listener", e);
}
}
});
}
// Loop through all collectors and notify the appropriate ones.
for (StanzaCollector collector : collectors) {
collector.processStanza(packet);
}
// Notify the receive listeners interested in the packet
listenersToNotify.clear();
synchronized (syncRecvListeners) {
for (ListenerWrapper listenerWrapper : syncRecvListeners.values()) {
if (listenerWrapper.filterMatches(packet)) {
listenersToNotify.add(listenerWrapper.getListener());
}
}
}
// Decouple incoming stanza processing from listener invocation. Unlike async listeners, this uses a single
// threaded executor service and therefore keeps the order.
singleThreadedExecutorService.execute(new Runnable() {
@Override
public void run() {
for (StanzaListener listener : listenersToNotify) {
try {
listener.processStanza(packet);
} catch (NotConnectedException e) {
LOGGER.log(Level.WARNING, "Got not connected exception, aborting", e);
break;
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Exception in packet listener", e);
}
}
}
});
}
Aggregations