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.util.UUID;
10  
11  import java.util.ArrayList;
12  import java.util.HashMap;
13  import java.util.List;
14  import java.util.Map;
15  
16  import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch;
17  
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  import org.jivesoftware.smack.Chat;
21  import org.jivesoftware.smack.ConnectionConfiguration;
22  import org.jivesoftware.smack.MessageListener;
23  import org.jivesoftware.smack.PacketCollector;
24  import org.jivesoftware.smack.PacketListener;
25  import org.jivesoftware.smack.XMPPConnection;
26  import org.jivesoftware.smack.XMPPException;
27  import org.jivesoftware.smack.filter.MessageTypeFilter;
28  import org.jivesoftware.smack.filter.OrFilter;
29  import org.jivesoftware.smack.filter.PacketFilter;
30  import org.jivesoftware.smack.packet.Message;
31  import org.jivesoftware.smack.packet.Packet;
32  import org.jivesoftware.smackx.muc.MultiUserChat;
33  
34  public class JabberClient implements PacketListener, MessageListener
35  {
36      private static Log logger = LogFactory.getLog(JabberClient.class);
37      
38      private String host;
39      private String user;
40      private String password;
41      private boolean synchronous = true;
42      private String replyPayload = "Reply";
43      private boolean autoreply = false;
44  
45      private XMPPConnection connection;
46      private Map<String, Chat> chats;
47      private MultiUserChat groupchat = null;
48      private List<Message> replies;
49      private PacketCollector packetCollector = null;
50      private CountDownLatch messageLatch = null;
51  
52      public JabberClient(String host, String user, String password) throws Exception
53      {
54          super();
55          this.host = host;
56          
57          int index = user.indexOf("@");
58          if (index > -1)
59          {
60              this.user = user.substring(0, index);
61          }
62          else
63          {
64              this.user = user;
65          }
66          
67          this.password = password;        
68  
69          replies = new ArrayList<Message>();
70          chats = new HashMap<String, Chat>();
71      }
72  
73      public void connect(CountDownLatch latch) throws Exception
74      {
75          ConnectionConfiguration connectionConfig = new ConnectionConfiguration(host);
76          // no roster required
77          connectionConfig.setRosterLoadedAtLogin(false);
78          
79          connection = new XMPPConnection(connectionConfig);
80          connection.connect();
81          if (logger.isDebugEnabled())
82          {
83              logger.debug("connected to " + host);
84          }
85          
86          connection.login(user, password);
87          if (logger.isDebugEnabled())
88          {
89              logger.debug("logged into " + host + " as " + user);
90          }
91  
92          registerListener();
93          
94          // notify the caller that we're finished connecting
95          latch.countDown();
96      }
97  
98      private void registerListener()
99      {
100         PacketFilter normalTypeFilter = new MessageTypeFilter(Message.Type.normal);
101         PacketFilter chatTypeFilter = new MessageTypeFilter(Message.Type.chat);
102         PacketFilter mucTypeFilter = new MessageTypeFilter(Message.Type.groupchat);
103         PacketFilter filter = new OrFilter(normalTypeFilter, chatTypeFilter);
104         filter = new OrFilter(filter, mucTypeFilter);
105 
106         if (synchronous)
107         {
108             packetCollector = connection.createPacketCollector(filter);
109         }
110         else
111         {
112             connection.addPacketListener(this, filter);
113         }
114     }
115 
116     public void disconnect()
117     {
118         connection.removePacketListener(this);
119         
120         if (packetCollector != null)
121         {
122             packetCollector.cancel();
123         }
124         if (groupchat != null)
125         {
126             groupchat.leave();
127         }
128         
129         chats = null;
130         connection.disconnect();
131     }
132 
133     //
134     // Jabber listeners
135     //
136     public void processPacket(Packet packet)
137     {
138         if (logger.isDebugEnabled())
139         {
140             logger.debug("received " + packet);
141         }
142         
143         // our filters make sure that we ever only see Message instances
144         replies.add((Message) packet);
145         
146         countDownMessageLatch();        
147         sendAutoreply(packet);
148     }
149 
150     public void processMessage(Chat chat, Message message)
151     {
152         if (logger.isDebugEnabled())
153         {
154             logger.debug("received from chat '" + chat.getThreadID() + ": " + message);
155         }
156         
157         replies.add(message);
158         countDownMessageLatch();
159     }
160 
161     private void countDownMessageLatch()
162     {
163         if (messageLatch != null)
164         {
165             messageLatch.countDown();
166         }
167     }
168 
169     private void sendAutoreply(Packet packet)
170     {
171         if (autoreply)
172         {
173             Message incomingMessage = (Message) packet;
174             
175             Message message = new Message();
176             message.setType(incomingMessage.getType());
177             message.setTo(incomingMessage.getFrom());
178             message.setBody(replyPayload);
179             
180             connection.sendPacket(message);
181             
182             if (logger.isDebugEnabled())
183             {
184                 logger.debug("sent autoreply message with payload: \"" + replyPayload + "\"");
185             }
186         }
187     }
188 
189     public void sendMessage(String recipient, String payload)
190     {
191         if (logger.isDebugEnabled())
192         {
193             logger.debug("Will send message to \"" + recipient + "\" with payload \"" + payload + "\"");
194         }
195         
196         Message message = buildMessage(Message.Type.normal, recipient, payload);
197         connection.sendPacket(message);
198     }
199 
200     public void sendChatMessage(String recipient, String payload) throws XMPPException
201     {
202         if (logger.isDebugEnabled())
203         {
204             logger.debug("Will send chat message to \"" + recipient + "\" with payload \"" + payload + "\"");
205         }
206 
207         Chat chat = chatWith(recipient);
208         Message message = buildMessage(Message.Type.chat, recipient, payload);
209         chat.sendMessage(message);
210     }
211     
212     private Chat chatWith(String recipient)
213     {
214         Chat chat = chats.get(recipient);
215         if (chat == null)
216         {
217             chat = connection.getChatManager().createChat(recipient, this);
218             chats.put(recipient, chat);
219         }
220         return chat;
221     }
222     
223     private Message buildMessage(Message.Type type, String recipient, String payload)
224     {
225         Message message = new Message();
226         message.setType(type);
227         
228         String from = user + "@" + host;
229         message.setFrom(from);
230         
231         message.setTo(recipient);
232         message.setBody(payload);
233 
234         return message;
235     }
236     
237     public List<Message> getReceivedMessages()
238     {
239         return replies;
240     }
241     
242     public Packet receive(long timeout)
243     {
244         return packetCollector.nextResult(timeout);
245     }
246 
247     public void joinGroupchat(String chatroom) throws XMPPException
248     {
249         groupchat = new MultiUserChat(connection, chatroom);
250         groupchat.join(UUID.getUUID().toString());
251     }
252 
253     public void sendGroupchatMessage(String text) throws XMPPException
254     {
255         groupchat.sendMessage(text);
256     }
257 
258     //
259     // setters for config parameters
260     // 
261     public void setReplyPayload(String reply)
262     {
263         replyPayload = reply;
264     }
265 
266     public void setAutoReply(boolean flag)
267     {
268         autoreply = flag;
269         // autoreply only works in an async mode
270         synchronous = false;
271     }
272     
273     public void setSynchronous(boolean flag)
274     {
275         synchronous = flag;
276     }
277 
278     public void setMessageLatch(CountDownLatch latch)
279     {
280         messageLatch = latch;
281     }
282 }