View Javadoc

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