View Javadoc

1   /*
2    * Created on 1 f???vr. 2005 by Pierre-Yves ROGER.
3    *
4    */
5   package net.sf.asterisk.manager;
6   
7   import java.io.IOException;
8   import java.util.*;
9   
10  import net.sf.asterisk.manager.action.*;
11  import net.sf.asterisk.manager.event.*;
12  import net.sf.asterisk.util.Log;
13  import net.sf.asterisk.util.LogFactory;
14  
15  /***
16   * @author PY
17   */
18  public class MultiAsterisksManager implements AsteriskManager, ManagerEventHandler
19  {
20      private final Log log = LogFactory.getLog(this.getClass());
21      /***
22       * A map of all Asterisk servers connections by their unique hostname.
23       */
24      private Map managerConnections;
25  
26      /***
27       * A map of all active channel by theirs hostname of connection and unique id. keyMap ->
28       * "hostname:uniqueId"
29       */
30      private Map channels;
31      private Map queues;
32      private List queuedEvents;
33  
34      /***
35       * A map of all "Initiallize flag" per connection. keyMap -> "hostname"
36       */
37      private Map initialized;
38  
39      public MultiAsterisksManager()
40      {
41          this.channels = Collections.synchronizedMap(new HashMap());
42          this.queues = Collections.synchronizedMap(new HashMap());
43          this.queuedEvents = Collections.synchronizedList(new ArrayList());
44          this.managerConnections = Collections.synchronizedMap(new HashMap());
45          this.initialized = Collections.synchronizedMap(new HashMap());
46      }
47  
48      public void addManagerConnection(ManagerConnection connection)
49      {
50          managerConnections.put(connection.getAsteriskServer(), connection);
51  
52          Hashtable initializedBoolean = new Hashtable(3, 1);
53          initializedBoolean.put("channelsInitialized", new Boolean(false));
54          // TODO fix detection of queuesInitialized
55          initializedBoolean.put("queuesInitialized", new Boolean(true));
56          initializedBoolean.put("initialized", new Boolean(false));
57  
58          initialized.put(connection.getAsteriskServer(), initializedBoolean);
59  
60      }
61  
62      public void initialize() throws TimeoutException, IOException, AuthenticationFailedException
63      {
64          Iterator iterConnect = managerConnections.values().iterator();
65          while (iterConnect.hasNext())
66          {
67              ManagerConnection connection = (ManagerConnection) iterConnect.next();
68              connection.addEventHandler(this);
69              connection.login();
70              connection.sendAction(new StatusAction());
71              connection.sendAction(new QueueStatusAction());
72          }
73      }
74  
75      /***
76       * Returns a map of all active channel by their unique id: "hostname:ChannelId".
77       */
78      public Map getChannels()
79      {
80          return channels;
81      }
82  
83      public Map getQueues()
84      {
85          return queues;
86      }
87  
88      /***
89       * Handles all events received from the asterisk server.<br>
90       * Events are queued until channels and queues are initialized and then delegated to the
91       * dispatchEvent method.
92       */
93      public void handleEvent(ManagerEvent event)
94      {
95          System.out.println("received: " + event);
96  
97          Hashtable initializedBoolean = (Hashtable) initialized.get((AsteriskServer) event.getSource());
98  
99          if (!((Boolean) initializedBoolean.get("initialized")).booleanValue())
100         {
101             if (event instanceof StatusEvent)
102             {
103                 handleStatusEvent((StatusEvent) event);
104             }
105             else if (event instanceof StatusCompleteEvent)
106             {
107                 handleStatusCompleteEvent((StatusCompleteEvent) event);
108             }
109             else if (event instanceof QueueParamsEvent)
110             {
111                 handleQueueParamsEvent((QueueParamsEvent) event);
112             }
113             else if (event instanceof QueueMemberEvent)
114             {
115                 handleQueueMemberEvent((QueueMemberEvent) event);
116             }
117             else if (event instanceof QueueEntryEvent)
118             {
119                 handleQueueEntryEvent((QueueEntryEvent) event);
120             }
121             else
122             {
123                 queuedEvents.add(event);
124             }
125 
126             if (((Boolean) initializedBoolean.get("channelsInitialized")).booleanValue()
127                     && ((Boolean) initializedBoolean.get("queuesInitialized")).booleanValue())
128             {
129                 Iterator i = queuedEvents.iterator();
130 
131                 while (i.hasNext())
132                 {
133                     ManagerEvent queuedEvent = (ManagerEvent) i.next();
134                     dispatchEvent(queuedEvent);
135                     i.remove();
136                 }
137 
138                 initializedBoolean.put("initialized", new Boolean(true));
139             }
140         }
141         else
142         {
143             dispatchEvent(event);
144         }
145     }
146 
147     protected void dispatchEvent(ManagerEvent event)
148     {
149         if (event instanceof NewChannelEvent)
150         {
151             handleNewChannelEvent((NewChannelEvent) event);
152         }
153         else if (event instanceof NewExtenEvent)
154         {
155             handleNewExtenEvent((NewExtenEvent) event);
156         }
157         else if (event instanceof NewStateEvent)
158         {
159             handleNewStateEvent((NewStateEvent) event);
160         }
161         else if (event instanceof LinkEvent)
162         {
163             handleLinkEvent((LinkEvent) event);
164         }
165         else if (event instanceof UnlinkEvent)
166         {
167             handleUnlinkEvent((UnlinkEvent) event);
168         }
169         else if (event instanceof RenameEvent)
170         {
171             handleRenameEvent((RenameEvent) event);
172         }
173         else if (event instanceof HangupEvent)
174         {
175             handleHangupEvent((HangupEvent) event);
176         }
177     }
178 
179     protected void addChannel(Channel channel)
180     {
181         channels.put(channel.getAsteriskServer().getHostname() + "/" + channel.getId(), channel);
182     }
183 
184     protected void removeChannel(Channel channel)
185     {
186         channels.remove(channel.getAsteriskServer().getHostname() + "/" + channel.getId());
187     }
188 
189     protected void addQueue(Queue queue)
190     {
191         queues.put(queue.getName(), queue);
192     }
193 
194     protected void removeQueue(Queue queue)
195     {
196         queues.remove(queue.getName());
197     }
198 
199     protected void handleStatusEvent(StatusEvent event)
200     {
201         Channel channel;
202         boolean isNew = false;
203 
204         channel = (Channel) channels
205                 .get(((AsteriskServer) event.getSource()).getHostname() + "/" + event.getUniqueId());
206         if (channel == null)
207         {
208             channel = new Channel(event.getChannel(), event.getUniqueId(), (AsteriskServer) event.getSource());
209             if (event.getSeconds() != null)
210             {
211                 channel
212                         .setDateOfCreation(new Date(System.currentTimeMillis() - (event.getSeconds().intValue() * 1000)));
213             }
214             isNew = true;
215         }
216 
217         synchronized (channel)
218         {
219             channel.setCallerId(event.getCallerId());
220             channel.setAccount(event.getAccount());
221             channel.setState(ChannelStateEnum.getEnum(event.getState()));
222             // TODO handle extension
223             if (event.getLink() != null)
224             {
225                 Channel linkedChannel = getChannelByName(event.getLink());
226                 if (linkedChannel != null)
227                 {
228                     channel.setLinkedChannel(linkedChannel);
229                     synchronized (linkedChannel)
230                     {
231                         linkedChannel.setLinkedChannel(channel);
232                     }
233                 }
234             }
235         }
236 
237         if (isNew)
238         {
239             log.info("Adding new channel " + channel.getName() + ", from server "
240                     + channel.getAsteriskServer().getHostname());
241             addChannel(channel);
242         }
243     }
244 
245     protected void handleStatusCompleteEvent(StatusCompleteEvent event)
246     {
247         log.info("Channels are now initialized");
248         Hashtable initializedBoolean = (Hashtable) initialized.get((AsteriskServer) event.getSource());
249         initializedBoolean.put("channelsInitialized", new Boolean(true));
250     }
251 
252     protected void handleQueueParamsEvent(QueueParamsEvent event)
253     {
254         Queue queue;
255         boolean isNew = false;
256 
257         queue = (Queue) queues.get(event.getQueue());
258 
259         if (queue == null)
260         {
261             queue = new Queue(event.getQueue());
262             isNew = true;
263         }
264 
265         synchronized (queue)
266         {
267             queue.setMax(event.getMax());
268         }
269 
270         if (isNew)
271         {
272             log.info("Adding new queue " + queue.getName());
273             addQueue(queue);
274         }
275     }
276 
277     protected void handleQueueMemberEvent(QueueMemberEvent event)
278     {
279 
280     }
281 
282     protected void handleQueueEntryEvent(QueueEntryEvent event)
283     {
284         Queue queue = (Queue) queues.get(event.getQueue());
285         Channel channel = getChannelByName(event.getChannel());
286 
287         if (queue == null)
288         {
289             log.error("ignored QueueEntryEvent for unknown queue " + event.getQueue());
290             return;
291         }
292         if (channel == null)
293         {
294             log.error("ignored QueueEntryEvent for unknown channel " + event.getChannel());
295             return;
296         }
297 
298         if (!queue.getEntries().contains(channel))
299         {
300             queue.addEntry(channel);
301         }
302     }
303 
304     /***
305      * Returns a channel by its name.
306      * 
307      * @param name name of the channel to return
308      * @return the channel with the given name
309      */
310     private Channel getChannelByName(String name)
311     {
312         // TODO must get unique
313         Channel channel = null;
314         Iterator channelIterator = channels.values().iterator();
315         while (channelIterator.hasNext())
316         {
317             Channel tmp = (Channel) channelIterator.next();
318             if (tmp.getName() != null && tmp.getName().equals(name))
319             {
320                 channel = tmp;
321             }
322         }
323         return channel;
324     }
325 
326     protected void handleNewChannelEvent(NewChannelEvent event)
327     {
328         Channel channel = new Channel(event.getChannel(), event.getUniqueId(), (AsteriskServer) event.getSource());
329 
330         channel.setCallerId(event.getCallerId());
331         channel.setState(ChannelStateEnum.getEnum(event.getState()));
332 
333         log.info("Adding channel " + channel.getName() + ", on server " + channel.getAsteriskServer().getHostname());
334         addChannel(channel);
335     }
336 
337     protected void handleNewExtenEvent(NewExtenEvent event)
338     {
339         Channel channel = (Channel) channels.get(((AsteriskServer) event.getSource()).getHostname() + "/"
340                 + event.getUniqueId());
341         if (channel == null)
342         {
343             log.error("Ignored NewExtenEvent for unknown channel " + event.getChannel());
344             return;
345         }
346 
347         synchronized (channel)
348         {
349             // TODO handle new extension
350         }
351     }
352 
353     protected void handleNewStateEvent(NewStateEvent event)
354     {
355         Channel channel = (Channel) channels.get(((AsteriskServer) event.getSource()).getHostname() + "/"
356                 + event.getUniqueId());
357         if (channel == null)
358         {
359             log.error("Ignored NewStateEvent for unknown channel " + event.getChannel());
360             return;
361         }
362 
363         channel.setState(ChannelStateEnum.getEnum(event.getState()));
364     }
365 
366     protected void handleHangupEvent(HangupEvent event)
367     {
368         Channel channel = (Channel) channels.get(((AsteriskServer) event.getSource()).getHostname() + "/"
369                 + event.getUniqueId());
370         if (channel == null)
371         {
372             log.error("Ignored HangupEvent for unknown channel " + event.getChannel());
373             return;
374         }
375 
376         synchronized (channel)
377         {
378             channel.setState(ChannelStateEnum.HUNGUP);
379         }
380 
381         log.info("Removing channel " + channel.getName() + " due to hangup");
382         removeChannel(channel);
383     }
384 
385     protected void handleLinkEvent(LinkEvent event)
386     {
387         Channel channel1 = (Channel) channels.get(((AsteriskServer) event.getSource()).getHostname() + "/"
388                 + event.getUniqueId1());
389         Channel channel2 = (Channel) channels.get(((AsteriskServer) event.getSource()).getHostname() + "/"
390                 + event.getUniqueId2());
391 
392         if (channel1 == null)
393         {
394             log.error("Ignored LinkEvent for unknown channel " + event.getChannel1());
395             return;
396         }
397         if (channel2 == null)
398         {
399             log.error("Ignored LinkEvent for unknown channel " + event.getChannel2());
400             return;
401         }
402 
403         log.info("Linking channels " + channel1.getName() + " and " + channel2.getName());
404         synchronized (this)
405         {
406             channel1.setLinkedChannel(channel2);
407             channel2.setLinkedChannel(channel1);
408         }
409     }
410 
411     protected void handleUnlinkEvent(UnlinkEvent event)
412     {
413         Channel channel1 = getChannelByName(event.getChannel1());
414         Channel channel2 = getChannelByName(event.getChannel2());
415 
416         if (channel1 == null)
417         {
418             log.error("Ignored UnlinkEvent for unknown channel " + event.getChannel1());
419             return;
420         }
421         if (channel2 == null)
422         {
423             log.error("Ignored UnlinkEvent for unknown channel " + event.getChannel2());
424             return;
425         }
426 
427         log.info("Unlinking channels " + channel1.getName() + " and " + channel2.getName());
428         synchronized (channel1)
429         {
430             channel1.setLinkedChannel(null);
431         }
432 
433         synchronized (channel2)
434         {
435             channel2.setLinkedChannel(null);
436         }
437     }
438 
439     protected void handleRenameEvent(RenameEvent event)
440     {
441         Channel channel = (Channel) channels.get(((AsteriskServer) event.getSource()).getHostname() + "/"
442                 + event.getUniqueId());
443 
444         log.info("Renaming channel '" + channel.getName() + "' to '" + event.getNewname() + "'");
445         channel.setName(event.getNewname());
446     }
447 
448     /*
449      * (non-Javadoc)
450      * 
451      * @see net.sf.asterisk.manager.AsteriskManager#originateCall(net.sf.asterisk.manager.action.OriginateAction)
452      */
453     public Call originateCall(Originate originate) throws TimeoutException, IOException
454     {
455         // TODO Auto-generated method stub
456         return null;
457     }
458 
459     public int[] getVersion(String file)
460     {
461         throw new UnsupportedOperationException();
462     }
463 
464     public String getVersion()
465     {
466         throw new UnsupportedOperationException();
467     }
468 }