001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.component.xmpp;
018    
019    import org.apache.camel.Exchange;
020    import org.apache.camel.Processor;
021    import org.apache.camel.impl.DefaultConsumer;
022    import org.apache.commons.logging.Log;
023    import org.apache.commons.logging.LogFactory;
024    import org.jivesoftware.smack.Chat;
025    import org.jivesoftware.smack.ChatManager;
026    import org.jivesoftware.smack.ChatManagerListener;
027    import org.jivesoftware.smack.MessageListener;
028    import org.jivesoftware.smack.PacketListener;
029    import org.jivesoftware.smack.SmackConfiguration;
030    import org.jivesoftware.smack.XMPPConnection;
031    import org.jivesoftware.smack.filter.AndFilter;
032    import org.jivesoftware.smack.filter.PacketTypeFilter;
033    import org.jivesoftware.smack.filter.ToContainsFilter;
034    import org.jivesoftware.smack.packet.Message;
035    import org.jivesoftware.smack.packet.Packet;
036    import org.jivesoftware.smack.packet.Presence;
037    import org.jivesoftware.smackx.muc.DiscussionHistory;
038    import org.jivesoftware.smackx.muc.MultiUserChat;
039    
040    /**
041     * A {@link org.apache.camel.Consumer Consumer} which listens to XMPP packets
042     *
043     * @version $Revision: 809453 $
044     */
045    public class XmppConsumer extends DefaultConsumer implements PacketListener, MessageListener, ChatManagerListener {
046        private static final transient Log LOG = LogFactory.getLog(XmppConsumer.class);
047        private final XmppEndpoint endpoint;
048        private MultiUserChat muc;
049        private Chat privateChat;
050        private ChatManager chatManager;
051        private XMPPConnection connection;
052    
053        public XmppConsumer(XmppEndpoint endpoint, Processor processor) {
054            super(endpoint, processor);
055            this.endpoint = endpoint;
056        }
057    
058        @Override
059        protected void doStart() throws Exception {
060            connection = endpoint.createConnection();
061            chatManager = connection.getChatManager();
062            chatManager.addChatListener(this);
063    
064            if (endpoint.getRoom() == null) {
065                privateChat = chatManager.getThreadChat(endpoint.getChatId());
066    
067                if (privateChat != null) {
068                    LOG.debug("Adding listener to existing chat opened to " + privateChat.getParticipant());
069                    privateChat.addMessageListener(this);
070                } else {                
071                    privateChat = connection.getChatManager().createChat(endpoint.getParticipant(), endpoint.getChatId(), this);
072                    LOG.debug("Opening private chat to " + privateChat.getParticipant());
073                }
074            } else {
075                // add the presence packet listener to the connection so we only get packets that concers us
076                // we must add the listener before creating the muc
077                final ToContainsFilter toFilter = new ToContainsFilter(endpoint.getParticipant());
078                final AndFilter packetFilter = new AndFilter(new PacketTypeFilter(Presence.class), toFilter);
079                connection.addPacketListener(this, packetFilter);
080    
081                muc = new MultiUserChat(connection, endpoint.resolveRoom(connection));
082                muc.addMessageListener(this);
083                DiscussionHistory history = new DiscussionHistory();
084                history.setMaxChars(0); // we do not want any historical messages
085    
086                muc.join(endpoint.getNickname(), null, history, SmackConfiguration.getPacketReplyTimeout());
087                if (LOG.isInfoEnabled()) {
088                    LOG.info("Joined room: " + muc.getRoom() + " as: " + endpoint.getNickname());
089                }
090            }
091    
092            super.doStart();
093        }
094    
095        @Override
096        protected void doStop() throws Exception {
097            super.doStop();
098            if (muc != null) {
099                if (LOG.isInfoEnabled()) {
100                    LOG.info("Leaving room: " + muc.getRoom());
101                }
102                muc.removeMessageListener(this);
103                muc.leave();
104                muc = null;
105            }
106            //the endpoint will clean up the connection
107        }
108    
109        public void chatCreated(Chat chat, boolean createdLocally) {
110            if (!createdLocally) {
111                LOG.debug("Accepting incoming chat session from " + chat.getParticipant());
112                chat.addMessageListener(this);
113            }
114        }
115    
116        public void processPacket(Packet packet) {
117            if (packet instanceof Message) {
118                processMessage(null, (Message)packet);
119            }
120        }
121    
122        public void processMessage(Chat chat, Message message) {
123            if (LOG.isDebugEnabled()) {
124                LOG.debug("Received XMPP message for " + endpoint.getUser() + " from " + endpoint.getParticipant() + " : " + message.getBody());
125            }
126    
127            Exchange exchange = endpoint.createExchange(message);
128            try {
129                getProcessor().process(exchange);
130            } catch (Exception e) {
131                exchange.setException(e);
132            }
133        }
134    }