org.asteriskjava.live.internal.AsteriskServerImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of asterisk-java Show documentation
Show all versions of asterisk-java Show documentation
The free Java library for Asterisk PBX integration.
The newest version!
/*
* Copyright 2004-2006 Stefan Reuter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.asteriskjava.live.internal;
import org.asteriskjava.AsteriskVersion;
import org.asteriskjava.config.ConfigFile;
import org.asteriskjava.live.*;
import org.asteriskjava.lock.Lockable;
import org.asteriskjava.lock.LockableList;
import org.asteriskjava.lock.LockableMap;
import org.asteriskjava.lock.LockableSet;
import org.asteriskjava.lock.Locker.LockCloser;
import org.asteriskjava.manager.*;
import org.asteriskjava.manager.action.*;
import org.asteriskjava.manager.event.*;
import org.asteriskjava.manager.response.*;
import org.asteriskjava.util.AstUtil;
import org.asteriskjava.util.DateUtil;
import org.asteriskjava.util.Log;
import org.asteriskjava.util.LogFactory;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Default implementation of the {@link AsteriskServer} interface.
*
* @author srt
* @version $Id$
*/
public class AsteriskServerImpl extends Lockable implements AsteriskServer, ManagerEventListener {
private static final String ACTION_ID_PREFIX_ORIGINATE = "AJ_ORIGINATE_";
private static final String SHOW_VERSION_COMMAND = "show version";
private static final String SHOW_VERSION_1_6_COMMAND = "core show version";
private static final String SHOW_VERSION_FILES_COMMAND = "show version files";
private static final String SHOW_VERSION_FILES_1_6_COMMAND = "core show file version";
private static final Pattern SHOW_VERSION_FILES_PATTERN = Pattern.compile("^([\\S]+)\\s+Revision: ([0-9\\.]+)");
private static final String SHOW_VOICEMAIL_USERS_COMMAND = "show voicemail users";
private static final String SHOW_VOICEMAIL_USERS_1_6_COMMAND = "voicemail show users";
private static final Pattern SHOW_VOICEMAIL_USERS_PATTERN = Pattern.compile("^(\\S+)\\s+(\\S+)\\s+(.{25})");
private final Log logger = LogFactory.getLog(this.getClass());
/**
* The underlying manager connection used to receive events from Asterisk.
*/
private ManagerConnection eventConnection;
private ManagerEventListener eventListener = null;
private ManagerEventListenerProxy managerEventListenerProxy;
private boolean initialized = false;
private boolean initializing = false;
final LockableSet listeners;
final ChannelManager channelManager;
final MeetMeManager meetMeManager;
final QueueManager queueManager;
final AgentManager agentManager;
/**
* The exact version string of the Asterisk server we are connected to.
*
* Contains null
until lazily initialized.
*/
private String version;
/**
* Holds the version of Asterisk's source files.
*
* That corresponds to the output of the CLI command
* show version files
.
*
* Contains null
until lazily initialized.
*/
private LockableMap versions;
/**
* Maps the traceId to the corresponding callback data.
*/
private final LockableMap originateCallbacks;
private final AtomicLong idCounter;
/* config options */
/**
* Flag to skip initializing queues as that results in a timeout on Asterisk
* 1.0.x.
*/
private boolean skipQueues;
/**
* Set to true
to not handle ManagerEvents in the reader tread
* but process them asynchronously. This is a good idea :)
*/
private boolean asyncEventHandling = true;
/**
* The chainListener allows a listener to receive manager events after they
* have been processed by the AsteriskServer. If the AsteriskServer is
* handling messages using the asyncEventHandling then these messages will
* also be async. You would use the chainListener if you are processing raw
* events and using the AJ live ChannelManager. If you don't use the chain
* listener then you can't be certain that a channel name passed in a raw
* event will match the channel name held by the Channel Manager. By
* chaining events you can be certain that events such as channel Rename
* events have been processed by the live ChannelManager before you receive
* an event and as such the names will always match.
*/
private LockableList chainListeners = new LockableList<>(new ArrayList<>());
/**
* Creates a new instance.
*/
public AsteriskServerImpl() {
idCounter = new AtomicLong();
listeners = new LockableSet<>(new LinkedHashSet<>());
originateCallbacks = new LockableMap<>(new HashMap<>());
channelManager = new ChannelManager(this);
agentManager = new AgentManager(this);
meetMeManager = new MeetMeManager(this, channelManager);
queueManager = new QueueManager(this, channelManager);
}
/**
* Creates a new instance.
*
* @param eventConnection the ManagerConnection to use for receiving events
* from Asterisk.
*/
public AsteriskServerImpl(ManagerConnection eventConnection) {
this();
setManagerConnection(eventConnection); // todo: !!! Possible bug !!!:
// call to overridable method
// over object construction
}
/**
* Determines if queue status is retrieved at startup. If you don't need
* queue information and still run Asterisk 1.0.x you can set this to
* true
to circumvent the startup delay caused by the missing
* QueueStatusComplete event.
* Default is false
.
*
* @param skipQueues true
to skip queue initialization,
* false
to not skip.
* @since 0.2
*/
public void setSkipQueues(boolean skipQueues) {
this.skipQueues = skipQueues;
}
public void setManagerConnection(ManagerConnection eventConnection) {
if (this.eventConnection != null) {
throw new IllegalStateException("ManagerConnection already set.");
}
this.eventConnection = eventConnection;
}
public ManagerConnection getManagerConnection() {
return eventConnection;
}
public void initialize() throws ManagerCommunicationException {
initializeIfNeeded();
}
private void initializeIfNeeded() throws ManagerCommunicationException {
try (LockCloser closer = this.withLock()) {
if (initialized || initializing) {
return;
}
if (asyncEventHandling && managerEventListenerProxy == null) {
managerEventListenerProxy = new ManagerEventListenerProxy(this);
eventConnection.addEventListener(managerEventListenerProxy);
} else if (!asyncEventHandling && eventListener == null) {
eventListener = this;
eventConnection.addEventListener(eventListener);
}
initializing = true;
if (eventConnection.getState() == ManagerConnectionState.INITIAL
|| eventConnection.getState() == ManagerConnectionState.DISCONNECTED) {
try {
eventConnection.login();
} catch (Exception e) {
throw new ManagerCommunicationException("Unable to login: " + e.getMessage(), e);
}
}
channelManager.initialize();
agentManager.initialize();
meetMeManager.initialize();
if (!skipQueues) {
queueManager.initialize();
}
if (asyncEventHandling && managerEventListenerProxy == null) {
managerEventListenerProxy = new ManagerEventListenerProxy(this);
eventConnection.addEventListener(managerEventListenerProxy);
} else if (!asyncEventHandling && eventListener == null) {
eventListener = this;
eventConnection.addEventListener(eventListener);
}
logger.info("Initializing done");
initializing = false;
initialized = true;
}
}
/* Implementation of the AsteriskServer interface */
public AsteriskChannel originateToExtension(String channel, String context, String exten, int priority, long timeout)
throws ManagerCommunicationException, NoSuchChannelException {
return originateToExtension(channel, context, exten, priority, timeout, null, null);
}
public AsteriskChannel originateToExtension(String channel, String context, String exten, int priority, long timeout,
CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException {
final OriginateAction originateAction;
originateAction = new OriginateAction();
originateAction.setChannel(channel);
originateAction.setContext(context);
originateAction.setExten(exten);
originateAction.setPriority(priority);
originateAction.setTimeout(timeout);
if (callerId != null) {
originateAction.setCallerId(callerId.toString());
}
originateAction.setVariables(variables);
return originate(originateAction);
}
public AsteriskChannel originateToApplication(String channel, String application, String data, long timeout)
throws ManagerCommunicationException, NoSuchChannelException {
return originateToApplication(channel, application, data, timeout, null, null);
}
public AsteriskChannel originateToApplication(String channel, String application, String data, long timeout,
CallerId callerId, Map variables) throws ManagerCommunicationException, NoSuchChannelException {
final OriginateAction originateAction;
originateAction = new OriginateAction();
originateAction.setChannel(channel);
originateAction.setApplication(application);
originateAction.setData(data);
originateAction.setTimeout(timeout);
if (callerId != null) {
originateAction.setCallerId(callerId.toString());
}
originateAction.setVariables(variables);
return originate(originateAction);
}
public AsteriskChannel originate(OriginateAction originateAction)
throws ManagerCommunicationException, NoSuchChannelException {
final ResponseEvents responseEvents;
final Iterator responseEventIterator;
String uniqueId;
AsteriskChannel channel = null;
// must set async to true to receive OriginateEvents.
originateAction.setAsync(Boolean.TRUE);
initializeIfNeeded();
// 2000 ms extra for the OriginateFailureEvent should be fine
responseEvents = sendEventGeneratingAction(originateAction, originateAction.getTimeout() + 2000);
responseEventIterator = responseEvents.getEvents().iterator();
if (responseEventIterator.hasNext()) {
ResponseEvent responseEvent;
responseEvent = responseEventIterator.next();
if (responseEvent instanceof OriginateResponseEvent) {
uniqueId = ((OriginateResponseEvent) responseEvent).getUniqueId();
logger.debug(responseEvent.getClass().getName() + " received with uniqueId " + uniqueId);
channel = getChannelById(uniqueId);
}
}
if (channel == null) {
throw new NoSuchChannelException("Channel '" + originateAction.getChannel() + "' is not available");
}
return channel;
}
public void originateToExtensionAsync(String channel, String context, String exten, int priority, long timeout,
OriginateCallback cb) throws ManagerCommunicationException {
originateToExtensionAsync(channel, context, exten, priority, timeout, null, null, cb);
}
public void originateToExtensionAsync(String channel, String context, String exten, int priority, long timeout,
CallerId callerId, Map variables, OriginateCallback cb) throws ManagerCommunicationException {
final OriginateAction originateAction;
originateAction = new OriginateAction();
originateAction.setChannel(channel);
originateAction.setContext(context);
originateAction.setExten(exten);
originateAction.setPriority(priority);
originateAction.setTimeout(timeout);
if (callerId != null) {
originateAction.setCallerId(callerId.toString());
}
originateAction.setVariables(variables);
originateAsync(originateAction, cb);
}
public void originateToApplicationAsync(String channel, String application, String data, long timeout,
OriginateCallback cb) throws ManagerCommunicationException {
originateToApplicationAsync(channel, application, data, timeout, null, null, cb);
}
public void originateToApplicationAsync(String channel, String application, String data, long timeout, CallerId callerId,
Map variables, OriginateCallback cb) throws ManagerCommunicationException {
final OriginateAction originateAction;
originateAction = new OriginateAction();
originateAction.setChannel(channel);
originateAction.setApplication(application);
originateAction.setData(data);
originateAction.setTimeout(timeout);
if (callerId != null) {
originateAction.setCallerId(callerId.toString());
}
originateAction.setVariables(variables);
originateAsync(originateAction, cb);
}
public void originateAsync(OriginateAction originateAction, OriginateCallback cb) throws ManagerCommunicationException {
final Map variables;
final String traceId;
traceId = ACTION_ID_PREFIX_ORIGINATE + idCounter.getAndIncrement();
if (originateAction.getVariables() == null) {
variables = new HashMap<>();
} else {
variables = new HashMap<>(originateAction.getVariables());
}
// prefix variable name by "__" to enable variable inheritence across
// channels
variables.put("__" + Constants.VARIABLE_TRACE_ID, traceId);
originateAction.setVariables(variables);
// async must be set to true to receive OriginateEvents.
originateAction.setAsync(Boolean.TRUE);
originateAction.setActionId(traceId);
if (cb != null) {
final OriginateCallbackData callbackData;
callbackData = new OriginateCallbackData(originateAction, DateUtil.getDate(), cb);
// register callback
try (LockCloser closer = originateCallbacks.withLock()) {
originateCallbacks.put(traceId, callbackData);
}
}
initializeIfNeeded();
sendActionOnEventConnection(originateAction);
}
public Collection getChannels() throws ManagerCommunicationException {
initializeIfNeeded();
return channelManager.getChannels();
}
public AsteriskChannel getChannelByName(String name) throws ManagerCommunicationException {
initializeIfNeeded();
return channelManager.getChannelImplByName(name);
}
public AsteriskChannel getChannelById(String id) throws ManagerCommunicationException {
initializeIfNeeded();
return channelManager.getChannelImplById(id);
}
public Collection getMeetMeRooms() throws ManagerCommunicationException {
initializeIfNeeded();
return meetMeManager.getMeetMeRooms();
}
public MeetMeRoom getMeetMeRoom(String name) throws ManagerCommunicationException {
initializeIfNeeded();
return meetMeManager.getOrCreateRoomImpl(name);
}
public Collection getQueues() throws ManagerCommunicationException {
initializeIfNeeded();
return queueManager.getQueues();
}
@Override
public AsteriskQueue getQueueByName(String queueName) {
initializeIfNeeded();
return queueManager.getQueueByName(queueName);
}
@Override
public List getQueuesUpdatedAfter(Date date) {
initializeIfNeeded();
return queueManager.getQueuesUpdatedAfter(date);
}
public String getVersion() throws ManagerCommunicationException {
try (LockCloser closer = this.withLock()) {
final ManagerResponse response;
final String command;
initializeIfNeeded();
if (version == null) {
if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) {
command = SHOW_VERSION_1_6_COMMAND;
} else {
command = SHOW_VERSION_COMMAND;
}
response = sendAction(new CommandAction(command));
if (response instanceof CommandResponse) {
final List result;
result = ((CommandResponse) response).getResult();
if (!result.isEmpty()) {
version = result.get(0);
}
} else {
logger.error("Response to CommandAction(\"" + command + "\") was not a CommandResponse but " + response);
}
}
return version;
}
}
public int[] getVersion(String file) throws ManagerCommunicationException {
String fileVersion = null;
String[] parts;
int[] intParts;
initializeIfNeeded();
if (versions == null) {
LockableMap map;
ManagerResponse response;
map = new LockableMap<>(new HashMap<>());
try {
final String command;
if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) {
command = SHOW_VERSION_FILES_1_6_COMMAND;
} else {
command = SHOW_VERSION_FILES_COMMAND;
}
response = sendAction(new CommandAction(command));
if (response instanceof CommandResponse) {
List result;
result = ((CommandResponse) response).getResult();
for (int i = 2; i < result.size(); i++) {
String line;
Matcher matcher;
line = result.get(i);
matcher = SHOW_VERSION_FILES_PATTERN.matcher(line);
if (matcher.find()) {
String key = matcher.group(1);
String value = matcher.group(2);
map.put(key, value);
}
}
fileVersion = map.get(file);
versions = map;
} else {
logger.error("Response to CommandAction(\"" + command + "\") was not a CommandResponse but " + response);
}
} catch (Exception e) {
logger.warn("Unable to send '" + SHOW_VERSION_FILES_COMMAND + "' command.", e);
}
} else {
try (LockCloser closer = versions.withLock()) {
fileVersion = versions.get(file);
}
}
if (fileVersion == null) {
return null;
}
parts = fileVersion.split("\\.");
intParts = new int[parts.length];
for (int i = 0; i < parts.length; i++) {
try {
intParts[i] = Integer.parseInt(parts[i]);
} catch (NumberFormatException e) {
intParts[i] = 0;
}
}
return intParts;
}
public String getGlobalVariable(String variable) throws ManagerCommunicationException {
ManagerResponse response;
String value;
initializeIfNeeded();
response = sendAction(new GetVarAction(variable));
if (response instanceof ManagerError) {
return null;
}
value = response.getAttribute("Value");
if (value == null) {
value = response.getAttribute(variable); // for Asterisk 1.0.x
}
return value;
}
public void setGlobalVariable(String variable, String value) throws ManagerCommunicationException {
ManagerResponse response;
initializeIfNeeded();
response = sendAction(new SetVarAction(variable, value));
if (response instanceof ManagerError) {
logger.error("Unable to set global variable '" + variable + "' to '" + value + "':" + response.getMessage());
}
}
public Collection getVoicemailboxes() throws ManagerCommunicationException {
final Collection voicemailboxes;
ManagerResponse response;
final List result;
initializeIfNeeded();
voicemailboxes = new ArrayList<>();
if (eventConnection.getVersion().isAtLeast(AsteriskVersion.ASTERISK_1_6)) {
response = sendAction(new CommandAction(SHOW_VOICEMAIL_USERS_1_6_COMMAND));
} else {
response = sendAction(new CommandAction(SHOW_VOICEMAIL_USERS_COMMAND));
}
if (!(response instanceof CommandResponse)) {
logger.error("Response to CommandAction(\"" + SHOW_VOICEMAIL_USERS_COMMAND + "\") was not a CommandResponse but "
+ response);
return voicemailboxes;
}
result = ((CommandResponse) response).getResult();
if (result == null || result.isEmpty()) {
return voicemailboxes;
}
// remove headline
result.remove(0);
for (String line : result) {
final Matcher matcher;
final Voicemailbox voicemailbox;
final String context;
final String mailbox;
final String user;
matcher = SHOW_VOICEMAIL_USERS_PATTERN.matcher(line);
if (!matcher.find()) {
continue;
}
context = matcher.group(1);
mailbox = matcher.group(2);
user = matcher.group(3).trim();
voicemailbox = new Voicemailbox(mailbox, context, user);
voicemailboxes.add(voicemailbox);
}
// get message count for each mailbox
for (Voicemailbox voicemailbox : voicemailboxes) {
final String fullname;
fullname = voicemailbox.getMailbox() + "@" + voicemailbox.getContext();
response = sendAction(new MailboxCountAction(fullname));
if (response instanceof MailboxCountResponse) {
MailboxCountResponse mailboxCountResponse;
mailboxCountResponse = (MailboxCountResponse) response;
voicemailbox.setNewMessages(mailboxCountResponse.getNewMessages());
voicemailbox.setOldMessages(mailboxCountResponse.getOldMessages());
} else {
logger.error("Response to MailboxCountAction was not a MailboxCountResponse but " + response);
}
}
return voicemailboxes;
}
public List executeCliCommand(String command) throws ManagerCommunicationException {
final ManagerResponse response;
initializeIfNeeded();
response = sendAction(new CommandAction(command));
if (!(response instanceof CommandResponse)) {
throw new ManagerCommunicationException(
"Response to CommandAction(\"" + command + "\") was not a CommandResponse but " + response, null);
}
return ((CommandResponse) response).getResult();
}
public boolean isModuleLoaded(String module) throws ManagerCommunicationException {
return sendAction(new ModuleCheckAction(module)) instanceof ModuleCheckResponse;
}
public void loadModule(String module) throws ManagerCommunicationException {
sendModuleLoadAction(module, ModuleLoadAction.LOAD_TYPE_LOAD);
}
public void unloadModule(String module) throws ManagerCommunicationException {
sendModuleLoadAction(module, ModuleLoadAction.LOAD_TYPE_UNLOAD);
}
public void reloadModule(String module) throws ManagerCommunicationException {
sendModuleLoadAction(module, ModuleLoadAction.LOAD_TYPE_RELOAD);
}
public void reloadAllModules() throws ManagerCommunicationException {
sendModuleLoadAction(null, ModuleLoadAction.LOAD_TYPE_RELOAD);
}
protected void sendModuleLoadAction(String module, String loadType) throws ManagerCommunicationException {
final ManagerResponse response;
response = sendAction(new ModuleLoadAction(module, loadType));
if (response instanceof ManagerError) {
final ManagerError error = (ManagerError) response;
throw new ManagerCommunicationException(error.getMessage(), null);
}
}
public ConfigFile getConfig(String filename) throws ManagerCommunicationException {
final ManagerResponse response;
final GetConfigResponse getConfigResponse;
initializeIfNeeded();
response = sendAction(new GetConfigAction(filename));
if (!(response instanceof GetConfigResponse)) {
throw new ManagerCommunicationException(
"Response to GetConfigAction(\"" + filename + "\") was not a CommandResponse but " + response, null);
}
getConfigResponse = (GetConfigResponse) response;
final Map categoryMap = getConfigResponse.getCategories();
final Map> categories = new LinkedHashMap<>();
for (Map.Entry categoryEntry : categoryMap.entrySet()) {
final List lines;
final Map lineMap = getConfigResponse.getLines(categoryEntry.getKey());
if (lineMap == null) {
lines = new ArrayList<>();
} else {
lines = new ArrayList<>(lineMap.values());
}
categories.put(categoryEntry.getValue(), lines);
}
return new ConfigFileImpl(filename, categories);
}
@Override
public void addAsteriskServerListener(AsteriskServerListener listener) throws ManagerCommunicationException {
initializeIfNeeded();
try (LockCloser closer = listeners.withLock()) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
}
@Override
public void removeAsteriskServerListener(AsteriskServerListener listener) {
try (LockCloser closer = listeners.withLock()) {
listeners.remove(listener);
}
}
@Override
public boolean isAsteriskServerListening(AsteriskServerListener listener) {
return listeners.contains(listener);
}
public void addChainListener(ManagerEventListener chainListener) {
try (LockCloser closer = this.chainListeners.withLock()) {
if (!this.chainListeners.contains(chainListener))
this.chainListeners.add(chainListener);
}
}
public void removeChainListener(ManagerEventListener chainListener) {
this.chainListeners.remove(chainListener);
}
void fireNewAsteriskChannel(AsteriskChannel channel) {
try (LockCloser closer = listeners.withLock()) {
for (AsteriskServerListener listener : listeners) {
try {
listener.onNewAsteriskChannel(channel);
} catch (Exception e) {
logger.warn("Exception in onNewAsteriskChannel()", e);
}
}
}
}
void fireNewMeetMeUser(MeetMeUser user) {
try (LockCloser closer = listeners.withLock()) {
for (AsteriskServerListener listener : listeners) {
try {
listener.onNewMeetMeUser(user);
} catch (Exception e) {
logger.warn("Exception in onNewMeetMeUser()", e);
}
}
}
}
ManagerResponse sendActionOnEventConnection(ManagerAction action) throws ManagerCommunicationException {
try {
return eventConnection.sendAction(action);
} catch (Exception e) {
throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e);
}
}
ManagerResponse sendAction(ManagerAction action) throws ManagerCommunicationException {
// return connectionPool.sendAction(action);
try {
return eventConnection.sendAction(action);
} catch (Exception e) {
throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e);
}
}
ResponseEvents sendEventGeneratingAction(EventGeneratingAction action) throws ManagerCommunicationException {
// return connectionPool.sendEventGeneratingAction(action);
try {
return eventConnection.sendEventGeneratingAction(action);
} catch (Exception e) {
throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e);
}
}
ResponseEvents
sendEventGeneratingAction(EventGeneratingAction action, long timeout) throws ManagerCommunicationException {
// return connectionPool.sendEventGeneratingAction(action, timeout);
try {
return eventConnection.sendEventGeneratingAction(action, timeout);
} catch (Exception e) {
throw ManagerCommunicationExceptionMapper.mapSendActionException(action.getAction(), e);
}
}
OriginateCallbackData getOriginateCallbackDataByTraceId(String traceId) {
try (LockCloser closer = originateCallbacks.withLock()) {
return originateCallbacks.get(traceId);
}
}
/* Implementation of the ManagerEventListener interface */
/**
* Handles all events received from the Asterisk server.
* Events are queued until channels and queues are initialized and then
* delegated to the dispatchEvent method.
*/
public void onManagerEvent(ManagerEvent event) {
// Handle Channel related events
if (event instanceof ConnectEvent) {
handleConnectEvent((ConnectEvent) event);
} else if (event instanceof DisconnectEvent) {
handleDisconnectEvent((DisconnectEvent) event);
} else if (event instanceof NewChannelEvent) {
channelManager.handleNewChannelEvent((NewChannelEvent) event);
} else if (event instanceof NewExtenEvent) {
channelManager.handleNewExtenEvent((NewExtenEvent) event);
} else if (event instanceof NewStateEvent) {
channelManager.handleNewStateEvent((NewStateEvent) event);
} else if (event instanceof NewCallerIdEvent) {
channelManager.handleNewCallerIdEvent((NewCallerIdEvent) event);
} else if (event instanceof DialEvent) {
channelManager.handleDialEvent((DialEvent) event);
} else if (event instanceof BridgeEvent) {
channelManager.handleBridgeEvent((BridgeEvent) event);
} else if (event instanceof RenameEvent) {
channelManager.handleRenameEvent((RenameEvent) event);
} else if (event instanceof HangupEvent) {
channelManager.handleHangupEvent((HangupEvent) event);
} else if (event instanceof CdrEvent) {
channelManager.handleCdrEvent((CdrEvent) event);
} else if (event instanceof VarSetEvent) {
channelManager.handleVarSetEvent((VarSetEvent) event);
} else if (event instanceof DtmfEvent) {
channelManager.handleDtmfEvent((DtmfEvent) event);
} else if (event instanceof MonitorStartEvent) {
channelManager.handleMonitorStartEvent((MonitorStartEvent) event);
} else if (event instanceof MonitorStopEvent) {
channelManager.handleMonitorStopEvent((MonitorStopEvent) event);
}
// End of channel related events
// Handle parking related event
else if (event instanceof ParkedCallEvent) {
channelManager.handleParkedCallEvent((ParkedCallEvent) event);
} else if (event instanceof ParkedCallGiveUpEvent) {
channelManager.handleParkedCallGiveUpEvent((ParkedCallGiveUpEvent) event);
} else if (event instanceof ParkedCallTimeOutEvent) {
channelManager.handleParkedCallTimeOutEvent((ParkedCallTimeOutEvent) event);
} else if (event instanceof UnparkedCallEvent) {
channelManager.handleUnparkedCallEvent((UnparkedCallEvent) event);
}
// End of parking related events
// Handle queue related event
else if (event instanceof JoinEvent) {
queueManager.handleJoinEvent((JoinEvent) event);
} else if (event instanceof LeaveEvent) {
queueManager.handleLeaveEvent((LeaveEvent) event);
} else if (event instanceof QueueMemberStatusEvent) {
queueManager.handleQueueMemberStatusEvent((QueueMemberStatusEvent) event);
} else if (event instanceof QueueMemberPenaltyEvent) {
queueManager.handleQueueMemberPenaltyEvent((QueueMemberPenaltyEvent) event);
} else if (event instanceof QueueMemberAddedEvent) {
queueManager.handleQueueMemberAddedEvent((QueueMemberAddedEvent) event);
} else if (event instanceof QueueMemberRemovedEvent) {
queueManager.handleQueueMemberRemovedEvent((QueueMemberRemovedEvent) event);
} else if (event instanceof QueueMemberPausedEvent) {
queueManager.handleQueueMemberPausedEvent((QueueMemberPausedEvent) event);
} else if (event instanceof QueueCallerJoinEvent) {
queueManager.handleJoinEvent((QueueCallerJoinEvent) event);
} else if (event instanceof QueueCallerLeaveEvent) {
queueManager.handleLeaveEvent((QueueCallerLeaveEvent) event);
}
// >>>>>> AJ 94
// Handle meetMeEvents
else if (event instanceof AbstractMeetMeEvent) {
meetMeManager.handleMeetMeEvent((AbstractMeetMeEvent) event);
} else if (event instanceof OriginateResponseEvent) {
handleOriginateEvent((OriginateResponseEvent) event);
}
// Handle agents-related events
else if (event instanceof AgentsEvent) {
agentManager.handleAgentsEvent((AgentsEvent) event);
} else if (event instanceof AgentCalledEvent) {
agentManager.handleAgentCalledEvent((AgentCalledEvent) event);
} else if (event instanceof AgentConnectEvent) {
agentManager.handleAgentConnectEvent((AgentConnectEvent) event);
} else if (event instanceof AgentCompleteEvent) {
agentManager.handleAgentCompleteEvent((AgentCompleteEvent) event);
} else if (event instanceof AgentCallbackLoginEvent) {
agentManager.handleAgentCallbackLoginEvent((AgentCallbackLoginEvent) event);
} else if (event instanceof AgentCallbackLogoffEvent) {
agentManager.handleAgentCallbackLogoffEvent((AgentCallbackLogoffEvent) event);
} else if (event instanceof AgentLoginEvent) {
agentManager.handleAgentLoginEvent((AgentLoginEvent) event);
} else if (event instanceof AgentLogoffEvent) {
agentManager.handleAgentLogoffEvent((AgentLogoffEvent) event);
}
// End of agent-related events
// dispatch the events to the chainListener if they exist.
fireChainListeners(event);
}
/**
* dispatch the event to the chainListener if they exist.
*
* @param event
*/
private void fireChainListeners(ManagerEvent event) {
try (LockCloser closer = this.chainListeners.withLock()) {
for (ManagerEventListener listener : this.chainListeners)
listener.onManagerEvent(event);
}
}
/*
* Resets the internal state when the connection to the asterisk server is
* lost.
*/
private void handleDisconnectEvent(DisconnectEvent disconnectEvent) {
// reset version information as it might have changed while Asterisk
// restarted
version = null;
versions = null;
// same for channels, agents and queues rooms, they are reinitialized
// when reconnected
channelManager.disconnected();
agentManager.disconnected();
meetMeManager.disconnected();
queueManager.disconnected();
initialized = false;
initializing = false;
}
/*
* Requests the current state from the asterisk server after the connection
* to the asterisk server is restored.
*/
private void handleConnectEvent(ConnectEvent connectEvent) {
try {
initialize();
channelManager.initialize();
agentManager.initialize();
meetMeManager.initialize();
if (!skipQueues) {
queueManager.initialize();
}
logger.info("Initializing done");
initialized = true;
initializing = false;
} catch (Exception e) {
logger.error("Unable to reinitialize state after reconnection", e);
}
}
private void handleOriginateEvent(OriginateResponseEvent originateEvent) {
final String traceId;
final OriginateCallbackData callbackData;
final OriginateCallback cb;
final AsteriskChannelImpl channel;
final AsteriskChannelImpl otherChannel; // the other side if local
// channel
traceId = originateEvent.getActionId();
if (traceId == null) {
return;
}
try (LockCloser closer = originateCallbacks.withLock()) {
callbackData = originateCallbacks.get(traceId);
if (callbackData == null) {
return;
}
originateCallbacks.remove(traceId);
}
cb = callbackData.getCallback();
if (!AstUtil.isNull(originateEvent.getUniqueId())) {
channel = channelManager.getChannelImplById(originateEvent.getUniqueId());
} else {
channel = callbackData.getChannel();
}
try {
if (channel == null) {
final LiveException cause;
cause = new NoSuchChannelException(
"Channel '" + callbackData.getOriginateAction().getChannel() + "' is not available");
cb.onFailure(cause);
return;
}
if (channel.wasInState(ChannelState.UP)) {
cb.onSuccess(channel);
return;
}
if (channel.wasBusy()) {
cb.onBusy(channel);
return;
}
otherChannel = channelManager.getOtherSideOfLocalChannel(channel);
// special treatment of local channels:
// the interesting things happen to the other side so we have a look
// at that
if (otherChannel != null) {
final AsteriskChannel dialedChannel;
dialedChannel = otherChannel.getDialedChannel();
// on busy the other channel is in state busy when we receive
// the originate event
if (otherChannel.wasBusy()) {
cb.onBusy(channel);
return;
}
// alternative:
// on busy the dialed channel is hung up when we receive the
// originate event having a look at the hangup cause reveals the
// information we are interested in
// this alternative has the drawback that there might by
// multiple channels that have been dialed by the local channel
// but we only look at the last one.
if (dialedChannel != null && dialedChannel.wasBusy()) {
cb.onBusy(channel);
return;
}
}
// if nothing else matched we asume no answer
cb.onNoAnswer(channel);
} catch (Throwable t) {
logger.warn("Exception dispatching originate progress", t);
}
}
@Override
public void shutdown() {
if (eventConnection != null && (eventConnection.getState() == ManagerConnectionState.CONNECTED
|| eventConnection.getState() == ManagerConnectionState.RECONNECTING)) {
try {
eventConnection.logoff();
} catch (Exception ignore) {
}
}
if (managerEventListenerProxy != null) {
if (eventConnection != null) {
eventConnection.removeEventListener(managerEventListenerProxy);
}
managerEventListenerProxy.shutdown();
}
if (eventConnection != null && eventListener != null) {
eventConnection.removeEventListener(eventListener);
}
managerEventListenerProxy = null;
eventListener = null;
if (initialized) {// incredible, but it happened
handleDisconnectEvent(null);
} // i
}// shutdown
public List getPeerEntries() throws ManagerCommunicationException {
ResponseEvents responseEvents = sendEventGeneratingAction(new SipPeersAction(), 2000);
List peerEntries = new ArrayList<>(30);
for (ResponseEvent re : responseEvents.getEvents()) {
if (re instanceof PeerEntryEvent) {
peerEntries.add((PeerEntryEvent) re);
}
}
return peerEntries;
}
public DbGetResponseEvent dbGet(String family, String key) throws ManagerCommunicationException {
ResponseEvents responseEvents = sendEventGeneratingAction(new DbGetAction(family, key), 2000);
DbGetResponseEvent dbgre = null;
for (ResponseEvent re : responseEvents.getEvents()) {
dbgre = (DbGetResponseEvent) re;
}
return dbgre;
}
public void dbDel(String family, String key) throws ManagerCommunicationException {
// The following only works with BRIStuffed asrterisk: sendAction(new
// DbDelAction(family,key));
// Use cli command instead ...
sendAction(new CommandAction("database del " + family + " " + key));
}
public void dbPut(String family, String key, String value) throws ManagerCommunicationException {
sendAction(new DbPutAction(family, key, value));
}
public AsteriskChannel getChannelByNameAndActive(String name) throws ManagerCommunicationException {
initializeIfNeeded();
return channelManager.getChannelImplByNameAndActive(name);
}
public Collection getAgents() throws ManagerCommunicationException {
initializeIfNeeded();
return agentManager.getAgents();
}
void fireNewAgent(AsteriskAgentImpl agent) {
try (LockCloser closer = listeners.withLock()) {
for (AsteriskServerListener listener : listeners) {
try {
listener.onNewAgent(agent);
} catch (Exception e) {
logger.warn("Exception in onNewAgent()", e);
}
}
}
}
void fireNewQueueEntry(AsteriskQueueEntry entry) {
try (LockCloser closer = listeners.withLock()) {
for (AsteriskServerListener listener : listeners) {
try {
listener.onNewQueueEntry(entry);
} catch (Exception e) {
logger.warn("Exception in onNewQueueEntry()", e);
}
}
}
}
/* OCTAVIO LUNA */
@Override
public void forceQueuesMonitor(boolean force) {
queueManager.forceQueuesMonitor(force);
}
@Override
public boolean isQueuesMonitorForced() {
return queueManager.isQueuesMonitorForced();
}
}