/*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.mobicents.servlet.sip.message;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.servlet.sip.Address;
import javax.servlet.sip.AuthInfo;
import javax.servlet.sip.Parameterable;
import javax.servlet.sip.ServletParseException;
import javax.servlet.sip.SipApplicationSession;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.SipURI;
import javax.servlet.sip.URI;
import javax.servlet.sip.ar.SipApplicationRouterInfo;
import javax.sip.ListeningPoint;
import javax.sip.SipException;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ContactHeader;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.Header;
import javax.sip.header.MaxForwardsHeader;
import javax.sip.header.RouteHeader;
import javax.sip.header.ToHeader;
import javax.sip.message.Request;
import org.apache.log4j.Logger;
import org.mobicents.servlet.sip.JainSipUtils;
import org.mobicents.servlet.sip.SipFactories;
import org.mobicents.servlet.sip.address.AddressImpl;
import org.mobicents.servlet.sip.address.GenericURIImpl;
import org.mobicents.servlet.sip.address.SipURIImpl;
import org.mobicents.servlet.sip.address.TelURLImpl;
import org.mobicents.servlet.sip.address.URIImpl;
import org.mobicents.servlet.sip.core.ApplicationRoutingHeaderComposer;
import org.mobicents.servlet.sip.core.ExtendedListeningPoint;
import org.mobicents.servlet.sip.core.SipApplicationDispatcher;
import org.mobicents.servlet.sip.core.SipNetworkInterfaceManager;
import org.mobicents.servlet.sip.core.dispatchers.MessageDispatcher;
import org.mobicents.servlet.sip.core.session.MobicentsSipApplicationSession;
import org.mobicents.servlet.sip.core.session.MobicentsSipSession;
import org.mobicents.servlet.sip.core.session.SessionManagerUtil;
import org.mobicents.servlet.sip.core.session.SipApplicationSessionKey;
import org.mobicents.servlet.sip.core.session.SipManager;
import org.mobicents.servlet.sip.core.session.SipSessionKey;
import org.mobicents.servlet.sip.security.AuthInfoImpl;
import org.mobicents.servlet.sip.startup.SipContext;
import org.mobicents.servlet.sip.startup.StaticServiceHolder;
import org.mobicents.servlet.sip.startup.failover.BalancerDescription;
public class SipFactoryImpl implements Externalizable {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(SipFactoryImpl.class
.getCanonicalName());
private static final String TAG_PARAM = "tag";
private static final String METHOD_PARAM = "method";
private static final String MADDR_PARAM = "maddr";
private static final String TTL_PARAM = "ttl";
private static final String TRANSPORT_PARAM = "transport";
private static final String LR_PARAM = "lr";
private boolean useLoadBalancer = false;
private BalancerDescription loadBalancerToUse = null;
public static class NamesComparator implements Comparator<String>, Serializable {
private static final long serialVersionUID = 1L;
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(o2);
}
}
private static final Set<String> forbbidenParams = new HashSet<String>();
static {
forbbidenParams.add(TAG_PARAM);
forbbidenParams.add(METHOD_PARAM);
forbbidenParams.add(MADDR_PARAM);
forbbidenParams.add(TTL_PARAM);
forbbidenParams.add(TRANSPORT_PARAM);
forbbidenParams.add(LR_PARAM);
}
private transient SipApplicationDispatcher sipApplicationDispatcher = null;
public SipFactoryImpl() {}
/**
* Dafault constructor
* @param sipApplicationDispatcher
*/
public SipFactoryImpl(SipApplicationDispatcher sipApplicationDispatcher) {
this.sipApplicationDispatcher = sipApplicationDispatcher;
}
/*
* (non-Javadoc)
*
* @see javax.servlet.sip.SipFactory#createAddress(java.lang.String)
*/
public Address createAddress(String sipAddress)
throws ServletParseException {
try {
if (logger.isDebugEnabled()) {
logger.debug("Creating Address from [" + sipAddress + "]");
}
AddressImpl retval = new AddressImpl();
retval.setValue(sipAddress);
return retval;
} catch (IllegalArgumentException e) {
throw new ServletParseException(e);
}
}
/*
* (non-Javadoc)
*
* @see javax.servlet.sip.SipFactory#createAddress(javax.servlet.sip.URI)
*/
public Address createAddress(URI uri) {
if (logger.isDebugEnabled()) {
logger.debug("Creating Address fromm URI[" + uri.toString()
+ "]");
}
URIImpl uriImpl = (URIImpl) uri;
return new AddressImpl(SipFactories.addressFactory
.createAddress(uriImpl.getURI()), null, true);
}
/*
* (non-Javadoc)
*
* @see javax.servlet.sip.SipFactory#createAddress(javax.servlet.sip.URI,
* java.lang.String)
*/
public Address createAddress(URI uri, String displayName) {
try {
if (logger.isDebugEnabled()) {
logger.debug("Creating Address from URI[" + uri.toString()
+ "] with display name[" + displayName + "]");
}
javax.sip.address.Address address = SipFactories.addressFactory
.createAddress(((URIImpl) uri).getURI());
address.setDisplayName(displayName);
return new AddressImpl(address, null, true);
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
/*
* (non-Javadoc)
*
* @see javax.servlet.sip.SipFactory#createApplicationSession()
*/
public SipApplicationSession createApplicationSession() {
throw new UnsupportedOperationException("use createApplicationSession(SipContext sipContext) instead !");
}
/**
* Creates an application session associated with the context
* @param sipContext
* @return
*/
public SipApplicationSession createApplicationSession(SipContext sipContext) {
if (logger.isDebugEnabled()) {
logger.debug("Creating new application session for sip context "+ sipContext.getApplicationName());
}
//call id not needed anymore since the sipappsessionkey is not a callid anymore but a random uuid
SipApplicationSessionKey sipApplicationSessionKey = SessionManagerUtil.getSipApplicationSessionKey(
sipContext.getApplicationName(),
null);
MobicentsSipApplicationSession sipApplicationSession = ((SipManager)sipContext.getManager()).getSipApplicationSession(
sipApplicationSessionKey, true);
return sipApplicationSession.getSession();
}
/*
* (non-Javadoc)
*
* @see javax.servlet.sip.SipFactory#createRequest(javax.servlet.sip.SipApplicationSession,
* java.lang.String, javax.servlet.sip.Address,
* javax.servlet.sip.Address)
*/
public SipServletRequest createRequest(SipApplicationSession sipAppSession,
String method, Address from, Address to, String handler) {
if (logger.isDebugEnabled()) {
logger
.debug("Creating new SipServletRequest for SipApplicationSession["
+ sipAppSession
+ "] METHOD["
+ method
+ "] FROM_A[" + from + "] TO_A[" + to + "]");
}
validateCreation(method, sipAppSession);
try {
//javadoc specifies that a copy of the address should be done hence the clone
return createSipServletRequest(sipAppSession, method, (Address)from.clone(), (Address)to.clone(), handler);
} catch (ServletParseException e) {
logger.error("Error creating sipServletRequest", e);
return null;
}
}
/*
* (non-Javadoc)
*
* @see javax.servlet.sip.SipFactory#createRequest(javax.servlet.sip.SipApplicationSession,
* java.lang.String, javax.servlet.sip.URI, javax.servlet.sip.URI)
*/
public SipServletRequest createRequest(SipApplicationSession sipAppSession,
String method, URI from, URI to, String handler) {
if (logger.isDebugEnabled()) {
logger
.debug("Creating new SipServletRequest for SipApplicationSession["
+ sipAppSession
+ "] METHOD["
+ method
+ "] FROM_URI[" + from + "] TO_URI[" + to + "]");
}
validateCreation(method, sipAppSession);
//javadoc specifies that a copy of the uri should be done hence the clone
Address toA = this.createAddress(to.clone());
Address fromA = this.createAddress(from.clone());
try {
return createSipServletRequest(sipAppSession, method, fromA, toA, handler);
} catch (ServletParseException e) {
logger.error("Error creating sipServletRequest", e);
return null;
}
}
/*
* (non-Javadoc)
*
* @see javax.servlet.sip.SipFactory#createRequest(javax.servlet.sip.SipApplicationSession,
* java.lang.String, java.lang.String, java.lang.String)
*/
public SipServletRequest createRequest(SipApplicationSession sipAppSession,
String method, String from, String to, String handler) throws ServletParseException {
if (logger.isDebugEnabled()) {
logger
.debug("Creating new SipServletRequest for SipApplicationSession["
+ sipAppSession
+ "] METHOD["
+ method
+ "] FROM["
+ from + "] TO[" + to + "]");
}
validateCreation(method, sipAppSession);
Address toA = this.createAddress(to);
Address fromA = this.createAddress(from);
return createSipServletRequest(sipAppSession, method, fromA, toA, handler);
}
/*
* (non-Javadoc)
*
* @see javax.servlet.sip.SipFactory#createRequest(javax.servlet.sip.SipServletRequest,
* boolean)
*/
public SipServletRequest createRequest(SipServletRequest origRequest,
boolean sameCallId) {
if (logger.isDebugEnabled()) {
logger.debug("Creating SipServletRequest from original request["
+ origRequest + "] with same call id[" + sameCallId + "]");
}
return origRequest.getB2buaHelper().createRequest(origRequest);
}
/*
* (non-Javadoc)
*
* @see javax.servlet.sip.SipFactory#createSipURI(java.lang.String,
* java.lang.String)
*/
public SipURI createSipURI(String user, String host) {
if (logger.isDebugEnabled()) {
logger.debug("Creating SipURI from USER[" + user + "] HOST[" + host
+ "]");
}
try {
return new SipURIImpl(SipFactories.addressFactory.createSipURI(
user, host));
} catch (ParseException e) {
logger.error("couldn't parse the SipURI from USER[" + user
+ "] HOST[" + host + "]", e);
throw new IllegalArgumentException("Could not create SIP URI user = " + user + " host = " + host);
}
}
public URI createURI(String uri) throws ServletParseException {
// if(!checkScheme(uri)) {
// // testCreateProxyBranches101 needs this to be IllegalArgumentExcpetion, but the test is wrong
// throw new ServletParseException("The uri " + uri + " is not valid");
// }
try {
javax.sip.address.URI jainUri = SipFactories.addressFactory
.createURI(uri);
if (jainUri instanceof javax.sip.address.SipURI) {
return new SipURIImpl(
(javax.sip.address.SipURI) jainUri);
} else if (jainUri instanceof javax.sip.address.TelURL) {
return new TelURLImpl(
(javax.sip.address.TelURL) jainUri);
} else {
return new GenericURIImpl(jainUri);
}
} catch (ParseException ex) {
throw new ServletParseException("Bad param " + uri, ex);
}
}
// ------------ HELPER METHODS
// -------------------- createRequest
/**
* Does basic check for illegal methods, wrong state, if it finds, it throws
* exception
*
*/
private static void validateCreation(String method, SipApplicationSession app) {
if (method.equals(Request.ACK)) {
throw new IllegalArgumentException(
"Wrong method to create request with[" + Request.ACK + "]!");
}
if (method.equals(Request.PRACK)) {
throw new IllegalArgumentException(
"Wrong method to create request with[" + Request.PRACK + "]!");
}
if (method.equals(Request.CANCEL)) {
throw new IllegalArgumentException(
"Wrong method to create request with[" + Request.CANCEL
+ "]!");
}
if (!app.isValid()) {
throw new IllegalArgumentException(
"Cant associate request with invalidaded sip session application!");
}
}
/**
* This method actually does create javax.sip.message.Request, dialog(if
* method is INVITE or SUBSCRIBE), ctx and wraps this in new sipsession
*
* @param sipAppSession
* @param method
* @param from
* @param to
* @return
*/
private SipServletRequest createSipServletRequest(
SipApplicationSession sipAppSession, String method, Address from,
Address to, String handler) throws ServletParseException {
MobicentsSipApplicationSession mobicentsSipApplicationSession = (MobicentsSipApplicationSession) sipAppSession;
// the request object with method, request URI, and From, To, Call-ID,
// CSeq, Route headers filled in.
Request requestToWrap = null;
ContactHeader contactHeader = null;
ToHeader toHeader = null;
FromHeader fromHeader = null;
CSeqHeader cseqHeader = null;
CallIdHeader callIdHeader = null;
MaxForwardsHeader maxForwardsHeader = null;
// FIXME: Is this nough?
// We need address from which this will be sent, also this one will be
// default for contact and via
String transport = ListeningPoint.UDP;
// LETS CREATE OUR HEADERS
javax.sip.address.Address fromAddress = null;
try {
// Issue 676 : Any component of the from and to URIs not allowed in the context of
// SIP From and To headers are removed from the copies [refer Table 1, Section
// 19.1.1, RFC3261]
for(String param : forbbidenParams) {
from.getURI().removeParameter(param);
}
// Issue 676 : from tags not removed so removing the tag
from.removeParameter(TAG_PARAM);
fromAddress = SipFactories.addressFactory
.createAddress(((URIImpl)from.getURI()).getURI());
fromAddress.setDisplayName(from.getDisplayName());
fromHeader = SipFactories.headerFactory.createFromHeader(fromAddress, null);
} catch (Exception pe) {
throw new ServletParseException("Impossoible to parse the given From " + from.toString(), pe);
}
javax.sip.address.Address toAddress = null;
try{
// Issue 676 : Any component of the from and to URIs not allowed in the context of
// SIP From and To headers are removed from the copies [refer Table 1, Section
// 19.1.1, RFC3261]
for(String param : forbbidenParams) {
to.getURI().removeParameter(param);
}
// Issue 676 : to tags not removed so removing the tag
to.removeParameter(TAG_PARAM);
toAddress = SipFactories.addressFactory
.createAddress(((URIImpl)to.getURI()).getURI());
toAddress.setDisplayName(to.getDisplayName());
toHeader = SipFactories.headerFactory.createToHeader(toAddress, null);
} catch (Exception pe) {
throw new ServletParseException("Impossoible to parse the given To " + to.toString(), pe);
}
try {
cseqHeader = SipFactories.headerFactory.createCSeqHeader(1L, method);
// Fix provided by Hauke D. Issue 411
SipApplicationSessionKey sipApplicationSessionKey = mobicentsSipApplicationSession.getKey();
// if(sipApplicationSessionKey.isAppGeneratedKey()) {
callIdHeader = SipFactories.headerFactory.createCallIdHeader(
getSipNetworkInterfaceManager().getExtendedListeningPoints().next().getSipProvider().getNewCallId().getCallId());
// } else {
// callIdHeader = SipFactories.headerFactory.createCallIdHeader(
// sipApplicationSessionKey.getId());
// }
maxForwardsHeader = SipFactories.headerFactory
.createMaxForwardsHeader(JainSipUtils.MAX_FORWARD_HEADER_VALUE);
URIImpl requestURI = (URIImpl)to.getURI().clone();
// copying address params into headers.
Iterator<String> keys = to.getParameterNames();
while (keys.hasNext()) {
String key = keys.next();
toHeader.setParameter(key, to.getParameter(key));
}
keys = from.getParameterNames();
while (keys.hasNext()) {
String key = keys.next();
fromHeader.setParameter(key, from.getParameter(key));
}
//Issue 112 by folsson : no via header to add will be added when the request will be sent out
List<Header> viaHeaders = new ArrayList<Header>();
requestToWrap = SipFactories.messageFactory.createRequest(
requestURI.getURI(),
method,
callIdHeader,
cseqHeader,
fromHeader,
toHeader,
viaHeaders,
maxForwardsHeader);
//Adding default contact header for register
if(Request.REGISTER.equalsIgnoreCase(method)) {
String fromName = null;
if(fromHeader.getAddress().getURI() instanceof javax.sip.address.SipURI) {
fromName = ((javax.sip.address.SipURI)fromHeader.getAddress().getURI()).getUser();
}
// Create the contact name address.
contactHeader = null;
// if a sip load balancer is present in front of the server, the contact header is the one from the sip lb
// so that the subsequent requests can be failed over
if(useLoadBalancer) {
javax.sip.address.SipURI sipURI = SipFactories.addressFactory.createSipURI(fromName, loadBalancerToUse.getAddress().getHostAddress());
sipURI.setHost(loadBalancerToUse.getAddress().getHostAddress());
sipURI.setPort(loadBalancerToUse.getSipPort());
sipURI.setTransportParam(transport);
javax.sip.address.Address contactAddress = SipFactories.addressFactory.createAddress(sipURI);
if(fromName != null && fromName.length() > 0) {
contactAddress.setDisplayName(fromName);
}
contactHeader = SipFactories.headerFactory.createContactHeader(contactAddress);
} else {
contactHeader = JainSipUtils.createContactHeader(getSipNetworkInterfaceManager(), requestToWrap, fromName);
}
}
// Add all headers
if(contactHeader != null) {
requestToWrap.addHeader(contactHeader);
}
fromHeader.setTag(ApplicationRoutingHeaderComposer.getHash(sipApplicationDispatcher, sipAppSession.getApplicationName(), sipApplicationSessionKey.getId()));
SipSessionKey key = SessionManagerUtil.getSipSessionKey(
mobicentsSipApplicationSession.getKey().getId(), mobicentsSipApplicationSession.getKey().getApplicationName(), requestToWrap, false);
MobicentsSipSession session = ((SipManager)mobicentsSipApplicationSession.getSipContext().getManager()).
getSipSession(key, true, this, mobicentsSipApplicationSession);
session.setHandler(handler);
session.setLocalParty(new AddressImpl(fromAddress, null, false));
session.setRemoteParty(new AddressImpl(toAddress, null, false));
SipServletRequest retVal = new SipServletRequestImpl(
requestToWrap, this, session, null, null,
JainSipUtils.dialogCreatingMethods.contains(method));
return retVal;
} catch (Exception e) {
logger.error("Error creating sipServletRequest", e);
}
return null;
}
/**
* {@inheritDoc}
*/
public Parameterable createParameterable(String value) throws ServletParseException {
try {
Header header = SipFactories.headerFactory.createHeader(ContactHeader.NAME, value);
return SipServletMessageImpl.createParameterable(header, SipServletMessageImpl.getFullHeaderName(header.getName()));
} catch (ParseException e) {
try {
Header header = SipFactories.headerFactory.createHeader(ContentTypeHeader.NAME, value);
return SipServletMessageImpl.createParameterable(header, SipServletMessageImpl.getFullHeaderName(header.getName()));
} catch (ParseException pe) {
throw new ServletParseException("Impossible to parse the following parameterable "+ value , pe);
}
}
}
/**
* {@inheritDoc}
*/
public SipApplicationRouterInfo getNextInterestedApplication(SipServletRequestImpl sipServletRequestImpl) {
return sipApplicationDispatcher.getNextInterestedApplication(sipServletRequestImpl);
}
/*
* (non-Javadoc)
* @see javax.servlet.sip.SipFactory#createApplicationSessionByAppName(java.lang.String)
*/
public SipApplicationSession createApplicationSessionByAppName(
String sipAppName) {
if (logger.isDebugEnabled()) {
logger.debug("Creating new application session for application name " + sipAppName);
}
SipContext sipContext = sipApplicationDispatcher.findSipApplication(sipAppName);
if(sipContext == null) {
throw new IllegalArgumentException("The specified application "+sipAppName+" is not currently deployed");
}
return createApplicationSession(sipContext);
}
/*
* (non-Javadoc)
* @see javax.servlet.sip.SipFactory#createApplicationSessionByKey(java.lang.String)
*/
public SipApplicationSession createApplicationSessionByKey(
String sipApplicationKey) {
if (logger.isDebugEnabled()) {
logger.debug("Creating new application session by following key " + sipApplicationKey);
}
SipApplicationSessionKey sipApplicationSessionKey = null;
try {
sipApplicationSessionKey = SessionManagerUtil.parseSipApplicationSessionKey(
sipApplicationKey);
} catch (ParseException e) {
throw new IllegalArgumentException(sipApplicationKey + " is not a valid sip application session key", e);
}
SipContext sipContext = sipApplicationDispatcher.findSipApplication(sipApplicationSessionKey.getApplicationName());
if(sipContext == null) {
throw new IllegalArgumentException("The specified application "+sipApplicationSessionKey.getApplicationName()+" is not currently deployed");
}
MobicentsSipApplicationSession sipApplicationSession = ((SipManager)sipContext.getManager()).getSipApplicationSession(
sipApplicationSessionKey, true);
return sipApplicationSession.getSession();
}
/*
* (non-Javadoc)
* @see javax.servlet.sip.SipFactory#createAuthInfo()
*/
public AuthInfo createAuthInfo() {
return new AuthInfoImpl();
}
/**
* @return the sipApplicationDispatcher
*/
public SipApplicationDispatcher getSipApplicationDispatcher() {
return sipApplicationDispatcher;
}
/**
* @param sipApplicationDispatcher the sipApplicationDispatcher to set
*/
public void setSipApplicationDispatcher(
SipApplicationDispatcher sipApplicationDispatcher) {
this.sipApplicationDispatcher = sipApplicationDispatcher;
}
/**
* Retrieve the manager for the sip network interfaces
* @return the manager for the sip network interfaces
*/
public SipNetworkInterfaceManager getSipNetworkInterfaceManager() {
return sipApplicationDispatcher.getSipNetworkInterfaceManager();
}
/**
* @return the loadBalancerToUse
*/
public BalancerDescription getLoadBalancerToUse() {
return loadBalancerToUse;
}
/**
* @param loadBalancerToUse the loadBalancerToUse to set
*/
public void setLoadBalancerToUse(BalancerDescription loadBalancerToUse) {
if(loadBalancerToUse == null) {
useLoadBalancer = false;
} else {
useLoadBalancer = true;
}
this.loadBalancerToUse = loadBalancerToUse;
}
/**
* @return the useLoadBalancer
*/
public boolean isUseLoadBalancer() {
return useLoadBalancer;
}
/**
*
* @param request
* @throws ParseException
*/
public void addLoadBalancerRouteHeader(Request request) {
try {
javax.sip.address.SipURI sipUri = SipFactories.addressFactory.createSipURI(null, loadBalancerToUse.getAddress().getHostAddress());
sipUri.setPort(loadBalancerToUse.getSipPort());
sipUri.setLrParam();
String transport = JainSipUtils.findTransport(request);
sipUri.setTransportParam(transport);
ExtendedListeningPoint listeningPoint =
getSipNetworkInterfaceManager().findMatchingListeningPoint(transport, false);
sipUri.setParameter(MessageDispatcher.ROUTE_PARAM_NODE_HOST,
listeningPoint.getHost(JainSipUtils.findUsePublicAddress(getSipNetworkInterfaceManager(), request, listeningPoint)));
sipUri.setParameter(MessageDispatcher.ROUTE_PARAM_NODE_PORT,
"" + listeningPoint.getPort());
javax.sip.address.Address routeAddress =
SipFactories.addressFactory.createAddress(sipUri);
RouteHeader routeHeader =
SipFactories.headerFactory.createRouteHeader(routeAddress);
request.addFirst(routeHeader);
} catch (ParseException e) {
//this should never happen
throw new IllegalArgumentException("Impossible to set the Load Balancer Route Header !", e);
} catch (SipException e) {
//this should never happen
throw new IllegalArgumentException("Impossible to set the Load Balancer Route Header !", e);
}
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
useLoadBalancer = in.readBoolean();
if(useLoadBalancer) {
loadBalancerToUse = (BalancerDescription) in.readObject();
}
sipApplicationDispatcher = StaticServiceHolder.sipStandardService.getSipApplicationDispatcher();
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeBoolean(useLoadBalancer);
if(useLoadBalancer) {
out.writeObject(loadBalancerToUse);
}
}
}