View Javadoc

1   /**
2    *
3    */
4   package org.cometd.demo;
5   
6   import java.util.ArrayList;
7   import java.util.HashMap;
8   import java.util.Map;
9   import java.util.concurrent.ConcurrentHashMap;
10  import java.util.concurrent.ConcurrentMap;
11  
12  import org.cometd.Bayeux;
13  import org.cometd.Channel;
14  import org.cometd.Client;
15  import org.cometd.RemoveListener;
16  import org.mortbay.cometd.BayeuxService;
17  import org.mortbay.log.Log;
18  
19  public class ChatService extends BayeuxService
20  {
21      /**
22       * A map(channel, map(userName, clientId))
23       */
24      private final ConcurrentMap<String, Map<String, String>> _members = new ConcurrentHashMap<String, Map<String, String>>();
25  
26      public ChatService(Bayeux bayeux)
27      {
28          super(bayeux, "chat");
29          subscribe("/chat/**", "trackMembers");
30          subscribe("/service/privatechat", "privateChat");
31      }
32  
33      public void trackMembers(final Client joiner, final String channelName, Map<String, Object> data, final String messageId)
34      {
35          if (Boolean.TRUE.equals(data.get("join")))
36          {
37              Map<String, String> membersMap = _members.get(channelName);
38              if (membersMap == null)
39              {
40                  Map<String, String> newMembersMap = new ConcurrentHashMap<String, String>();
41                  membersMap = _members.putIfAbsent(channelName, newMembersMap);
42                  if (membersMap == null) membersMap = newMembersMap;
43              }
44  
45              final Map<String, String> members = membersMap;
46              final String userName = (String)data.get("user");
47              members.put(userName, joiner.getId());
48              joiner.addListener(new RemoveListener()
49              {
50                  public void removed(String clientId, boolean timeout)
51                  {
52                      members.values().remove(clientId);
53                      Log.info("members: " + members);
54                      // Broadcast the members to all existing members
55                      Channel channel = getBayeux().getChannel(channelName, false);
56                      if (channel != null) channel.publish(getClient(), members.keySet(), messageId);
57                  }
58              });
59  
60              Log.info("Members: " + members);
61              // Broadcast the members to all existing members
62              getBayeux().getChannel(channelName, false).publish(getClient(), members.keySet(), messageId);
63          }
64      }
65  
66      public void privateChat(Client source, String channel, Map<String, Object> data, String messageId)
67      {
68          String roomName = (String)data.get("room");
69          Map<String, String> membersMap = _members.get(roomName);
70          String[] peerNames = ((String)data.get("peer")).split(",");
71          ArrayList<Client> peers = new ArrayList<Client>(peerNames.length);
72  
73          for (String peerName : peerNames)
74          {
75              String peerId = membersMap.get(peerName);
76              if (peerId!=null)
77              {
78                  Client peer = getBayeux().getClient(peerId);
79                  if (peer!=null)
80                      peers.add(peer);
81              }
82          }
83  
84          if (peers.size()>0)
85          {
86              Map<String, Object> message = new HashMap<String, Object>();
87              message.put("chat", data.get("chat"));
88              message.put("user", data.get("user"));
89              message.put("scope", "private");
90              for (int i = 0; i < peers.size(); ++i) peers.get(i).deliver(source, roomName, message, messageId);
91              source.deliver(getClient(), roomName, message, messageId);
92          }
93          else if (!"silent".equals(data.get("peer")))
94          {
95              Map<String, Object> message = new HashMap<String, Object>();
96              message.put("chat", "Unknown user(s): "+data.get("peer"));
97              message.put("user", "SERVER");
98              message.put("scope", "error");
99              source.deliver(source, roomName, message, messageId);
100         }
101     }
102 }
103