View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.transport.xmpp;
8   
9   import org.mule.api.endpoint.ImmutableEndpoint;
10  import org.mule.api.transport.Connector;
11  import org.mule.transport.ConnectException;
12  import org.mule.util.UUID;
13  
14  import org.jivesoftware.smack.PacketCollector;
15  import org.jivesoftware.smack.SmackConfiguration;
16  import org.jivesoftware.smack.XMPPException;
17  import org.jivesoftware.smack.packet.Message;
18  import org.jivesoftware.smack.packet.XMPPError;
19  import org.jivesoftware.smackx.muc.DiscussionHistory;
20  import org.jivesoftware.smackx.muc.MultiUserChat;
21  
22  public class XmppMultiUserChatConversation extends AbstractXmppConversation
23  {
24      private MultiUserChat chat;
25      private String nickname;
26      private final Connector connector;
27      
28      public XmppMultiUserChatConversation(ImmutableEndpoint endpoint)
29      {
30          super(endpoint);
31          connector = endpoint.getConnector();
32          
33          Object nickValue = endpoint.getProperty(XmppConnector.XMPP_NICKNAME);
34          if (nickValue != null)
35          {
36              nickname = nickValue.toString();
37          }
38          else
39          {
40              nickname = UUID.getUUID().toString();
41          }
42      }
43  
44      @Override
45      protected void doConnect() throws ConnectException
46      {
47          chat = new MultiUserChat(connection, recipient);
48          joinChat();
49      }
50  
51      protected void joinChat() throws ConnectException
52      {
53          try
54          {
55              tryToJoinChat();
56          }
57          catch (XMPPException e)
58          {
59              if (roomDoesNotExist(e))
60              {
61                  createRoom();
62              }
63              else
64              {
65                  throw new ConnectException(e, connector);
66              }
67          }
68      }
69      
70      protected void tryToJoinChat() throws XMPPException
71      {
72          DiscussionHistory history = new DiscussionHistory();
73          history.setMaxStanzas(0);
74          
75          // use the same default value that the smack API uses internally
76          long joinTimeout = SmackConfiguration.getPacketReplyTimeout();
77          
78          chat.join(nickname, null, history, joinTimeout);
79          if (logger.isDebugEnabled())
80          {
81              logger.debug("joined groupchat '" + recipient + "'");
82          }
83      }
84      
85      protected boolean roomDoesNotExist(XMPPException exception)
86      {
87          XMPPError error = exception.getXMPPError();
88          if ((error.getCode() == 404) &&
89              error.getCondition().equals(XMPPError.Condition.recipient_unavailable.toString()))
90          {
91              return true;
92          }
93          return false;
94      }
95      
96      protected void createRoom() throws ConnectException
97      {
98          try
99          {
100             chat.create(nickname);
101             if (logger.isDebugEnabled())
102             {
103                 logger.debug("created and joined groupchat '" + recipient + "'");
104             }
105         }
106         catch (XMPPException e)
107         {
108             throw new ConnectException(e, connector);
109         }
110     }
111 
112     @Override
113     protected void doDisconnect()
114     {
115         chat.leave();
116     }
117     
118     /**
119      * This implementation returns <code>null</code> as we override {@link #receive()} and
120      * {@link #receive(long)}.
121      */
122     @Override
123     protected PacketCollector createPacketCollector()
124     {
125         return null;
126     }
127 
128     public void dispatch(Message message) throws XMPPException
129     {
130         message.setType(Message.Type.groupchat);
131         message.setTo(recipient);
132         
133         chat.sendMessage(message);
134     }
135 
136     @Override
137     public Message receive()
138     {
139         return chat.nextMessage();
140     }
141 
142     @Override
143     public Message receive(long timeout)
144     {
145         return chat.nextMessage(timeout);
146     }
147 }