package org.voicebridge;
import java.util.*;
import java.text.ParseException;
import java.net.*;
import java.io.File;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sun.voip.server.*;
import com.sun.voip.client.*;
import com.sun.voip.*;
public class Application implements CallEventListener {
private static final Logger log = LoggerFactory.getLogger(Application.class);
private String version = "0.0.0.1";
private Config config;
private Map< String, Object > callObjects = new HashMap< String, Object >();
private Map< String, CallParticipant > callPartipants = new HashMap< String, CallParticipant >();
private static ArrayList<ConferenceMonitor> conferenceMonitors = new ArrayList<ConferenceMonitor>();
private static ArrayList<Object> incomingCallListeners = new ArrayList<Object>();
private static ArrayList<Object> outgoingCallListeners = new ArrayList<Object>();
public boolean appStart(File pluginDirectory) {
try{
String logDir = pluginDirectory.getAbsolutePath() + File.separator + ".." + File.separator + ".." + File.separator + "logs" + File.separator;
loginfo(String.format("VoiceBridge logs %s", logDir));
config = Config.getInstance();
config.initialise();
String webHome = pluginDirectory.getAbsolutePath() + File.separator + ".." + File.separator + ".." + File.separator + "resources" + File.separator + "spank" + File.separator + "rayo";
System.setProperty("com.sun.voip.server.LOGLEVEL", "99");
System.setProperty("com.sun.voip.server.FIRST_RTP_PORT", "3200");
System.setProperty("com.sun.voip.server.LAST_RTP_PORT", "3899");
System.setProperty("com.sun.voip.server.FIRST_VIDEOBRIDGE_RTP_PORT", "3900");
System.setProperty("com.sun.voip.server.LAST_VIDEOBRIDGE_RTP_PORT", "3999");
System.setProperty("com.sun.voip.server.Bridge.logDirectory", logDir);
System.setProperty("com.sun.voip.server.BRIDGE_LOG", "bridge.log");
System.setProperty("com.sun.voip.server.LOGLEVEL", "99");
System.setProperty("com.sun.voip.server.PUBLIC_IP_ADDRESS", config.getPublicHost());
System.setProperty("com.sun.voip.server.PROTOCOL", config.getDefaultProtocol());
System.setProperty("com.sun.voip.server.SIP_PORT", config.getDefaultSIPPort());
System.setProperty("com.sun.voip.server.Bridge.recordDirectory", webHome + File.separator + "recordings");
System.setProperty("com.sun.voip.server.Bridge.soundsDirectory", webHome + File.separator + "sounds");
System.setProperty("com.sun.voip.server.Bridge.soundPath", "/com/sun/voip/server/sounds:" + webHome + File.separator + "sounds");
System.setProperty("freetts.voices", "com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory");
Properties properties = new Properties();
properties.setProperty("javax.sip.STACK_NAME", "JAIN SIP 1.1");
properties.setProperty("javax.sip.RETRANSMISSION_FILTER", "on");
properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "99");
properties.setProperty("gov.nist.javax.sip.MIN_KEEPALIVE_TIME_SECONDS", "360");
properties.setProperty("gov.nist.javax.sip.SERVER_LOG", logDir + "sip_server.log");
properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", logDir + "sip_debug.log");
properties.setProperty("javax.sip.IP_ADDRESS",config.getPrivateHost());
Bridge.setPublicHost(config.getPublicHost());
Bridge.setPrivateHost(config.getPrivateHost());
Bridge.setBridgeLocation("LCL");
new SipServer(config, properties);
FreeTTSClient.initialize();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
public void appStop()
{
loginfo( "VoiceBridge stopping");
Object service = this;
synchronized (incomingCallListeners)
{
boolean removeIncomingCallHandler = false;
for (Object theService : incomingCallListeners)
{
if (theService == service) {
removeIncomingCallHandler = true;
}
}
if (removeIncomingCallHandler)
{
monitorIncomingCalls(false);
}
monitorOutgoingCalls(false);
}
synchronized(conferenceMonitors)
{
ArrayList<ConferenceMonitor> monitorsToRemove = new ArrayList<ConferenceMonitor>();
for (ConferenceMonitor m : conferenceMonitors)
{
if (service == m.getService())
{
monitorsToRemove.add(m);
}
}
for (ConferenceMonitor m : monitorsToRemove)
{
loginfo("Removing conference monitor for " + m.getConferenceId());
conferenceMonitors.remove(m);
}
}
CallHandler.shutdown();
config.terminate();
}
public void callEventNotification(CallEvent callEvent)
{
loginfo( "VoiceBridge callEventNotification " + callEvent.toString());
if (conferenceMonitors.size() > 0)
{
notifyConferenceMonitors(callEvent);
}
Application.reportCallEventNotification(null, callEvent, "monitorCallStatus");
}
public static void reportCallEventNotification(Object service, CallEvent callEvent, String monitorName)
{
if ( service != null )
{
String myEvent = CallEvent.getEventString(callEvent.getEvent());
String callState = callEvent.getCallState().toString();
String info = callEvent.getInfo() == null ? "" : callEvent.getInfo();
String dtmf = callEvent.getDtmfKey() == null ? "" : callEvent.getDtmfKey();
String treatmentdId = callEvent.getTreatmentId() == null ? "" : callEvent.getTreatmentId();
int noOfCalls = callEvent.getNumberOfCalls();
String callId = callEvent.getCallId() == null ? "" : callEvent.getCallId();
String confId = callEvent.getConferenceId() == null ? "" : callEvent.getConferenceId();
String callInfo = callEvent.getCallInfo() == null ? "" : callEvent.getCallInfo();
//service.invoke("callsEventNotification", new Object[] {monitorName, myEvent, callState, info, dtmf, treatmentdId, String.valueOf(noOfCalls), callId, confId, callInfo });
}
}
public static void registerNotification(String status, ProxyCredentials credentials)
{
log.info("registerNotification " + status + " " + credentials.getXmppUserName());
try {
Config.updateStatus(credentials.getXmppUserName(), status);
} catch (Exception e) {
System.out.println("registerNotification " + e);
}
}
public void manageCallParticipant(String uid, String parameter, String value)
{
loginfo("VoiceBridge manageParticipant");
if ( callPartipants.containsKey(uid) == false)
{
callPartipants.put(uid, new CallParticipant());
reportInfo("Call Participant " + uid + " created");
}
CallParticipant cp = callPartipants.get(uid);
try {
parseCallParameters(parameter, value, cp, uid);
reportInfo("manageCallParticipant processing " + parameter + " value: " + value);
} catch (Exception e) {
reportError(e.toString());
}
}
public void manageVoiceBridge(String parameter, String value)
{
loginfo("VoiceBridge manageConference");
try {
parseBridgeParameters(parameter, value);
reportInfo("manageVoiceBridge processing " + parameter + " value: " + value);
} catch (Exception e) {
reportError(e.toString());
}
}
private void makeOutgoingCall(CallParticipant cp, String uid)
{
loginfo("VoiceBridge makeOutgoingCall");
try {
if (validateAndAdjustParameters(cp))
{
if (cp.getSecondPartyNumber() == null)
{
OutgoingCallHandler outgoingCallHandler = new OutgoingCallHandler(this, cp);
outgoingCallHandler.start();
callObjects.put(uid, outgoingCallHandler);
reportInfo("Outgoing call made to " + cp.getPhoneNumber() + " id: " + cp.getCallId());
} else {
TwoPartyCallHandler twoPartyCallHandler = new TwoPartyCallHandler(this, cp);
twoPartyCallHandler.start();
callObjects.put(uid, twoPartyCallHandler);
reportInfo("Two party call made to " + cp.getPhoneNumber() + " id: " + cp.getCallId());
}
}
} catch (Exception e) {
reportError(e.toString());
}
}
private void migrateCall(CallParticipant cp)
{
loginfo("VoiceBridge migrateCall");
try {
if (validateAndAdjustParameters(cp))
{
if (cp.migrateCall())
{
new CallMigrator(this, cp).start();
reportInfo("Call migrated to " + cp.getSecondPartyNumber() + " id: " + cp.getCallId());
} else {
reportError("Call participant is not configured for migration");
}
}
} catch (Exception e) {
reportError(e.toString());
}
}
private void reportError(String error)
{
logerror("VoiceBridge " + error);
}
private void reportInfo(String info)
{
loginfo(info);
}
private void loginfo( String s ) {
log.info( s );
System.out.println( s );
}
private void logerror( String s ) {
log.error( s );
System.out.println( "[ERROR] " + s );
}
private void parseBridgeParameters(String parameter, String value)
{
if ("nAvg".equalsIgnoreCase(parameter))
{
try {
LowPassFilter.setNAvg(getInteger(value));
} catch (Exception e) {
reportError("parseBridgeParameters : nAvg " + value + " is not numeric" );
}
return;
}
if ("lpfv".equalsIgnoreCase(parameter))
{
try {
LowPassFilter.setLpfVolumeAdjustment(getDouble(value));
} catch (Exception e) {
reportError("parseBridgeParameters : lpfv " + value + " is not numeric" );
}
return;
}
if ("forceGatewayError".equalsIgnoreCase(parameter))
{
try {
SipTPCCallAgent.forceGatewayError(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("addCallToWhisperGroup".equalsIgnoreCase(parameter))
{
String[] tokens = value.split(":");
if (tokens.length != 2)
{
reportError("You must specify both a whisperGroupId and a callId");
return;
}
String whisperGroupId = tokens[0];
String callId = tokens[1];
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("Invalid callId: " + callId);
return;
}
try {
callHandler.getMember().addCall(whisperGroupId);
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("allowShortNames".equalsIgnoreCase(parameter))
{
try {
ConferenceManager.setAllowShortNames(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("bridgeLocation".equalsIgnoreCase(parameter))
{
Bridge.setBridgeLocation(value);
return;
}
if ("cancelCall".equalsIgnoreCase(parameter))
{
CallHandler.hangup(value, "User requested call termination");
return;
}
if ("cancelMigration".equalsIgnoreCase(parameter))
{
CallMigrator.hangup(value, "User requested call termination");
return;
}
if ("cnThresh".equalsIgnoreCase(parameter))
{
try {
CallHandler.setCnThresh(getQualifierString(value), getInteger(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("comfortNoiseType".equalsIgnoreCase(parameter))
{
try {
MemberSender.setComfortNoiseType(getInteger(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("comfortNoiseLevel".equalsIgnoreCase(parameter))
{
try {
RtpPacket.setDefaultComfortNoiseLevel((byte) getInteger(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("commonMixDefault".equalsIgnoreCase(parameter))
{
try {
WhisperGroup.setCommonMixDefault(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("conferenceInfoShort".equalsIgnoreCase(parameter))
{
reportInfo(ConferenceManager.getAbbreviatedConferenceInfo());
return;
}
if ("conferenceInfo".equalsIgnoreCase(parameter))
{
reportInfo(ConferenceManager.getDetailedConferenceInfo());
return;
}
if ("createConference".equalsIgnoreCase(parameter))
{
String[] tokens = value.split(":");
if (tokens.length < 2)
{
reportError("Missing parameters");
return;
}
String conferenceId = tokens[0];
if (tokens[1].indexOf("PCM") != 0 && tokens[1].indexOf("SPEEX") != 0)
{
reportError("invalid media specification");
return;
}
String mediaPreference = tokens[1];
String displayName = null;
if (tokens.length > 2)
{
displayName = tokens[2];
}
try {
ConferenceManager.createConference(conferenceId, mediaPreference, displayName);
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("createWhisperGroup".equalsIgnoreCase(parameter))
{
String[] tokens = value.split(":");
if (tokens.length < 2)
{
reportError("You must specify both a conferenceId and a whisperGroupId");
return;
}
try {
String conferenceId = tokens[0];
String whisperGroupId = tokens[1];
double attenuation = WhisperGroup.getDefaultAttenuation();
if (tokens.length == 3)
{
attenuation = getDouble(tokens[2]);
}
ConferenceManager.createWhisperGroup(conferenceId, whisperGroupId, attenuation);
} catch (ParseException e) {
reportError("Can't create Whisper group " + tokens[1] + " " + e.getMessage());
}
return;
}
if ("deferMixing".equalsIgnoreCase(parameter))
{
try {
MemberReceiver.deferMixing(getBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("destroyWhisperGroup".equalsIgnoreCase(parameter))
{
String[] tokens = value.split(":");
if (tokens.length != 2)
{
reportError("You must specify both a conferenceId and a whisperGroupId");
return;
}
try {
ConferenceManager.destroyWhisperGroup(tokens[0], tokens[1]);
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("callAnswerTimeout".equalsIgnoreCase(parameter))
{
try {
CallSetupAgent.setDefaultCallAnswerTimeout(getInteger(value));
} catch (Exception e) {
reportError("callAnswerTimeout " + value + " is not numeric" );
}
return;
}
if ("doNotRecord".equalsIgnoreCase(parameter))
{
try {
boolean booleanValue = getBoolean(value);
String callId = getQualifierString(value);
if (callId == null)
{
reportError("Call id is missing");
return;
}
try {
CallHandler.setDoNotRecord(callId, booleanValue);
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("dtmfSuppression".equalsIgnoreCase(parameter))
{
try {
boolean booleanValue = getBoolean(value);
String callId = getQualifierString(value);
if (callId == null)
{
reportError("Call id is missing");
return;
}
try {
CallHandler.setDtmfSuppression(callId, booleanValue);
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("drop".equalsIgnoreCase(parameter))
{
try {
int integerValue = getInteger(value);
String callId = getQualifierString(value);
if (callId == null)
{
reportError("Call id is missing");
return;
}
try {
CallHandler.setDropPackets(callId, integerValue);
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("duplicateCallLimit".equalsIgnoreCase(parameter))
{
try {
CallHandler.setDuplicateCallLimit(getInteger(value));
} catch (Exception e) {
reportError("duplicateCallLimit " + value + " is not numeric" );
}
return;
}
if ("directConferencing".equalsIgnoreCase(parameter))
{
try {
IncomingCallHandler.setDirectConferencing(getBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("distributedConferenceInfo".equalsIgnoreCase(parameter))
{
reportInfo(ConferenceManager.getDistributedConferenceInfo());
return;
}
if ("dropDb".equalsIgnoreCase(parameter))
{
ConferenceManager.dropDb();
return;
}
if ("enablePSTNCalls".equalsIgnoreCase(parameter))
{
try {
CallHandler.enablePSTNCalls(getBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("endConference".equalsIgnoreCase(parameter))
{
try {
ConferenceManager.endConference(value);
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("firstRtpPort".equalsIgnoreCase(parameter))
{
try {
ConferenceMember.setFirstRtpPort(getInteger(value));
} catch (Exception e) {
reportError("firstRtpPort " + value + " is not numeric" );
}
return;
}
if ("setForcePrivateMix".equalsIgnoreCase(parameter))
{
try {
MixManager.setForcePrivateMix(getBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("forwardData".equalsIgnoreCase(parameter))
{
try {
String[] tokens = value.split(":");
if (tokens.length < 2)
{
reportError("Missing parameters: " + value);
return;
}
CallHandler dest = CallHandler.findCall(tokens[0]);
if (dest == null)
{
reportError("Invalid callId: " + tokens[0]);
return;
}
CallHandler src = CallHandler.findCall(tokens[1]);
if (src == null)
{
reportError("Invalid callId: " + tokens[1]);
return;
}
src.getMember().getMemberReceiver().addForwardMember(dest.getMember().getMemberSender());
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("forwardDtmfKeys".equalsIgnoreCase(parameter))
{
try {
MemberReceiver.setForwardDtmfKeys(getBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("gc".equalsIgnoreCase(parameter))
{
System.gc();
return;
}
if ("gcs".equalsIgnoreCase(parameter))
{
reportInfo(CallHandler.getCallStateForAllCalls());
return;
}
if ("getCallState".equalsIgnoreCase(parameter))
{
String callId = getString(value);
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("Invalid callId: " + callId);
return;
}
reportInfo(callHandler.getCallState());
return;
}
if ("getAllAbbreviatedMixDescriptors".equalsIgnoreCase(parameter))
{
reportInfo(CallHandler.getAllAbbreviatedMixDescriptors());
return;
}
if ("getAbbreviatedMixDescriptors".equalsIgnoreCase(parameter))
{
String callId = getString(value);
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("Invalid callId: " + callId);
return;
}
reportInfo(callHandler.getMember().getAbbreviatedMixDescriptors());
return;
}
if ("getAllMixDescriptors".equalsIgnoreCase(parameter))
{
reportInfo(CallHandler.getAllMixDescriptors());
return;
}
if ("getMixDescriptors".equalsIgnoreCase(parameter))
{
String callId = getString(value);
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("Invalid callId: " + callId);
return;
}
reportInfo(callHandler.getMember().getMixDescriptors());
return;
}
if ("getStatistics".equalsIgnoreCase(parameter))
{
/*
{ String.valueOf(ConferenceManager.getNumberOfConferences()),
String.valueOf(ConferenceManager.getTotalMembers()),
String.valueOf(CallHandler.getTotalSpeaking()),
String.valueOf(Math.round(ConferenceSender.getTimeBetweenSends() * 10000) / 10000.),
String.valueOf(Math.round(ConferenceSender.getAverageSendTime() * 10000) / 10000.),
String.valueOf(Math.round(ConferenceSender.getMaxSendTime() * 10000) / 10000.)
});
*/
}
if ("getBriefConferenceInfo".equalsIgnoreCase(parameter))
{
reportInfo(ConferenceManager.getBriefConferenceInfo());
return;
}
if ("gc".equalsIgnoreCase(parameter))
{
System.gc();
return;
}
if ("incomingCallTreatment".equalsIgnoreCase(parameter))
{
IncomingCallHandler.setIncomingCallTreatment(value);
return;
}
if ("incomingCallVoiceDetection".equalsIgnoreCase(parameter))
{
try {
IncomingCallHandler.setIncomingCallVoiceDetection(getBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("internationalPrefix".equalsIgnoreCase(parameter))
{
if (value.equals("\"\"") || value.equals("''"))
{
value = "";
}
config.setInternationalPrefix(value);
return;
}
if ("internalExtenLength".equalsIgnoreCase(parameter))
{
try {
config.setInternalExtenLength(getInteger(value));
} catch (Exception e) {
reportError("internalExtenLength " + value + " is not numeric" );
}
}
if ("conferenceJoinTreatment".equalsIgnoreCase(parameter))
{
try {
String[] tokens = value.split(":");
if (tokens.length != 2)
{
reportError("conferenceJoinTreatment requires two inputs");
return;
}
ConferenceManager.setConferenceJoinTreatment(tokens[1], tokens[0]);
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("conferenceLeaveTreatment".equalsIgnoreCase(parameter))
{
try {
String[] tokens = value.split(":");
if (tokens.length != 2)
{
reportError("conferenceLeaveTreatment requires two inputs");
return;
}
ConferenceManager.setConferenceLeaveTreatment(tokens[1], tokens[0]);
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("lastRtpPort".equalsIgnoreCase(parameter))
{
try {
ConferenceMember.setLastRtpPort(getInteger(value));
} catch (Exception e) {
reportError("lastRtpPort " + value + " is not numeric" );
}
return;
}
if ("loneReceiverPort".equalsIgnoreCase(parameter))
{
try {
ConferenceManager.setLoneReceiverPort(getInteger(value));
} catch (Exception e) {
reportError("loneReceiverPort " + value + " is not numeric" );
}
return;
}
if ("longDistancePrefix".equalsIgnoreCase(parameter))
{
if (value.equals("\"\"") || value.equals("''"))
{
value = "";
}
config.setLongDistancePrefix(value);
return;
}
if ("migrateToBridge".equalsIgnoreCase(parameter))
{
try {
String[] tokens = value.split(":");
if (tokens.length != 3)
{
reportError("migrateToBridge requires three inputs");
return;
}
String bridge = tokens[0];
String port = tokens[1];
String callId = tokens[2];
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("Invalid callId: " + callId);
return;
}
CallParticipant cp = callHandler.getCallParticipant();
if (cp.getInputTreatment() != null)
{
cp.setPhoneNumber(null);
}
/*
BridgeConnector bridgeConnector;
int serverPort;
try {
serverPort = Integer.parseInt(port);
} catch (NumberFormatException e) {
reportError("Invalid bridge server port: " + port);
return;
}
try {
bridgeConnector = new BridgeConnector(bridge, serverPort, 5000);
} catch (IOException e) {
reportError("Unable to connect to bridge " + bridge + " " + e.getMessage());
return;
}
callHandler.suppressStatus(true);
try {
String s = cp.getCallSetupRequest();
s = s.substring(0, s.length() - 1); // get rid of last new line
bridgeConnector.sendCommand(s);
} catch (IOException e) {
reportError("Unable to send command to bridge: " + e.getMessage());
return;
}
bridgeConnector.addCallEventListener(requestHandler);
// XXX need to figure out how to deal with Private Mixes now that the call has moved!
*/
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("senderThreads".equalsIgnoreCase(parameter))
{
try {
ConferenceSender.setSenderThreads(getInteger(value));
} catch (Exception e) {
reportError("senderThreads " + value + " is not numeric" );
}
return;
}
if ("minJitterBufferSize".equalsIgnoreCase(parameter))
{
try {
String[] tokens = value.split(":");
if (tokens.length != 2)
{
reportError("minJitterBufferSize requires two inputs");
return;
}
int minJitterBufferSize = getInteger(tokens[0]);
CallHandler callHandler = CallHandler.findCall(tokens[1]);
if (callHandler == null)
{
reportError("Invalid callId: " + tokens[1]);
return;
}
callHandler.getMember().getMemberReceiver().setMinJitterBufferSize(minJitterBufferSize);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("maxJitterBufferSize".equalsIgnoreCase(parameter))
{
try {
String[] tokens = value.split(":");
if (tokens.length != 2)
{
reportError("maxJitterBufferSize requires two inputs");
return;
}
int minJitterBufferSize = getInteger(tokens[0]);
CallHandler callHandler = CallHandler.findCall(tokens[1]);
if (callHandler == null)
{
reportError("Invalid callId: " + tokens[1]);
return;
}
callHandler.getMember().getMemberReceiver().setMaxJitterBufferSize(minJitterBufferSize);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("monitorCallStatus".equalsIgnoreCase(parameter))
{
try {
boolean booleanValue = getBoolean(value);
String callId = getQualifierString(value);
if (callId == null)
{
reportError("Call id is missing");
return;
}
try {
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("No such callId: " + callId);
return;
}
if (booleanValue == true)
{
callHandler.addCallEventListener(this);
} else {
callHandler.removeCallEventListener(this);
}
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("monitorConferenceStatus".equalsIgnoreCase(parameter))
{
try {
boolean booleanValue = getBoolean(value);
String conferenceId = getQualifierString(value);
if (conferenceId == null)
{
reportError("conferenceId id is missing");
return;
}
monitorConferenceStatus(conferenceId, booleanValue);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("monitorIncomingCalls".equalsIgnoreCase(parameter))
{
try {
boolean booleanValue = getBoolean(value);
if (monitorIncomingCalls(booleanValue) == false)
{
reportInfo("There is already an incoming call monitor!");
return;
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("monitorOutgoingCalls".equalsIgnoreCase(parameter))
{
try {
boolean booleanValue = getBoolean(value);
monitorOutgoingCalls(booleanValue);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("muteCall".equalsIgnoreCase(parameter))
{
try {
boolean booleanValue = getBoolean(value);
String callId = getQualifierString(value);
if (callId == null)
{
reportError("Call id is missing");
return;
}
try {
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("No such callId: " + callId);
return;
}
CallHandler.setMuted(callId, booleanValue);
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("muteWhisperGroup".equalsIgnoreCase(parameter))
{
try {
boolean booleanValue = getBoolean(value);
String callId = getQualifierString(value);
if (callId == null)
{
reportError("Call id is missing");
return;
}
try {
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("No such callId: " + callId);
return;
}
CallHandler.setMuteWhisperGroup(callId, booleanValue);
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("muteConference".equalsIgnoreCase(parameter))
{
try {
boolean booleanValue = getBoolean(value);
String callId = getQualifierString(value);
if (callId == null)
{
reportError("Call id is missing");
return;
}
try {
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("No such callId: " + callId);
return;
}
CallHandler.setConferenceMuted(callId, booleanValue);
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("numberOfCalls".equalsIgnoreCase(parameter))
{
try {
String[] tokens = value.split(":");
if (tokens.length != 1)
{
reportError("You must specify a conference id");
return;
}
CallEvent event = new CallEvent(CallEvent.NUMBER_OF_CALLS);
event.setNumberOfCalls(ConferenceManager.getNumberOfMembers(tokens[0]));
//callEventNotification(event);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("outsideLinePrefix".equalsIgnoreCase(parameter))
{
if (value.equals("\"\"") || value.equals("''"))
{
value = "";
}
config.setOutsideLinePrefix(value);
return;
}
if ("receiverPause".equalsIgnoreCase(parameter))
{
try {
ConferenceReceiver.setReceiverPause(getInteger(value));
} catch (Exception e) {
reportError("pause " + value + " is not numeric" );
}
return;
}
if ("pauseTreatmentToCall".equalsIgnoreCase(parameter))
{
try {
String[] tokens = value.split(":");
CallHandler callHandler = CallHandler.findCall(tokens[0]);
if (callHandler == null)
{
reportError("Invalid callId: " + tokens[0]);
return;
}
String treatmentId = null;
if (tokens.length > 1)
{
treatmentId = tokens[1];
}
callHandler.getMember().pauseTreatment(treatmentId, true);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("pauseTreatmentToConference".equalsIgnoreCase(parameter))
{
try {
String treatment = getTreatment(value);
value = value.substring(treatment.length());
String conferenceId = getQualifierString(value);
if (conferenceId == null)
{
reportError("conferenceId must be specified: " + value);
return;
}
ConferenceManager.pauseTreatment(conferenceId, treatment, true);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("playTreatmentToCall".equalsIgnoreCase(parameter))
{
try {
String treatment = getTreatment(value);
double volume[] = getVolume(value);
value = value.substring(treatment.length());
String callId = getQualifierString(value);
if (callId == null)
{
reportError("callId must be specified: " + value);
return;
}
try {
CallHandler.playTreatmentToCall(callId, treatment);
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
return;
} catch (IOException e) {
reportError("Unable to read treatment file " + treatment + " " + e.getMessage());
return;
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("playTreatmentToConference".equalsIgnoreCase(parameter))
{
try {
String treatment = getTreatment(value);
double volume[] = getVolume(value);
value = value.substring(treatment.length());
String conferenceId = getQualifierString(value);
if (conferenceId == null)
{
reportError("conference Id must be specified: " + value);
return;
}
try {
ConferenceManager.playTreatment(conferenceId, treatment);
} catch (NoSuchElementException e) {
reportError("Invalid conference Id specified: " + value);
return;
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("playTreatmentToAllConferences".equalsIgnoreCase(parameter))
{
try {
String treatment = getTreatment(value);
double volume[] = getVolume(value);
value = value.substring(treatment.length());
try {
ConferenceManager.playTreatmentToAllConferences(treatment);
} catch (Exception e) {
reportError("Error playing treatment : " + value);
return;
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("transferCall".equalsIgnoreCase(parameter))
{
try {
String callId = getString(value);
if (callId == null)
{
reportError("Call id is missing");
return;
}
try {
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("No such callId: " + callId);
return;
}
String conferenceId = getQualifierString(value);
IncomingCallHandler.transferCall(callId, conferenceId);
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("sendDtmfKey".equalsIgnoreCase(parameter))
{
try {
String callId = getString(value);
if (callId == null)
{
reportError("Call id is missing");
return;
}
try {
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler == null)
{
reportError("No such callId: " + callId);
return;
}
String dtmfKey = getQualifierString(value);
callHandler.dtmfKeys(dtmfKey);
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
}
} catch (Exception e) {
reportError(e.toString());
}
return;
}
}
private void parseCallParameters(String parameter, String value, CallParticipant cp, String uid)
{
if ("makeCall".equalsIgnoreCase(parameter))
{
try {
makeOutgoingCall(cp, uid);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("migrateCall".equalsIgnoreCase(parameter))
{
try {
migrateCall(cp);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("cancelCall".equalsIgnoreCase(parameter))
{
CallHandler.hangup(cp.getCallId(), "User requested call termination");
return;
}
if ("sendDtmfKey".equalsIgnoreCase(parameter))
{
try {
CallHandler callHandler = CallHandler.findCall(cp.getCallId());
callHandler.dtmfKeys(value);
} catch (NoSuchElementException e) {
reportError("Invalid callId specified: " + value);
}
return;
}
if ("conferenceJoinTreatment".equalsIgnoreCase(parameter))
{
cp.setConferenceJoinTreatment(value);
return;
}
if ("conferenceLeaveTreatment".equalsIgnoreCase(parameter))
{
cp.setConferenceLeaveTreatment(value);
return;
}
if ("callAnsweredTreatment".equalsIgnoreCase(parameter))
{
cp.setCallAnsweredTreatment(value);
return;
}
if ("callanswertimeout".equalsIgnoreCase(parameter))
{
try {
cp.setCallAnswerTimeout(getInteger(value));
} catch (Exception e) {
reportError("callAnswerTimeout " + value + " is not numeric" );
}
return;
}
if ("calltimeout".equalsIgnoreCase(parameter))
{
try {
cp.setCallTimeout(getInteger(value) * 1000);
} catch (Exception e) {
reportError("callTimeout " + value + " is not numeric" );
}
return;
}
if ("callendtreatment".equalsIgnoreCase(parameter))
{
cp.setCallEndTreatment(value);
return;
}
if ("callestablishedtreatment".equalsIgnoreCase(parameter))
{
cp.setCallEstablishedTreatment(value);
return;
}
if ("callid".equalsIgnoreCase(parameter))
{
cp.setCallId(value);
return;
}
if ("conferenceid".equalsIgnoreCase(parameter))
{
try {
String[] tokens = value.split(":");
cp.setConferenceId(tokens[0].trim());
if (tokens.length > 1) {
cp.setMediaPreference(tokens[1]);
}
if (tokens.length > 2) {
cp.setConferenceDisplayName(tokens[2]);
}
} catch (Exception e) {
reportError("conferenceId " + value + " is invalid" );
}
return;
}
if ("displayname".equalsIgnoreCase(parameter))
{
cp.setDisplayName(value);
return;
}
if ("distributedbridge".equalsIgnoreCase(parameter))
{
try {
cp.setDistributedBridge(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("donotrecord".equalsIgnoreCase(parameter))
{
try {
cp.setDoNotRecord(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("dtmfdetection".equalsIgnoreCase(parameter))
{
try {
cp.setDtmfDetection(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("dtmfsuppression".equalsIgnoreCase(parameter))
{
try {
cp.setDtmfSuppression(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("forwarddatafrom".equalsIgnoreCase(parameter))
{
cp.setForwardingCallId(value);
return;
}
if ("ignoretelephoneevents".equalsIgnoreCase(parameter))
{
try {
cp.setIgnoreTelephoneEvents(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("inputtreatment".equalsIgnoreCase(parameter))
{
cp.setInputTreatment(value);
return;
}
if ("encryptkey".equalsIgnoreCase(parameter))
{
cp.setEncryptionKey(value);
return;
}
if ("encryptalgorithm".equalsIgnoreCase(parameter))
{
cp.setEncryptionAlgorithm(value);
return;
}
if ("firstConferenceMemberTreatment".equalsIgnoreCase(parameter))
{
cp.setFirstConferenceMemberTreatment(value);
return;
}
if ("handlesessionprogress".equalsIgnoreCase(parameter))
{
try {
cp.setHandleSessionProgress(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("joinconfirmationkey".equalsIgnoreCase(parameter))
{
try {
MemberReceiver.setJoinConfirmationKey(value);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("joinconfirmationtimeout".equalsIgnoreCase(parameter))
{
try {
cp.setJoinConfirmationTimeout(getInteger(value));
} catch (Exception e) {
reportError("callAnswerTimeout " + value + " is not numeric" );
}
return;
}
if ("mediapreference".equalsIgnoreCase(parameter))
{
cp.setMediaPreference(value);
return;
}
if ("migrate".equalsIgnoreCase(parameter))
{
String callId = getFirstString(value);
cp.setCallId(callId);
/*
* The second party number may be a sip address
* with colons. So we treat everything after the
* first colon as the second party number.
*/
int ix;
if ((ix = value.indexOf(":")) < 0) {
reportError("secondPartyNumber must be specified: " + value);
return;
}
String secondPartyNumber = value.substring(ix + 1);
if (secondPartyNumber == null)
{
reportError("secondPartyNumber must be specified: " + value);
return;
}
try {
cp.setSecondPartyNumber(secondPartyNumber);
cp.setMigrateCall(true);
} catch (Exception e) {
reportError(e.toString());
}
return;
}
if ("mute".equalsIgnoreCase(parameter))
{
try {
cp.setMuted(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("mutewhispergroup".equalsIgnoreCase(parameter))
{
try {
cp.setMuteWhisperGroup(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("muteconference".equalsIgnoreCase(parameter))
{
try {
cp.setConferenceMuted(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("name".equalsIgnoreCase(parameter))
{
cp.setName(value);
return;
}
if ("phonenumber".equalsIgnoreCase(parameter))
{
cp.setPhoneNumber(value);
return;
}
if ("phonenumberlocation".equalsIgnoreCase(parameter))
{
cp.setPhoneNumberLocation(value);
}
if ("protocol".equalsIgnoreCase(parameter))
{
if (value.equalsIgnoreCase("SIP") == false && value.equalsIgnoreCase("NS") == false && value.equalsIgnoreCase("WebRtc") == false && value.equalsIgnoreCase("Rtmfp") == false && value.equalsIgnoreCase("Speaker") == false)
{
reportError("Invalid protocol: " + value);
return;
}
cp.setProtocol(value);
return;
}
if ("recorder".equalsIgnoreCase(parameter))
{
try {
cp.setRecorder(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("recorddirectory".equalsIgnoreCase(parameter))
{
cp.setRecordDirectory(value);
return;
}
if ("remotecallid".equalsIgnoreCase(parameter))
{
cp.setRemoteCallId(value);
return;
}
if ("voiceDetectionWhileMuted".equalsIgnoreCase(parameter))
{
try {
cp.setVoiceDetectionWhileMuted(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("useConferenceReceiverThread".equalsIgnoreCase(parameter))
{
try {
cp.setUseConferenceReceiverThread(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("voiceDetection".equalsIgnoreCase(parameter))
{
try {
cp.setVoiceDetection(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("whisperGroup".equalsIgnoreCase(parameter))
{
cp.setWhisperGroupId(value);
return;
}
if ("voipGateway".equalsIgnoreCase(parameter))
{
cp.setVoIPGateway(value);
return;
}
if ("secondPartyCallId".equalsIgnoreCase(parameter))
{
cp.setSecondPartyCallId(value);
return;
}
if ("sipProxy".equalsIgnoreCase(parameter))
{
cp.setSipProxy(value);
return;
}
if ("secondPartyCallId".equalsIgnoreCase(parameter))
{
cp.setSecondPartyCallId(value);
return;
}
if ("secondPartyCallEndTreatment".equalsIgnoreCase(parameter))
{
cp.setSecondPartyCallEndTreatment(value);
return;
}
if ("secondPartyName".equalsIgnoreCase(parameter))
{
cp.setSecondPartyName(value);
return;
}
if ("secondPartyNumber".equalsIgnoreCase(parameter))
{
cp.setSecondPartyNumber(value);
return;
}
if ("secondPartyTreatment".equalsIgnoreCase(parameter))
{
cp.setSecondPartyTreatment(value);
return;
}
if ("secondpartyVoiceDetection".equalsIgnoreCase(parameter))
{
try {
cp.setSecondPartyVoiceDetection(stringToBoolean(value));
} catch (ParseException e) {
reportError(e.toString());
}
return;
}
if ("secondPartyTimeout".equalsIgnoreCase(parameter))
{
try {
cp.setSecondPartyTimeout(getInteger(value));
} catch (Exception e) {
reportError("setSecondPartyTimeout " + value + " is not numeric" );
}
return;
}
}
private String getString(String value)
{
int n;
if ((n = value.lastIndexOf(":")) > 0) {
value = value.substring(0, n);
}
return value;
}
private double[] getVolume(String value) throws ParseException
{
String v = new String(value);
int n;
if ((n = v.indexOf(":volume=")) < 0) {
return null;
}
v = v.substring(n + 8);
String[] tokens = v.split(":");
double[] volume = new double[tokens.length];
for (int i = 0; i < volume.length; i++)
{
try {
volume[i] = Double.parseDouble(tokens[i]);
} catch (NumberFormatException e) {
throw new ParseException("Invalid floating point value: " + tokens[i], 0);
}
}
return volume;
}
private String getTreatment(String value)
{
String v = new String(value);
int n;
if ((n = v.indexOf(":volume=")) >= 0)
{
v = v.substring(0, n);
}
if ((n = v.lastIndexOf(":")) < 0) {
/*
* There's no ":", so the whole string is the treatment
*/
return v;
}
String s = v.substring(0, n);
if (s.equalsIgnoreCase("f") || s.equalsIgnoreCase("file")
|| s.equalsIgnoreCase("d") || s.equalsIgnoreCase("dtmf")
|| s.equalsIgnoreCase("t") || s.equalsIgnoreCase("tts")) {
/*
* The only ":" is preceded by the type of treatment.
* The whole string is the treatment.
*/
return v;
}
/*
* The treatment is the string up to the last ":".
*/
return s;
}
private boolean getBoolean(String value) throws ParseException
{
int n;
if ((n = value.indexOf(":")) > 0) {
value = value.substring(0, n);
}
return stringToBoolean(value);
}
private boolean stringToBoolean(String value) throws ParseException
{
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("t")) {
return true;
}
if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("F")) {
return false;
}
throw new ParseException("Invalid boolean value, must be true or false: " + value, 0);
}
private int getInteger(String value) throws ParseException
{
int n;
if ((n = value.indexOf(":")) > 0) {
value = value.substring(0, n);
}
int i = 0;
try {
i = Integer.parseInt(value);
} catch (NumberFormatException e) {
throw new ParseException("Invalid integer value: " + value, 0);
}
return i;
}
private String getQualifierString(String value)
{
int n;
if (value == null) {
return null;
}
if ((n = value.lastIndexOf(":")) >= 0) {
return value.substring(n+1);
}
return null;
}
private double getDouble(String value) throws ParseException
{
int n;
if ((n = value.indexOf(":")) > 0) {
value = value.substring(0, n);
}
double f = 0.0;
try {
f = Double.parseDouble(value);
} catch (NumberFormatException e) {
throw new ParseException("Invalid double value: " + value, 0);
}
return f;
}
private String getFirstString(String value)
{
int ix;
if ((ix = value.indexOf(":")) < 0) {
return value;
}
return value.substring(0, ix);
}
private boolean validateAndAdjustParameters(CallParticipant cp) throws ParseException
{
String callId = cp.getCallId();
if (callId == null) {
cp.setCallId(CallHandler.getNewCallId());
} else {
if (callId.equals("0"))
{
reportError("Zero is an invalid callId");
return false;
}
if (cp.migrateCall() == false)
{
CallHandler callHandler = CallHandler.findCall(callId);
if (callHandler != null)
{
if (callHandler.isCallEnding() == false)
{
reportError("CallId " + callId + " is already in use");
return false;
} else {
reportError("Reusing callId for ending call " + callId);
}
}
}
}
handleCallAttendant(cp);
cp.setSecondPartyNumber(config.formatPhoneNumber(cp.getSecondPartyNumber(), cp.getPhoneNumberLocation()));
if (cp.migrateCall() == false)
{
if (cp.getProtocol() == null || "SIP".equals(cp.getProtocol()))
{
cp.setPhoneNumber(config.formatPhoneNumber(cp.getPhoneNumber(), cp.getPhoneNumberLocation()));
if (cp.getPhoneNumber() == null)
{
if (cp.getInputTreatment() == null)
{
reportError("You must specify a phone number or a soft phone URI");
return false;
} else {
if (cp.getInputTreatment().equals("null"))
{
cp.setInputTreatment("");
}
cp.setPhoneNumber(cp.getInputTreatment());
cp.setProtocol("NS");
}
}
}
}
if (cp.getName() == null || cp.getName().equals(""))
{
cp.setName("Anonymous");
}
if (cp.migrateCall() == true)
{
if (cp.getCallId() == null || cp.getSecondPartyNumber() == null)
{
reportError("You must specify old and new phone numbers to migrate a call");
return false;
}
}
if (cp.getConferenceId() == null && cp.getSecondPartyNumber() == null)
{
reportError("You must specify a conference Id");
return false;
}
if (cp.getDisplayName() == null)
{
if (cp.getSecondPartyNumber() == null)
{
cp.setDisplayName(cp.getConferenceId());
} else {
if (cp.getSecondPartyName() != null)
{
cp.setDisplayName(cp.getSecondPartyName());
} else {
cp.setDisplayName(cp.getSecondPartyNumber());
}
}
}
/*
* For two party calls.
*/
if (cp.getConferenceId() != null)
{
if (cp.getSecondPartyTreatment() != null)
{
cp.setConferenceJoinTreatment(cp.getSecondPartyTreatment());
}
if (cp.getSecondPartyCallEndTreatment() != null)
{
cp.setConferenceLeaveTreatment(
cp.getSecondPartyCallEndTreatment());
}
}
if (cp.getSecondPartyNumber() != null)
{
if (cp.getConferenceId() == null)
{
cp.setConferenceId(cp.getPhoneNumber());
}
}
return true;
}
/*
* Some Sun sites such as China have an automated call attendent
* which asks the user to enter the extension again.
*
* If a phone number has ">" in it, we replace the phone number
* to call with everything before the ">" and set the call
* answer treatment to be dtmf keys of everything after the ">".
*/
private void handleCallAttendant(CallParticipant cp)
{
String phoneNumber = cp.getPhoneNumber();
int ix;
if (phoneNumber != null && phoneNumber.indexOf("sip:") < 0 && phoneNumber.indexOf("@") < 0)
{
if ((ix = phoneNumber.indexOf(">")) > 0)
{
/*
* Must have 5 digit extension
*/
if (phoneNumber.length() >= ix + 1 + 5) {
cp.setCallAnsweredTreatment("dtmf:" +
phoneNumber.substring(ix + 1));
cp.setPhoneNumber(phoneNumber.substring(0, ix));
}
}
}
phoneNumber = cp.getSecondPartyNumber();
if (phoneNumber != null &&
phoneNumber.indexOf("sip:") < 0 &&
phoneNumber.indexOf("@") < 0) {
if ((ix = phoneNumber.indexOf(">")) > 0) {
/*
* Must have 5 digit extension
*/
if (phoneNumber.length() >= ix + 1 + 5) {
cp.setSecondPartyTreatment("dtmf:" +
phoneNumber.substring(ix + 1));
cp.setSecondPartyNumber(phoneNumber.substring(0, ix));
}
}
}
}
private void monitorConferenceStatus(String conferenceId, boolean monitor)
{
if (monitor)
{
synchronized(conferenceMonitors)
{
loginfo("adding conference monitor for " + conferenceId);
conferenceMonitors.add(new ConferenceMonitor(null, conferenceId));
}
} else {
synchronized(conferenceMonitors)
{
ArrayList<ConferenceMonitor> monitorsToRemove = new ArrayList<ConferenceMonitor>();
for (ConferenceMonitor m : conferenceMonitors)
{
if (null != m.getService())
{
continue;
}
if (conferenceId.equals(m.getConferenceId()))
{
monitorsToRemove.add(m);
}
}
for (ConferenceMonitor m : monitorsToRemove)
{
loginfo("Removing conference monitor for " + conferenceId);
conferenceMonitors.remove(m);
}
}
}
}
public void monitorOutgoingCalls(boolean monitor)
{
synchronized(outgoingCallListeners)
{
if (monitor == true) {
outgoingCallListeners.add(this);
} else {
outgoingCallListeners.remove(this);
}
}
}
public boolean monitorIncomingCalls(boolean monitor)
{
synchronized(incomingCallListeners)
{
if (monitor == true)
{
if (incomingCallListeners.contains(this))
{
reportError("Client already has an incomingCallListener");
return false;
}
incomingCallListeners.add(this);
IncomingCallHandler.setDirectConferencing(false);
loginfo("adding incoming call monitor, setting directConferencing to false");
} else {
if (incomingCallListeners.contains(this) == false)
{
return false;
}
incomingCallListeners.remove(this);
if (incomingCallListeners.size() == 0)
{
IncomingCallHandler.setDirectConferencing(true);
loginfo("removing last incoming call monitor setting directConferencing to true");
}
}
}
return true;
}
public static void notifyConferenceMonitors(CallEvent callEvent)
{
//System.out.println("notifyConferenceMonitors " + callEvent.toString());
synchronized(conferenceMonitors)
{
/*
* Notify conference listeners
*/
String conferenceId = callEvent.getConferenceId();
String s = callEvent.toString();
if (conferenceId == null)
{
int ix;
String search = "ConferenceId='";
if ((ix = s.indexOf(search)) < 0) {
return;
}
conferenceId = s.substring(search.length());
int end;
if ((end = conferenceId.indexOf("'")) < 0) {
return;
}
conferenceId = conferenceId.substring(0, end);
}
for (ConferenceMonitor m : conferenceMonitors)
{
if (conferenceId.equals(m.getConferenceId()))
{
Application.reportCallEventNotification(m.getService(), callEvent, "monitorConferenceStatus");
}
}
}
}
public static void incomingCallNotification(CallEvent callEvent)
{
//System.out.println("incomingCallNotification " + callEvent.toString());
synchronized (incomingCallListeners)
{
for (Object service : incomingCallListeners)
{
Application.reportCallEventNotification(service, callEvent, "monitorIncomingCalls");
}
}
notifyConferenceMonitors(callEvent);
}
public static void outgoingCallNotification(CallEvent callEvent)
{
//System.out.println("outgoingCallNotification " + callEvent.toString());
synchronized(outgoingCallListeners)
{
for (Object service : outgoingCallListeners)
{
Application.reportCallEventNotification(service, callEvent, "monitorOutgoingCalls");
}
}
}
class ConferenceMonitor {
private Object service;
private String conferenceId;
public ConferenceMonitor(Object service, String conferenceId) {
this.service = service;
this.conferenceId = conferenceId;
}
public Object getService() {
return service;
}
public String getConferenceId() {
return conferenceId;
}
}
}