1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.asteriskjava.live.internal;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.concurrent.atomic.AtomicLong;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28
29 import org.asteriskjava.live.AsteriskChannel;
30 import org.asteriskjava.live.AsteriskQueue;
31 import org.asteriskjava.live.AsteriskServer;
32 import org.asteriskjava.live.AsteriskServerListener;
33 import org.asteriskjava.live.CallerId;
34 import org.asteriskjava.live.ChannelState;
35 import org.asteriskjava.live.LiveException;
36 import org.asteriskjava.live.ManagerCommunicationException;
37 import org.asteriskjava.live.MeetMeRoom;
38 import org.asteriskjava.live.MeetMeUser;
39 import org.asteriskjava.live.NoSuchChannelException;
40 import org.asteriskjava.live.OriginateCallback;
41 import org.asteriskjava.live.Voicemailbox;
42 import org.asteriskjava.manager.ManagerConnection;
43 import org.asteriskjava.manager.ManagerConnectionState;
44 import org.asteriskjava.manager.ManagerEventListener;
45 import org.asteriskjava.manager.ManagerEventListenerProxy;
46 import org.asteriskjava.manager.ResponseEvents;
47 import org.asteriskjava.manager.action.CommandAction;
48 import org.asteriskjava.manager.action.EventGeneratingAction;
49 import org.asteriskjava.manager.action.GetVarAction;
50 import org.asteriskjava.manager.action.MailboxCountAction;
51 import org.asteriskjava.manager.action.ManagerAction;
52 import org.asteriskjava.manager.action.OriginateAction;
53 import org.asteriskjava.manager.action.SetVarAction;
54 import org.asteriskjava.manager.event.AbstractMeetMeEvent;
55 import org.asteriskjava.manager.event.OriginateResponseEvent;
56 import org.asteriskjava.manager.event.CdrEvent;
57 import org.asteriskjava.manager.event.ConnectEvent;
58 import org.asteriskjava.manager.event.DialEvent;
59 import org.asteriskjava.manager.event.DisconnectEvent;
60 import org.asteriskjava.manager.event.HangupEvent;
61 import org.asteriskjava.manager.event.JoinEvent;
62 import org.asteriskjava.manager.event.LeaveEvent;
63 import org.asteriskjava.manager.event.LinkEvent;
64 import org.asteriskjava.manager.event.ManagerEvent;
65 import org.asteriskjava.manager.event.NewCallerIdEvent;
66 import org.asteriskjava.manager.event.NewChannelEvent;
67 import org.asteriskjava.manager.event.NewExtenEvent;
68 import org.asteriskjava.manager.event.NewStateEvent;
69 import org.asteriskjava.manager.event.RenameEvent;
70 import org.asteriskjava.manager.event.ResponseEvent;
71 import org.asteriskjava.manager.event.UnlinkEvent;
72 import org.asteriskjava.manager.response.CommandResponse;
73 import org.asteriskjava.manager.response.MailboxCountResponse;
74 import org.asteriskjava.manager.response.ManagerError;
75 import org.asteriskjava.manager.response.ManagerResponse;
76 import org.asteriskjava.util.DateUtil;
77 import org.asteriskjava.util.Log;
78 import org.asteriskjava.util.LogFactory;
79
80 /***
81 * Default implementation of the {@link AsteriskServer} interface.
82 *
83 * @author srt
84 * @version $Id: AsteriskServerImpl.java 877 2007-07-31 15:47:01Z srt $
85 */
86 public class AsteriskServerImpl implements AsteriskServer, ManagerEventListener
87 {
88 private static final String ACTION_ID_PREFIX_ORIGINATE = "AJ_ORIGINATE_";
89 private static final String SHOW_VERSION_COMMAND = "show version";
90 private static final String SHOW_VERSION_FILES_COMMAND = "show version files";
91 private static final Pattern SHOW_VERSION_FILES_PATTERN = Pattern.compile("^([//S]+)//s+Revision: ([0-9//.]+)");
92 private static final String SHOW_VOICEMAIL_USERS_COMMAND = "show voicemail users";
93 private static final Pattern SHOW_VOICEMAIL_USERS_PATTERN = Pattern.compile("^(//S+)//s+(//S+)//s+(.{25})");
94
95 private final Log logger = LogFactory.getLog(this.getClass());
96
97 /***
98 * The underlying manager connection used to receive events from Asterisk.
99 */
100 private ManagerConnection eventConnection;
101 private ManagerEventListener eventListener = null;
102 private ManagerEventListenerProxy managerEventListenerProxy = null;
103
104 private boolean initialized = false;
105
106 /***
107 * A pool of manager connections to use for sending actions to Asterisk.
108 */
109 private final ManagerConnectionPool connectionPool;
110
111 private final List<AsteriskServerListener> listeners;
112
113 private final ChannelManager channelManager;
114 private final MeetMeManager meetMeManager;
115 private final QueueManager queueManager;
116
117 /***
118 * The exact version string of the Asterisk server we are connected to.
119 * <p>
120 * Contains <code>null</code> until lazily initialized.
121 */
122 private String version;
123
124 /***
125 * Holds the version of Asterisk's source files.
126 * <p>
127 * That corresponds to the output of the CLI command
128 * <code>show version files</code>.
129 * <p>
130 * Contains <code>null</code> until lazily initialized.
131 */
132 private Map<String, String> versions;
133
134 /***
135 * Maps the traceId to the corresponding callback data.
136 */
137 private final Map<String, OriginateCallbackData> originateCallbacks;
138
139 private final AtomicLong idCounter;
140
141
142
143 /***
144 * Flag to skip initializing queues as that results in a timeout on Asterisk
145 * 1.0.x.
146 */
147 private boolean skipQueues;
148
149 /***
150 * Set to <code>true</code> to not handle ManagerEvents in the reader
151 * tread but process them asynchronously. This is a good idea :)
152 */
153 private boolean asyncEventHandling = true;
154
155 /***
156 * Creates a new instance.
157 */
158 public AsteriskServerImpl()
159 {
160 connectionPool = new ManagerConnectionPool(1);
161 idCounter = new AtomicLong();
162 listeners = new ArrayList<AsteriskServerListener>();
163 originateCallbacks = new HashMap<String, OriginateCallbackData>();
164 channelManager = new ChannelManager(this);
165 meetMeManager = new MeetMeManager(this, channelManager);
166 queueManager = new QueueManager(this, channelManager);
167 }
168
169 /***
170 * Creates a new instance.
171 *
172 * @param eventConnection the ManagerConnection to use for receiving events
173 * from Asterisk.
174 */
175 public AsteriskServerImpl(ManagerConnection eventConnection)
176 {
177 this();
178 setManagerConnection(eventConnection);
179 }
180
181 /***
182 * Determines if queue status is retrieved at startup. If you don't need
183 * queue information and still run Asterisk 1.0.x you can set this to
184 * <code>true</code> to circumvent the startup delay caused by the missing
185 * QueueStatusComplete event.
186 * <p>
187 * Default is <code>false</code>.
188 *
189 * @param skipQueues <code>true</code> to skip queue initialization,
190 * <code>false</code> to not skip.
191 * @since 0.2
192 */
193 public void setSkipQueues(boolean skipQueues)
194 {
195 this.skipQueues = skipQueues;
196 }
197
198 public void setManagerConnection(ManagerConnection eventConnection)
199 {
200 if (this.eventConnection != null)
201 {
202 throw new IllegalStateException("ManagerConnection already set.");
203 }
204
205 this.eventConnection = eventConnection;
206 this.connectionPool.clear();
207 this.connectionPool.add(eventConnection);
208 }
209
210 public ManagerConnection getManagerConnection()
211 {
212 return eventConnection;
213 }
214
215 public void initialize() throws ManagerCommunicationException
216 {
217 initializeIfNeeded();
218 }
219
220 private synchronized void initializeIfNeeded() throws ManagerCommunicationException
221 {
222 if (initialized)
223 {
224 return;
225 }
226
227 if (eventConnection.getState() == ManagerConnectionState.INITIAL
228 || eventConnection.getState() == ManagerConnectionState.DISCONNECTED)
229 {
230 try
231 {
232 eventConnection.login();
233 }
234 catch (Exception e)
235 {
236 throw new ManagerCommunicationException("Unable to login", e);
237 }
238 }
239
240 channelManager.initialize();
241 meetMeManager.initialize();
242 if (!skipQueues)
243 {
244 queueManager.initialize();
245 }
246
247 if (asyncEventHandling && managerEventListenerProxy == null)
248 {
249 managerEventListenerProxy = new ManagerEventListenerProxy(this);
250 eventConnection.addEventListener(managerEventListenerProxy);
251 }
252 else if (!asyncEventHandling && eventListener == null)
253 {
254 eventListener = this;
255 eventConnection.addEventListener(eventListener);
256 }
257 logger.info("Initializing done");
258 initialized = true;
259 }
260
261
262
263 public AsteriskChannel originateToExtension(String channel, String context, String exten, int priority, long timeout)
264 throws ManagerCommunicationException, NoSuchChannelException
265 {
266 return originateToExtension(channel, context, exten, priority, timeout, null, null);
267 }
268
269 public AsteriskChannel originateToExtension(String channel, String context, String exten, int priority, long timeout,
270 CallerId callerId, Map<String, String> variables) throws ManagerCommunicationException, NoSuchChannelException
271 {
272 final OriginateAction originateAction;
273
274 originateAction = new OriginateAction();
275 originateAction.setChannel(channel);
276 originateAction.setContext(context);
277 originateAction.setExten(exten);
278 originateAction.setPriority(priority);
279 originateAction.setTimeout(timeout);
280 if (callerId != null)
281 {
282 originateAction.setCallerId(callerId.toString());
283 }
284 originateAction.setVariables(variables);
285
286 return originate(originateAction);
287 }
288
289 public AsteriskChannel originateToApplication(String channel, String application, String data, long timeout)
290 throws ManagerCommunicationException, NoSuchChannelException
291 {
292 return originateToApplication(channel, application, data, timeout, null, null);
293 }
294
295 public AsteriskChannel originateToApplication(String channel, String application, String data, long timeout,
296 CallerId callerId, Map<String, String> variables) throws ManagerCommunicationException, NoSuchChannelException
297 {
298 final OriginateAction originateAction;
299
300 originateAction = new OriginateAction();
301 originateAction.setChannel(channel);
302 originateAction.setApplication(application);
303 originateAction.setData(data);
304 originateAction.setTimeout(timeout);
305 if (callerId != null)
306 {
307 originateAction.setCallerId(callerId.toString());
308 }
309 originateAction.setVariables(variables);
310
311 return originate(originateAction);
312 }
313
314 private AsteriskChannel originate(OriginateAction originateAction) throws ManagerCommunicationException,
315 NoSuchChannelException
316 {
317 final ResponseEvents responseEvents;
318 final Iterator<ResponseEvent> responseEventIterator;
319 String uniqueId = null;
320 AsteriskChannel channel = null;
321
322
323 originateAction.setAsync(Boolean.TRUE);
324
325 initializeIfNeeded();
326
327
328 responseEvents = sendEventGeneratingAction(originateAction, originateAction.getTimeout() + 2000);
329
330 responseEventIterator = responseEvents.getEvents().iterator();
331 if (responseEventIterator.hasNext())
332 {
333 ResponseEvent responseEvent;
334
335 responseEvent = responseEventIterator.next();
336 if (responseEvent instanceof OriginateResponseEvent)
337 {
338 uniqueId = ((OriginateResponseEvent) responseEvent).getUniqueId();
339 logger.debug(responseEvent.getClass().getName() + " received with uniqueId " + uniqueId);
340 channel = getChannelById(uniqueId);
341 }
342 }
343
344 if (channel == null)
345 {
346 throw new NoSuchChannelException("Channel '" + originateAction.getChannel() + "' is not available");
347 }
348
349 return channel;
350 }
351
352 public void originateToExtensionAsync(String channel, String context, String exten, int priority, long timeout,
353 OriginateCallback cb) throws ManagerCommunicationException
354 {
355 originateToExtensionAsync(channel, context, exten, priority, timeout, null, null, cb);
356 }
357
358 public void originateToExtensionAsync(String channel, String context, String exten, int priority, long timeout,
359 CallerId callerId, Map<String, String> variables, OriginateCallback cb) throws ManagerCommunicationException
360 {
361 final OriginateAction originateAction;
362
363 originateAction = new OriginateAction();
364 originateAction.setChannel(channel);
365 originateAction.setContext(context);
366 originateAction.setExten(exten);
367 originateAction.setPriority(priority);
368 originateAction.setTimeout(timeout);
369 if (callerId != null)
370 {
371 originateAction.setCallerId(callerId.toString());
372 }
373 originateAction.setVariables(variables);
374
375 originateAsync(originateAction, cb);
376 }
377
378 public void originateToApplicationAsync(String channel, String application, String data, long timeout,
379 OriginateCallback cb) throws ManagerCommunicationException
380 {
381 originateToApplicationAsync(channel, application, data, timeout, null, null, cb);
382 }
383
384 public void originateToApplicationAsync(String channel, String application, String data, long timeout,
385 CallerId callerId, Map<String, String> variables, OriginateCallback cb) throws ManagerCommunicationException
386 {
387 final OriginateAction originateAction;
388
389 originateAction = new OriginateAction();
390 originateAction.setChannel(channel);
391 originateAction.setApplication(application);
392 originateAction.setData(data);
393 originateAction.setTimeout(timeout);
394 if (callerId != null)
395 {
396 originateAction.setCallerId(callerId.toString());
397 }
398 originateAction.setVariables(variables);
399
400 originateAsync(originateAction, cb);
401 }
402
403 private void originateAsync(OriginateAction originateAction, OriginateCallback cb) throws ManagerCommunicationException
404 {
405 final Map<String, String> variables;
406 final String traceId;
407
408 traceId = ACTION_ID_PREFIX_ORIGINATE + idCounter.getAndIncrement();
409 if (originateAction.getVariables() == null)
410 {
411 variables = new HashMap<String, String>();
412 }
413 else
414 {
415 variables = new HashMap<String, String>(originateAction.getVariables());
416 }
417
418
419 variables.put("__" + Constants.VARIABLE_TRACE_ID, traceId);
420 originateAction.setVariables(variables);
421
422
423 originateAction.setAsync(Boolean.TRUE);
424 originateAction.setActionId(traceId);
425
426 if (cb != null)
427 {
428 OriginateCallbackData callbackData;
429
430 callbackData = new OriginateCallbackData(originateAction, DateUtil.getDate(), cb);
431
432 synchronized (originateCallbacks)
433 {
434 originateCallbacks.put(traceId, callbackData);
435 }
436 }
437
438 initializeIfNeeded();
439 sendActionOnEventConnection(originateAction);
440 }
441
442 public Collection<AsteriskChannel> getChannels() throws ManagerCommunicationException
443 {
444 initializeIfNeeded();
445 return channelManager.getChannels();
446 }
447
448 public AsteriskChannel getChannelByName(String name) throws ManagerCommunicationException
449 {
450 initializeIfNeeded();
451 return channelManager.getChannelImplByName(name);
452 }
453
454 public AsteriskChannel getChannelById(String id) throws ManagerCommunicationException
455 {
456 initializeIfNeeded();
457 return channelManager.getChannelImplById(id);
458 }
459
460 public Collection<MeetMeRoom> getMeetMeRooms() throws ManagerCommunicationException
461 {
462 initializeIfNeeded();
463 return meetMeManager.getMeetMeRooms();
464 }
465
466 public MeetMeRoom getMeetMeRoom(String name) throws ManagerCommunicationException
467 {
468 initializeIfNeeded();
469 return meetMeManager.getOrCreateRoomImpl(name);
470 }
471
472 public Collection<AsteriskQueue> getQueues() throws ManagerCommunicationException
473 {
474 initializeIfNeeded();
475 return queueManager.getQueues();
476 }
477
478 public synchronized String getVersion() throws ManagerCommunicationException
479 {
480 final ManagerResponse response;
481
482 initializeIfNeeded();
483 if (version == null)
484 {
485 response = sendAction(new CommandAction(SHOW_VERSION_COMMAND));
486 if (response instanceof CommandResponse)
487 {
488 final List result;
489
490 result = ((CommandResponse) response).getResult();
491 if (result.size() > 0)
492 {
493 version = (String) result.get(0);
494 }
495 }
496 else
497 {
498 logger.error("Response to CommandAction(\"" + SHOW_VERSION_COMMAND + "\") was not a CommandResponse but "
499 + response);
500 }
501 }
502
503 return version;
504 }
505
506 public int[] getVersion(String file) throws ManagerCommunicationException
507 {
508 String fileVersion = null;
509 String[] parts;
510 int[] intParts;
511
512 initializeIfNeeded();
513 if (versions == null)
514 {
515 Map<String, String> map;
516 ManagerResponse response;
517
518 map = new HashMap<String, String>();
519 try
520 {
521 response = sendAction(new CommandAction(SHOW_VERSION_FILES_COMMAND));
522 if (response instanceof CommandResponse)
523 {
524 List<String> result;
525
526 result = ((CommandResponse) response).getResult();
527 for (int i = 2; i < result.size(); i++)
528 {
529 String line;
530 Matcher matcher;
531
532 line = (String) result.get(i);
533 matcher = SHOW_VERSION_FILES_PATTERN.matcher(line);
534 if (matcher.find())
535 {
536 String key = matcher.group(1);
537 String value = matcher.group(2);
538
539 map.put(key, value);
540 }
541 }
542
543 fileVersion = (String) map.get(file);
544 versions = map;
545 }
546 else
547 {
548 logger.error("Response to CommandAction(\"" + SHOW_VERSION_FILES_COMMAND
549 + "\") was not a CommandResponse but " + response);
550 }
551 }
552 catch (Exception e)
553 {
554 logger.warn("Unable to send '" + SHOW_VERSION_FILES_COMMAND + "' command.", e);
555 }
556 }
557 else
558 {
559 synchronized (versions)
560 {
561 fileVersion = versions.get(file);
562 }
563 }
564
565 if (fileVersion == null)
566 {
567 return null;
568 }
569
570 parts = fileVersion.split("//.");
571 intParts = new int[parts.length];
572
573 for (int i = 0; i < parts.length; i++)
574 {
575 try
576 {
577 intParts[i] = Integer.parseInt(parts[i]);
578 }
579 catch (NumberFormatException e)
580 {
581 intParts[i] = 0;
582 }
583 }
584
585 return intParts;
586 }
587
588 public String getGlobalVariable(String variable) throws ManagerCommunicationException
589 {
590 ManagerResponse response;
591 String value;
592
593 initializeIfNeeded();
594 response = sendAction(new GetVarAction(variable));
595 if (response instanceof ManagerError)
596 {
597 return null;
598 }
599 value = response.getAttribute("Value");
600 if (value == null)
601 {
602 value = response.getAttribute(variable);
603 }
604 return value;
605 }
606
607 public void setGlobalVariable(String variable, String value) throws ManagerCommunicationException
608 {
609 ManagerResponse response;
610
611 initializeIfNeeded();
612 response = sendAction(new SetVarAction(variable, value));
613 if (response instanceof ManagerError)
614 {
615 logger.error("Unable to set global variable '" + variable + "' to '" + value + "':" + response.getMessage());
616 }
617 }
618
619 public Collection<Voicemailbox> getVoicemailboxes() throws ManagerCommunicationException
620 {
621 final Collection<Voicemailbox> voicemailboxes;
622 ManagerResponse response;
623 final List<String> result;
624
625 initializeIfNeeded();
626 voicemailboxes = new ArrayList<Voicemailbox>();
627 response = sendAction(new CommandAction(SHOW_VOICEMAIL_USERS_COMMAND));
628 if (!(response instanceof CommandResponse))
629 {
630 logger.error("Response to CommandAction(\"" + SHOW_VOICEMAIL_USERS_COMMAND
631 + "\") was not a CommandResponse but " + response);
632 return voicemailboxes;
633 }
634
635 result = ((CommandResponse) response).getResult();
636 if (result == null || result.size() < 1)
637 {
638 return voicemailboxes;
639 }
640
641
642 result.remove(0);
643
644 for (String line : result)
645 {
646 final Matcher matcher;
647 final Voicemailbox voicemailbox;
648 final String context;
649 final String mailbox;
650 final String user;
651
652 matcher = SHOW_VOICEMAIL_USERS_PATTERN.matcher(line);
653 if (!matcher.find())
654 {
655 continue;
656 }
657
658 context = matcher.group(1);
659 mailbox = matcher.group(2);
660 user = matcher.group(3).trim();
661
662 voicemailbox = new Voicemailbox(mailbox, context, user);
663 voicemailboxes.add(voicemailbox);
664 }
665
666
667 for (Voicemailbox voicemailbox : voicemailboxes)
668 {
669 final String fullname;
670
671 fullname = voicemailbox.getMailbox() + "@" + voicemailbox.getContext();
672 response = sendAction(new MailboxCountAction(fullname));
673 if (response instanceof MailboxCountResponse)
674 {
675 MailboxCountResponse mailboxCountResponse;
676
677 mailboxCountResponse = (MailboxCountResponse) response;
678 voicemailbox.setNewMessages(mailboxCountResponse.getNewMessages());
679 voicemailbox.setOldMessages(mailboxCountResponse.getOldMessages());
680 }
681 else
682 {
683 logger.error("Response to MailboxCountAction was not a MailboxCountResponse but " + response);
684 }
685 }
686
687 return voicemailboxes;
688 }
689
690 public List<String> executeCliCommand(String command) throws ManagerCommunicationException
691 {
692 final ManagerResponse response;
693
694 initializeIfNeeded();
695 response = sendAction(new CommandAction(command));
696 if (!(response instanceof CommandResponse))
697 {
698 throw new ManagerCommunicationException("Response to CommandAction(\"" + command
699 + "\") was not a CommandResponse but " + response, null);
700 }
701
702 return ((CommandResponse) response).getResult();
703 }
704
705 public void addAsteriskServerListener(AsteriskServerListener listener) throws ManagerCommunicationException
706 {
707 initializeIfNeeded();
708 synchronized (listeners)
709 {
710 listeners.add(listener);
711 }
712 }
713
714 public void removeAsteriskServerListener(AsteriskServerListener listener)
715 {
716 synchronized (listeners)
717 {
718 listeners.remove(listener);
719 }
720 }
721
722 void fireNewAsteriskChannel(AsteriskChannel channel)
723 {
724 synchronized (listeners)
725 {
726 for (AsteriskServerListener listener : listeners)
727 {
728 try
729 {
730 listener.onNewAsteriskChannel(channel);
731 }
732 catch (Exception e)
733 {
734 logger.warn("Exception in onNewAsteriskChannel()", e);
735 }
736 }
737 }
738 }
739
740 void fireNewMeetMeUser(MeetMeUser user)
741 {
742 synchronized (listeners)
743 {
744 for (AsteriskServerListener listener : listeners)
745 {
746 try
747 {
748 listener.onNewMeetMeUser(user);
749 }
750 catch (Exception e)
751 {
752 logger.warn("Exception in onNewMeetMeUser()", e);
753 }
754 }
755 }
756 }
757
758 ManagerResponse sendActionOnEventConnection(ManagerAction action) throws ManagerCommunicationException
759 {
760 try
761 {
762 return eventConnection.sendAction(action);
763 }
764 catch (Exception e)
765 {
766 throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e);
767 }
768 }
769
770 ManagerResponse sendAction(ManagerAction action) throws ManagerCommunicationException
771 {
772
773 try
774 {
775 return eventConnection.sendAction(action);
776 }
777 catch (Exception e)
778 {
779 throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e);
780 }
781 }
782
783 ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws ManagerCommunicationException
784 {
785
786 try
787 {
788 return eventConnection.sendEventGeneratingAction(action);
789 }
790 catch (Exception e)
791 {
792 throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e);
793 }
794 }
795
796 ResponseEvents sendEventGeneratingAction(EventGeneratingAction action, long timeout)
797 throws ManagerCommunicationException
798 {
799
800 try
801 {
802 return eventConnection.sendEventGeneratingAction(action, timeout);
803 }
804 catch (Exception e)
805 {
806 throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e);
807 }
808 }
809
810 OriginateCallbackData getOriginateCallbackDataByTraceId(String traceId)
811 {
812 synchronized (originateCallbacks)
813 {
814 return originateCallbacks.get(traceId);
815 }
816 }
817
818
819
820 /***
821 * Handles all events received from the Asterisk server.
822 * <p>
823 * Events are queued until channels and queues are initialized and then
824 * delegated to the dispatchEvent method.
825 */
826 public void onManagerEvent(ManagerEvent event)
827 {
828 if (event instanceof ConnectEvent)
829 {
830 handleConnectEvent((ConnectEvent) event);
831 }
832 else if (event instanceof DisconnectEvent)
833 {
834 handleDisconnectEvent((DisconnectEvent) event);
835 }
836 else if (event instanceof NewChannelEvent)
837 {
838 channelManager.handleNewChannelEvent((NewChannelEvent) event);
839 }
840 else if (event instanceof NewExtenEvent)
841 {
842 channelManager.handleNewExtenEvent((NewExtenEvent) event);
843 }
844 else if (event instanceof NewStateEvent)
845 {
846 channelManager.handleNewStateEvent((NewStateEvent) event);
847 }
848 else if (event instanceof NewCallerIdEvent)
849 {
850 channelManager.handleNewCallerIdEvent((NewCallerIdEvent) event);
851 }
852 else if (event instanceof DialEvent)
853 {
854 channelManager.handleDialEvent((DialEvent) event);
855 }
856 else if (event instanceof LinkEvent)
857 {
858 channelManager.handleLinkEvent((LinkEvent) event);
859 }
860 else if (event instanceof UnlinkEvent)
861 {
862 channelManager.handleUnlinkEvent((UnlinkEvent) event);
863 }
864 else if (event instanceof RenameEvent)
865 {
866 channelManager.handleRenameEvent((RenameEvent) event);
867 }
868 else if (event instanceof HangupEvent)
869 {
870 channelManager.handleHangupEvent((HangupEvent) event);
871 }
872 else if (event instanceof CdrEvent)
873 {
874 channelManager.handleCdrEvent((CdrEvent) event);
875 }
876 else if (event instanceof JoinEvent)
877 {
878 queueManager.handleJoinEvent((JoinEvent) event);
879 }
880 else if (event instanceof LeaveEvent)
881 {
882 queueManager.handleLeaveEvent((LeaveEvent) event);
883 }
884 else if (event instanceof AbstractMeetMeEvent)
885 {
886 meetMeManager.handleMeetMeEvent((AbstractMeetMeEvent) event);
887 }
888 else if (event instanceof OriginateResponseEvent)
889 {
890 handleOriginateEvent((OriginateResponseEvent) event);
891 }
892 }
893
894
895
896
897
898 private void handleDisconnectEvent(DisconnectEvent disconnectEvent)
899 {
900
901
902 version = null;
903 versions = null;
904
905
906 channelManager.disconnected();
907 meetMeManager.disconnected();
908 queueManager.disconnected();
909 initialized = false;
910 }
911
912
913
914
915
916 private void handleConnectEvent(ConnectEvent connectEvent)
917 {
918 try
919 {
920 initialize();
921 }
922 catch (Exception e)
923 {
924 logger.error("Unable to reinitialize state after reconnection", e);
925 }
926 }
927
928 private void handleOriginateEvent(OriginateResponseEvent originateEvent)
929 {
930 final String traceId;
931 final OriginateCallbackData callbackData;
932 final OriginateCallback cb;
933 final AsteriskChannelImpl channel;
934 final AsteriskChannelImpl otherChannel;
935
936
937 traceId = originateEvent.getActionId();
938 if (traceId == null)
939 {
940 return;
941 }
942
943 synchronized (originateCallbacks)
944 {
945 callbackData = originateCallbacks.get(traceId);
946 if (callbackData == null)
947 {
948 return;
949 }
950 originateCallbacks.remove(traceId);
951 }
952
953 cb = callbackData.getCallback();
954 channel = channelManager.getChannelImplById(originateEvent.getUniqueId());
955
956 try
957 {
958 if (channel == null)
959 {
960 LiveException cause;
961
962 cause = new NoSuchChannelException("Channel '" + callbackData.getOriginateAction().getChannel()
963 + "' is not available");
964 cb.onFailure(cause);
965 return;
966 }
967
968 if (channel.wasInState(ChannelState.UP))
969 {
970 cb.onSuccess(channel);
971 return;
972 }
973
974 if (channel.wasBusy())
975 {
976 cb.onBusy(channel);
977 return;
978 }
979
980 otherChannel = channelManager.getOtherSideOfLocalChannel(channel);
981
982
983
984 if (otherChannel != null)
985 {
986 final AsteriskChannel dialedChannel;
987
988 dialedChannel = otherChannel.getDialedChannel();
989
990
991
992 if (otherChannel.wasBusy())
993 {
994 cb.onBusy(channel);
995 return;
996 }
997
998
999
1000
1001
1002
1003
1004
1005 if (dialedChannel != null && dialedChannel.wasBusy())
1006 {
1007 cb.onBusy(channel);
1008 return;
1009 }
1010 }
1011
1012
1013 cb.onNoAnswer(channel);
1014 }
1015 catch (Throwable t)
1016 {
1017 logger.warn("Exception dispatching originate progress", t);
1018 }
1019 }
1020
1021 public void shutdown() {
1022
1023 if (eventConnection != null && eventConnection.getState() == ManagerConnectionState.CONNECTED)
1024 {
1025 eventConnection.logoff();
1026 eventConnection = null;
1027 }
1028 if (managerEventListenerProxy != null)
1029 {
1030 managerEventListenerProxy.shutdown();
1031 }
1032 managerEventListenerProxy = null;
1033 eventListener = null;
1034 }
1035 }