Search in sources :

Example 1 with IQRequestHandler

use of org.jivesoftware.smack.iqrequest.IQRequestHandler 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);
                }
            }
        }
    });
}
Also used : ErrorIQ(org.jivesoftware.smack.packet.ErrorIQ) NotConnectedException(org.jivesoftware.smack.SmackException.NotConnectedException) IQ(org.jivesoftware.smack.packet.IQ) ErrorIQ(org.jivesoftware.smack.packet.ErrorIQ) LinkedList(java.util.LinkedList) SecurityRequiredException(org.jivesoftware.smack.SmackException.SecurityRequiredException) XMPPErrorException(org.jivesoftware.smack.XMPPException.XMPPErrorException) AlreadyLoggedInException(org.jivesoftware.smack.SmackException.AlreadyLoggedInException) NotConnectedException(org.jivesoftware.smack.SmackException.NotConnectedException) StreamErrorException(org.jivesoftware.smack.XMPPException.StreamErrorException) NoResponseException(org.jivesoftware.smack.SmackException.NoResponseException) IOException(java.io.IOException) AlreadyConnectedException(org.jivesoftware.smack.SmackException.AlreadyConnectedException) SecurityRequiredByClientException(org.jivesoftware.smack.SmackException.SecurityRequiredByClientException) ResourceBindingNotOfferedException(org.jivesoftware.smack.SmackException.ResourceBindingNotOfferedException) IQRequestHandler(org.jivesoftware.smack.iqrequest.IQRequestHandler) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) ExecutorService(java.util.concurrent.ExecutorService)

Aggregations

IOException (java.io.IOException)1 LinkedList (java.util.LinkedList)1 ExecutorService (java.util.concurrent.ExecutorService)1 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)1 AlreadyConnectedException (org.jivesoftware.smack.SmackException.AlreadyConnectedException)1 AlreadyLoggedInException (org.jivesoftware.smack.SmackException.AlreadyLoggedInException)1 NoResponseException (org.jivesoftware.smack.SmackException.NoResponseException)1 NotConnectedException (org.jivesoftware.smack.SmackException.NotConnectedException)1 ResourceBindingNotOfferedException (org.jivesoftware.smack.SmackException.ResourceBindingNotOfferedException)1 SecurityRequiredByClientException (org.jivesoftware.smack.SmackException.SecurityRequiredByClientException)1 SecurityRequiredException (org.jivesoftware.smack.SmackException.SecurityRequiredException)1 StreamErrorException (org.jivesoftware.smack.XMPPException.StreamErrorException)1 XMPPErrorException (org.jivesoftware.smack.XMPPException.XMPPErrorException)1 IQRequestHandler (org.jivesoftware.smack.iqrequest.IQRequestHandler)1 ErrorIQ (org.jivesoftware.smack.packet.ErrorIQ)1 IQ (org.jivesoftware.smack.packet.IQ)1