1   //========================================================================
2   //Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
3   //------------------------------------------------------------------------
4   //Licensed under the Apache License, Version 2.0 (the "License");
5   //you may not use this file except in compliance with the License.
6   //You may obtain a copy of the License at
7   //http://www.apache.org/licenses/LICENSE-2.0
8   //Unless required by applicable law or agreed to in writing, software
9   //distributed under the License is distributed on an "AS IS" BASIS,
10  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  //See the License for the specific language governing permissions and
12  //limitations under the License.
13  //========================================================================
14  
15  /**
16   *
17   */
18  package org.cometd.demo;
19  
20  import java.util.HashMap;
21  import java.util.Map;
22  import java.util.concurrent.ConcurrentHashMap;
23  import java.util.concurrent.ConcurrentMap;
24  
25  import org.cometd.Bayeux;
26  import org.cometd.Channel;
27  import org.cometd.Client;
28  import org.cometd.RemoveListener;
29  import org.mortbay.cometd.BayeuxService;
30  import org.mortbay.log.Log;
31  
32  public class ChatService extends BayeuxService
33  {
34      /**
35       * A map(channel, map(userName, clientId))
36       */
37      private final ConcurrentMap<String, Map<String, String>> _members = new ConcurrentHashMap<String, Map<String, String>>();
38  
39      public ChatService(Bayeux bayeux)
40      {
41          super(bayeux, "chat");
42          subscribe("/chat/**", "trackMembers");
43          subscribe("/service/privatechat", "privateChat");
44      }
45  
46      public void trackMembers(final Client joiner, final String channelName, Map<String, Object> data, final String messageId)
47      {
48          if (Boolean.TRUE.equals(data.get("join")))
49          {
50              Map<String, String> membersMap = _members.get(channelName);
51              if (membersMap == null)
52              {
53                  Map<String, String> newMembersMap = new ConcurrentHashMap<String, String>();
54                  membersMap = _members.putIfAbsent(channelName, newMembersMap);
55                  if (membersMap == null) membersMap = newMembersMap;
56              }
57  
58              final Map<String, String> members = membersMap;
59              final String userName = (String)data.get("user");
60              members.put(userName, joiner.getId());
61              joiner.addListener(new RemoveListener()
62              {
63                  public void removed(String clientId, boolean timeout)
64                  {
65                      members.values().remove(clientId);
66                      Log.info("members: " + members);
67                      // Broadcast the members to all existing members
68                      Channel channel = getBayeux().getChannel(channelName, false);
69                      if (channel != null) channel.publish(getClient(), members.keySet(), messageId);
70                  }
71              });
72  
73              Log.info("Members: " + members);
74              // Broadcast the members to all existing members
75              getBayeux().getChannel(channelName, false).publish(getClient(), members.keySet(), messageId);
76          }
77      }
78  
79      public void privateChat(Client source, String channel, Map<String, Object> data, String messageId)
80      {
81          String roomName = (String)data.get("room");
82          Map<String, String> membersMap = _members.get(roomName);
83          String peerName = (String)data.get("peer");
84          String peerId = membersMap.get(peerName);
85  	if (peerId!=null)
86          {
87              Client peer = getBayeux().getClient(peerId);
88  	    if (peer!=null)
89  	    {
90  		Map<String, Object> message = new HashMap<String, Object>();
91  		message.put("chat", data.get("chat"));
92  		message.put("user", data.get("user"));
93  		message.put("scope", "private");
94  		peer.deliver(getClient(), roomName, message, messageId);
95  		source.deliver(getClient(), roomName, message, messageId);
96  		return;
97              }
98  	}
99  	Map<String, Object> message = new HashMap<String, Object>();
100 	message.put("chat", "Unknown user: "+peerName);
101 	message.put("user", "SERVER");
102 	message.put("scope", "error");
103 	source.deliver(source, roomName, message, messageId);
104     }
105 }
106