1   // ========================================================================
2   // Copyright 2007-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  package dojox.cometd.demo;
16  
17  
18  import javax.servlet.ServletContext;
19  import javax.servlet.ServletContextAttributeEvent;
20  import javax.servlet.ServletContextAttributeListener;
21  
22  import org.mortbay.cometd.BayeuxService;
23  import org.mortbay.log.Log;
24  import org.mortbay.thread.QueuedThreadPool;
25  
26  import dojox.cometd.Bayeux;
27  import dojox.cometd.Client;
28  import dojox.cometd.Listener;
29  import dojox.cometd.Message;
30  import dojox.cometd.MessageListener;
31  import dojox.cometd.RemoveListener;
32  
33  import java.util.Map;
34  import java.util.Set;
35  import java.util.concurrent.ConcurrentHashMap;
36  import java.util.concurrent.ConcurrentMap;
37  import java.util.concurrent.CopyOnWriteArraySet;
38  
39  public class BayeuxStartupListener implements ServletContextAttributeListener
40  {
41      public void initialize(Bayeux bayeux)
42      {
43          synchronized(bayeux)
44          {
45              if (!bayeux.hasChannel("/service/echo"))
46              {
47                  new EchoRPC(bayeux);
48                  /* Demo off
49                  new Monitor(bayeux);
50                  new ChatService(bayeux);
51                  */
52              }
53          }
54      }
55      
56      public void attributeAdded(ServletContextAttributeEvent scab)
57      {
58          if (scab.getName().equals(Bayeux.DOJOX_COMETD_BAYEUX))
59          {
60              Bayeux bayeux=(Bayeux)scab.getValue();
61              initialize(bayeux);
62          }
63      }
64  
65      public void attributeRemoved(ServletContextAttributeEvent scab)
66      {
67  
68      }
69  
70      public void attributeReplaced(ServletContextAttributeEvent scab)
71      {
72  
73      }
74  
75      
76      public static class EchoRPC extends BayeuxService
77      {
78          public EchoRPC(Bayeux bayeux)
79          {
80              super(bayeux,"echo");
81              subscribe("/service/echo","doEcho");
82          }
83          
84          public Object doEcho(Client client, Object data)
85          {
86  	    Log.info("ECHO from "+client+" "+data);
87  	    return data;
88          }
89      }
90      
91      public static class Monitor extends BayeuxService
92      {
93          public Monitor(Bayeux bayeux)
94          {
95              super(bayeux,"monitor");
96              subscribe("/meta/subscribe","monitorSubscribe");
97              subscribe("/meta/subscribe","monitorUnsubscribe");
98              subscribe("/meta/*","monitorMeta");
99              // subscribe("/**","monitorVerbose");
100         }
101         
102         public void monitorSubscribe(Client client, Message message)
103         {
104             Log.info("Subscribe from "+client+" for "+message.get(Bayeux.SUBSCRIPTION_FIELD));
105         }
106         
107         public void monitorUnsubscribe(Client client, Message message)
108         {
109             Log.info("Unsubscribe from "+client+" for "+message.get(Bayeux.SUBSCRIPTION_FIELD));
110         }
111         
112         public void monitorMeta(Client client, Message message)
113         {
114             if (Log.isDebugEnabled())
115                 Log.debug(message.toString());
116         }
117         
118         /*
119         public void monitorVerbose(Client client, Message message)
120         {
121             System.err.println(message);
122             try 
123             {
124                 Thread.sleep(5000);
125             }
126             catch(Exception e)
127             {
128                 Log.warn(e);
129             }
130         }
131         */
132     }
133     
134     public static class ChatService extends BayeuxService
135     {
136         ConcurrentMap<String,Set<String>> _members = new ConcurrentHashMap<String,Set<String>>();
137         
138         public ChatService(Bayeux bayeux)
139         {
140             super(bayeux,"chat");
141             subscribe("/chat/**","trackMembers");
142         }
143         
144         public void trackMembers(Client joiner,String channel,Map<String,Object> data,String id)
145         {
146             if (Boolean.TRUE.equals(data.get("join")))
147             {
148                 Set<String> m = _members.get(channel);
149                 if (m==null)
150                 {
151                     Set<String> new_list=new CopyOnWriteArraySet<String>();
152                     m=_members.putIfAbsent(channel,new_list);
153                     if (m==null)
154                         m=new_list;
155                 }
156                 
157                 final Set<String> members=m;
158                 final String username=(String)data.get("user");
159                 
160                 members.add(username);
161                 joiner.addListener(new RemoveListener(){
162                     public void removed(String clientId, boolean timeout)
163                     {
164                         members.remove(username);
165                     }
166                 });
167                 
168                 send(joiner,channel,members,id);
169             }
170         }
171     }
172 }