package org.asteriskjava.fastagi;
import org.asteriskjava.manager.ManagerEventListener;
import org.asteriskjava.manager.ManagerConnection;
import org.asteriskjava.manager.event.ManagerEvent;
import org.asteriskjava.manager.event.AsyncAgiEvent;
import org.asteriskjava.manager.event.RenameEvent;
import org.asteriskjava.util.Log;
import org.asteriskjava.util.LogFactory;
import org.asteriskjava.fastagi.internal.AsyncAgiConnectionHandler;
import java.util.Map;
import java.util.HashMap;
/**
* AGI server for AGI over the Manager API (AsyncAGI).<p>
* AsyncAGI is available since Asterisk 1.6.
*
* @since 1.0.0
*/
public class AsyncAgiServer extends AbstractAgiServer implements ManagerEventListener
{
private final Log logger = LogFactory.getLog(getClass());
private final Map<Integer, AsyncAgiConnectionHandler> connectionHandlers;
public AsyncAgiServer()
{
this.connectionHandlers = new HashMap<Integer, AsyncAgiConnectionHandler>();
}
public AsyncAgiServer(MappingStrategy mappingStrategy)
{
this();
setMappingStrategy(mappingStrategy);
}
public AsyncAgiServer(AgiScript agiScript)
{
this();
setMappingStrategy(new StaticMappingStrategy(agiScript));
}
public void shutdown()
{
super.shutdown();
}
public void onManagerEvent(ManagerEvent event)
{
if (event instanceof AsyncAgiEvent)
{
handleAsyncAgiEvent((AsyncAgiEvent) event);
}
else if (event instanceof RenameEvent)
{
handleRenameEvent((RenameEvent) event);
}
}
private void handleAsyncAgiEvent(AsyncAgiEvent asyncAgiEvent)
{
final ManagerConnection connection;
final String channelName;
final AsyncAgiConnectionHandler connectionHandler;
connection = (ManagerConnection) asyncAgiEvent.getSource();
channelName = asyncAgiEvent.getChannel();
if (asyncAgiEvent.isStart())
{
connectionHandler = new AsyncAgiConnectionHandler(getMappingStrategy(), asyncAgiEvent);
setConnectionHandler(connection, channelName, connectionHandler);
execute(connectionHandler);
}
else
{
connectionHandler = getConnectionHandler(connection, channelName);
if (connectionHandler == null)
{
logger.info("No AsyncAgiConnectionHandler registered for channel " + channelName + ": Ignoring AsyncAgiEvent");
return;
}
if (asyncAgiEvent.isExec())
{
connectionHandler.onAsyncAgiExecEvent(asyncAgiEvent);
}
else if (asyncAgiEvent.isEnd())
{
connectionHandler.onAsyncAgiEndEvent(asyncAgiEvent);
removeConnectionHandler(connection, channelName);
}
else
{
logger.warn("Ignored unknown AsyncAgiEvent of sub type '" + asyncAgiEvent.getSubEvent() + "'");
}
}
}
private void handleRenameEvent(RenameEvent renameEvent)
{
final ManagerConnection connection = (ManagerConnection) renameEvent.getSource();
final AsyncAgiConnectionHandler connectionHandler = getConnectionHandler(connection, renameEvent.getChannel());
if (connectionHandler == null)
{
return;
}
removeConnectionHandler(connection, renameEvent.getChannel());
setConnectionHandler(connection, renameEvent.getNewname(), connectionHandler);
connectionHandler.updateChannelName(renameEvent.getNewname());
}
private AsyncAgiConnectionHandler getConnectionHandler(ManagerConnection connection, String channelName)
{
synchronized (connectionHandlers)
{
return connectionHandlers.get(calculateHashKey(connection, channelName));
}
}
private void setConnectionHandler(ManagerConnection connection, String channelName, AsyncAgiConnectionHandler connectionHandler)
{
synchronized (connectionHandlers)
{
connectionHandlers.put(calculateHashKey(connection, channelName), connectionHandler);
}
}
private void removeConnectionHandler(ManagerConnection connection, String channelName)
{
synchronized (connectionHandlers)
{
connectionHandlers.remove(calculateHashKey(connection, channelName));
}
}
private Integer calculateHashKey(ManagerConnection connection, String channelName)
{
return connection.hashCode() * 31 + channelName.hashCode();
}
}