
org.mobicents.servlet.sip.startup.SipStandardContext Maven / Gradle / Ivy
The newest version!
/*
* TeleStax, Open Source Cloud Communications
* Copyright 2011-2014, Telestax Inc and individual contributors
* by the @authors tag.
*
* This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see
*/
package org.mobicents.servlet.sip.startup;
import static org.jboss.web.CatalinaMessages.MESSAGES;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EventListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.sip.SipServlet;
import javax.servlet.sip.SipServletContextEvent;
import javax.servlet.sip.SipServletListener;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.TimerService;
import org.apache.catalina.Container;
import org.apache.catalina.Engine;
import org.apache.catalina.Globals;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Manager;
import org.apache.catalina.Service;
import org.apache.catalina.Wrapper;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.security.SecurityUtil;
import org.apache.log4j.Logger;
import org.apache.tomcat.InstanceManager;
import org.mobicents.servlet.sip.SipConnector;
import org.mobicents.servlet.sip.annotation.ConcurrencyControlMode;
import org.mobicents.servlet.sip.catalina.CatalinaSipContext;
import org.mobicents.servlet.sip.catalina.CatalinaSipListenersHolder;
import org.mobicents.servlet.sip.catalina.CatalinaSipManager;
import org.mobicents.servlet.sip.catalina.SARDirContext;
import org.mobicents.servlet.sip.catalina.SipDeploymentException;
import org.mobicents.servlet.sip.catalina.SipSecurityConstraint;
import org.mobicents.servlet.sip.catalina.SipServletImpl;
import org.mobicents.servlet.sip.catalina.SipStandardManager;
import org.mobicents.servlet.sip.catalina.annotations.SipInstanceManager;
import org.mobicents.servlet.sip.catalina.security.SipSecurityUtils;
import org.mobicents.servlet.sip.catalina.security.authentication.DigestAuthenticator;
import org.mobicents.servlet.sip.core.MobicentsSipServlet;
import org.mobicents.servlet.sip.core.SipApplicationDispatcher;
import org.mobicents.servlet.sip.core.SipContextEvent;
import org.mobicents.servlet.sip.core.SipContextEventType;
import org.mobicents.servlet.sip.core.SipListeners;
import org.mobicents.servlet.sip.core.SipManager;
import org.mobicents.servlet.sip.core.SipService;
import org.mobicents.servlet.sip.core.descriptor.MobicentsSipServletMapping;
import org.mobicents.servlet.sip.core.message.MobicentsSipServletRequest;
import org.mobicents.servlet.sip.core.message.MobicentsSipServletResponse;
import org.mobicents.servlet.sip.core.security.MobicentsSipLoginConfig;
import org.mobicents.servlet.sip.core.security.SipDigestAuthenticator;
import org.mobicents.servlet.sip.core.session.DistributableSipManager;
import org.mobicents.servlet.sip.core.session.MobicentsSipApplicationSession;
import org.mobicents.servlet.sip.core.session.MobicentsSipSession;
import org.mobicents.servlet.sip.core.session.SipApplicationSessionCreationThreadLocal;
import org.mobicents.servlet.sip.core.session.SipSessionsUtilImpl;
import org.mobicents.servlet.sip.core.timers.ProxyTimerService;
import org.mobicents.servlet.sip.core.timers.ProxyTimerServiceImpl;
import org.mobicents.servlet.sip.core.timers.SipApplicationSessionTimerService;
import org.mobicents.servlet.sip.core.timers.SipServletTimerService;
import org.mobicents.servlet.sip.core.timers.StandardSipApplicationSessionTimerService;
import org.mobicents.servlet.sip.core.timers.TimerServiceImpl;
import org.mobicents.servlet.sip.dns.MobicentsDNSResolver;
import org.mobicents.servlet.sip.listener.SipConnectorListener;
import org.mobicents.servlet.sip.message.SipFactoryFacade;
import org.mobicents.servlet.sip.message.SipFactoryImpl;
import org.mobicents.servlet.sip.ruby.SipRubyController;
/**
* Sip implementation of the Context interface extending the standard
* tomcat context to allow deployment of converged applications (sip & web apps)
* as well as standalone sip servlets applications.
*
* @author Jean Deruelle
*
*/
public class SipStandardContext extends StandardContext implements CatalinaSipContext {
private static final long serialVersionUID = 1L;
// the logger
private static final Logger logger = Logger.getLogger(SipStandardContext.class);
private transient SipRubyController rubyController;
/**
* The descriptive information string for this implementation.
*/
private static final String info =
"org.mobicents.servlet.sip.startup.SipStandardContext/1.0";
// as mentionned per JSR 289 Section 6.1.2.1 default lifetime for an
// application session is 3 minutes
private static int DEFAULT_LIFETIME = 3;
protected String applicationName;
protected String smallIcon;
protected String largeIcon;
protected String description;
protected int proxyTimeout;
protected int sipApplicationSessionTimeout;
protected transient SipListeners sipListeners;
protected transient SipFactoryFacade sipFactoryFacade;
protected transient SipSessionsUtilImpl sipSessionsUtil;
protected transient MobicentsSipLoginConfig sipLoginConfig;
protected transient SipSecurityUtils sipSecurityUtils;
protected transient SipDigestAuthenticator sipDigestAuthenticator;
protected transient String securityDomain;
protected boolean hasDistributableManager;
protected String namingContextName;
protected transient Method sipApplicationKeyMethod;
protected ConcurrencyControlMode concurrencyControlMode;
/**
* The set of sip application listener class names configured for this
* application, in the order they were encountered in the sip.xml file.
*/
protected transient List sipApplicationListeners = new CopyOnWriteArrayList();
// Issue 1200 this is needed to be able to give a default servlet handler if we are not in main-servlet servlet selection case
// by example when creating a new sip application session from a factory from an http servlet
private String servletHandler;
protected boolean isMainServlet;
private String mainServlet;
/**
* The set of sip servlet mapping configured for this
* application.
*/
protected transient List sipServletMappings = new ArrayList();
protected transient SipApplicationDispatcher sipApplicationDispatcher = null;
protected transient Map childrenMap;
protected transient Map childrenMapByClassName;
// timer service used to schedule sip application session expiration timer
protected transient SipApplicationSessionTimerService sasTimerService = null;
// timer service used to schedule sip servlet originated timer tasks
protected transient SipServletTimerService timerService = null;
// timer service used to schedule proxy timer tasks
protected transient ProxyTimerService proxyTimerService = null;
// http://code.google.com/p/mobicents/issues/detail?id=2450
private transient ThreadLocal sipApplicationSessionsAccessedThreadLocal = new ThreadLocal();
// http://code.google.com/p/mobicents/issues/detail?id=2534 && http://code.google.com/p/mobicents/issues/detail?id=2526
private transient ThreadLocal isManagedThread = new ThreadLocal();
/**
*
*/
public SipStandardContext() {
super();
sipApplicationSessionTimeout = DEFAULT_LIFETIME;
pipeline.setBasic(new SipStandardContextValve());
sipListeners = new CatalinaSipListenersHolder(this);
childrenMap = new HashMap();
childrenMapByClassName = new HashMap();
int idleTime = getSipApplicationSessionTimeout();
if(idleTime <= 0) {
idleTime = 1;
}
isMainServlet = false;
}
@Override
public void init() throws Exception {
if(logger.isDebugEnabled()) {
logger.debug("Initializing the sip context");
}
// if (this.getParent() != null) {
// // Add the main configuration listener for sip applications
// LifecycleListener sipConfigurationListener = new SipContextConfig();
// this.addLifecycleListener(sipConfigurationListener);
// setDelegate(true);
// }
// call the super method to correctly initialize the context and fire
// up the
// init event on the new registered SipContextConfig, so that the
// standardcontextconfig
// is correctly initialized too
super.init();
prepareServletContext();
if(logger.isDebugEnabled()) {
logger.debug("sip context Initialized");
}
}
protected void prepareServletContext() throws LifecycleException {
if(sipApplicationDispatcher == null) {
setApplicationDispatcher();
}
if(sipFactoryFacade == null) {
sipFactoryFacade = new SipFactoryFacade((SipFactoryImpl)sipApplicationDispatcher.getSipFactory(), this);
}
if(sipSessionsUtil == null) {
sipSessionsUtil = new SipSessionsUtilImpl(this);
}
//needed when restarting applications through the tomcat manager
this.getServletContext().setAttribute(javax.servlet.sip.SipServlet.SIP_FACTORY,
sipFactoryFacade);
if(timerService == null) {
// FIXME: distributable not supported
// if(getDistributable() && hasDistributableManager) {
// if(logger.isInfoEnabled()) {
// logger.info("Using the Fault Tolerant Timer Service to schedule fault tolerant timers in a distributed environment");
// }
// timerService = new FaultTolerantTimerServiceImpl((DistributableSipManager)getSipManager());
// } else {
// timerService = new TimerServiceImpl();
// }
timerService = new TimerServiceImpl(sipApplicationDispatcher.getSipService());
}
if(proxyTimerService == null) {
proxyTimerService = new ProxyTimerServiceImpl();
}
if(sasTimerService == null || !sasTimerService.isStarted()) {
// FIXME: distributable not supported
//distributable if(getDistributable() && hasDistributableManager) {
// sasTimerService = new FaultTolerantSasTimerService((DistributableSipManager)getSipManager(), 4);
// } else {
// sasTimerService = new StandardSipApplicationSessionTimerService();
// }
sasTimerService = new StandardSipApplicationSessionTimerService();
}
this.getServletContext().setAttribute(javax.servlet.sip.SipServlet.TIMER_SERVICE,
timerService);
this.getServletContext().setAttribute(javax.servlet.sip.SipServlet.SUPPORTED,
Arrays.asList(sipApplicationDispatcher.getExtensionsSupported()));
this.getServletContext().setAttribute("javax.servlet.sip.100rel", Boolean.TRUE);
this.getServletContext().setAttribute(javax.servlet.sip.SipServlet.SUPPORTED_RFCs,
Arrays.asList(sipApplicationDispatcher.getRfcSupported()));
this.getServletContext().setAttribute(javax.servlet.sip.SipServlet.SIP_SESSIONS_UTIL,
sipSessionsUtil);
this.getServletContext().setAttribute(javax.servlet.sip.SipServlet.OUTBOUND_INTERFACES,
sipApplicationDispatcher.getOutboundInterfaces());
this.getServletContext().setAttribute("org.mobicents.servlet.sip.SIP_CONNECTORS",
sipApplicationDispatcher.getSipService().findSipConnectors());
this.getServletContext().setAttribute("org.mobicents.servlet.sip.DNS_RESOLVER",
sipApplicationDispatcher.getDNSResolver());
}
/**
* @throws Exception
*/
protected void setApplicationDispatcher() throws LifecycleException {
Container container = getParent().getParent();
if(container instanceof Engine) {
Service service = ((Engine)container).getService();
if(service instanceof SipService) {
sipApplicationDispatcher =
((SipService)service).getSipApplicationDispatcher();
}
}
if(sipApplicationDispatcher == null) {
throw new LifecycleException("cannot find any application dispatcher for this context " + name);
}
}
@Override
public synchronized void start() throws LifecycleException {
if(logger.isDebugEnabled()) {
logger.debug("Starting the sip context " + getName());
}
if( initialized ) {
prepareServletContext();
}
// Add missing components as necessary
if (getResources() == null) { // (1) Required by Loader
if (logger.isDebugEnabled())
logger.debug("Configuring default Resources");
try {
if ((getDocBase() != null) && (getDocBase().endsWith(".sar")) && (!(new File(getBasePath())).isDirectory()))
setResources(new SARDirContext());
} catch (IllegalArgumentException e) {
logger.error("Error initializing resources: " + e.getMessage());
// ok = false;
}
}
// Configure default manager if none was specified
if (manager == null) {
if ((getCluster() != null) && getDistributable()) {
try {
manager = getCluster().createManager(getName());
} catch (Exception ex) {
logger.error("standardContext.clusterFail", ex);
// ok = false;
}
} else {
setManager(new SipStandardManager());
}
}
//JSR 289 Section 2.1.1 Step 1.Deploy the application.
//This will make start the sip context config, which will in turn parse the sip descriptor deployment
//and call load on startup which is equivalent to
//JSR 289 Section 2.1.1 Step 2.Invoke servlet.init(), the initialization method on the Servlet. Invoke the init() on all the load-on-startup Servlets in the applicatio
if(manager instanceof DistributableSipManager) {
// due to refactoring on http://code.google.com/p/mobicents/issues/detail?id=2794
// we set the container on the manager right before the start and after the context have been init-ed
hasDistributableManager = true;
if(logger.isDebugEnabled()) {
logger.debug("this context contains a manager that allows applications to work in a distributed environment");
}
((SipManager)getManager()).setMobicentsSipFactory(
(sipApplicationDispatcher.getSipFactory()));
((CatalinaSipManager)manager).setContainer(this);
}
super.start();
if(getAvailable()) {
//set the session manager on the specific sipstandardmanager to handle converged http sessions
if(!(getManager() instanceof DistributableSipManager) && getManager() instanceof CatalinaSipManager) {
((SipManager)getManager()).setMobicentsSipFactory(
(sipApplicationDispatcher.getSipFactory()));
((CatalinaSipManager)manager).setContainer(this);
}
// JSR 289 16.2 Servlet Selection
// When using this mechanism (the main-servlet) for servlet selection,
// if there is only one servlet in the application then this
// declaration is optional and the lone servlet becomes the main servlet
if((mainServlet == null || mainServlet.length() < 1) && childrenMap.size() == 1) {
setMainServlet(childrenMap.keySet().iterator().next());
}
sipSecurityUtils = new SipSecurityUtils(this);
sipDigestAuthenticator = new DigestAuthenticator(sipApplicationDispatcher.getSipFactory().getHeaderFactory());
//JSR 289 Section 2.1.1 Step 3.Invoke SipApplicationRouter.applicationDeployed() for this application.
//called implicitly within sipApplicationDispatcher.addSipApplication
sipApplicationDispatcher.addSipApplication(applicationName, this);
if(manager instanceof DistributableSipManager) {
// only call the setContainer on the manager when it has been fully initialized
hasDistributableManager = true;
if(logger.isDebugEnabled()) {
logger.debug("this context contains a manager that allows applications to work in a distributed environment");
}
((SipManager)getManager()).setMobicentsSipFactory(
(sipApplicationDispatcher.getSipFactory()));
((CatalinaSipManager)manager).setContainer(this);
}
if(logger.isDebugEnabled()) {
logger.debug("sip application session timeout for this context is " + sipApplicationSessionTimeout + " minutes");
}
if(logger.isDebugEnabled()) {
logger.debug("http session timeout for this context is " + getSessionTimeout() + " minutes");
}
if(logger.isDebugEnabled()) {
logger.debug("sip context started " + getName());
}
} else {
if(logger.isInfoEnabled()) {
logger.info("sip context " + getName() + " didn't started due to errors");
}
}
}
@Override
public ServletContext getServletContext() {
if (context == null) {
context = new ConvergedApplicationContext(getBasePath(), this);
if (getAltDDName() != null)
context.setAttribute(Globals.ALT_DD_ATTR,getAltDDName());
}
return ((ConvergedApplicationContext)context).getFacade();
}
// AS7 invokes this before listenerStart()
@Override
public boolean contextListenerStart() {
boolean ok = super.contextListenerStart();
//the web listeners couldn't be started so we don't even try to load the sip ones
if(!ok) {
return ok;
}
if (logger.isDebugEnabled())
logger.debug("Configuring sip listeners");
// Instantiate the required listeners
ClassLoader loader = getLoader().getClassLoader();
ok = sipListeners.loadListeners(findSipApplicationListeners(), loader);
if(!ok) {
return ok;
}
List servletContextListeners = sipListeners.getServletContextListeners();
if (servletContextListeners != null) {
ServletContextEvent event =
new ServletContextEvent(getServletContext());
for (ServletContextListener servletContextListener : servletContextListeners) {
if (servletContextListener == null)
continue;
try {
fireContainerEvent("beforeContextInitialized", servletContextListener);
servletContextListener.contextInitialized(event);
fireContainerEvent("afterContextInitialized", servletContextListener);
} catch (Throwable t) {
fireContainerEvent("afterContextInitialized", servletContextListener);
// getLogger().error
// (sm.getString("standardContext.listenerStart",
// servletContextListener.getClass().getName()), t);
getLogger().error
(MESSAGES.errorSendingContextInitializedEvent(servletContextListener.getClass().getName()), t);
ok = false;
}
// TODO Annotation processing
}
}
return (ok);
}
@Override
public boolean listenerStart() {
boolean ok = super.listenerStart();
//the web listeners couldn't be started so we don't even try to load the sip ones
if(!ok) {
return ok;
}
if (logger.isDebugEnabled())
logger.debug("Configuring sip listeners");
return ok;
}
@Override
public boolean listenerStop() {
boolean ok = super.listenerStop();
if (logger.isDebugEnabled())
logger.debug("Sending application stop events");
List servletContextListeners = sipListeners.getServletContextListeners();
if (servletContextListeners != null) {
ServletContextEvent event =
new ServletContextEvent(getServletContext());
for (ServletContextListener servletContextListener : servletContextListeners) {
if (servletContextListener == null)
continue;
try {
fireContainerEvent("beforeContextDestroyed", servletContextListener);
servletContextListener.contextDestroyed(event);
fireContainerEvent("afterContextDestroyed", servletContextListener);
} catch (Throwable t) {
fireContainerEvent("afterContextDestroyed", servletContextListener);
// getLogger().error
// (sm.getString("standardContext.listenerStop",
// servletContextListener.getClass().getName()), t);
getLogger().error
(MESSAGES.errorSendingContextDestroyedEvent(servletContextListener.getClass().getName()), t);
ok = false;
}
// TODO Annotation processing
}
}
// TODO Annotation processing check super class on tomcat 6
sipListeners.clean();
return ok;
}
/**
* Get base path. Copy pasted from StandardContext Tomcat class
*/
public String getBasePath() {
String docBase = null;
Container container = this;
while (container != null) {
if (container instanceof Host)
break;
container = container.getParent();
}
File file = new File(getDocBase());
if (!file.isAbsolute()) {
if (container == null) {
docBase = (new File(engineBase(), getDocBase())).getPath();
} else {
// Use the "appBase" property of this container
String appBase = ((Host) container).getAppBase();
file = new File(appBase);
if (!file.isAbsolute())
file = new File(engineBase(), appBase);
docBase = (new File(file, getDocBase())).getPath();
}
} else {
docBase = file.getPath();
}
return docBase;
}
@Override
public synchronized void stop() throws LifecycleException {
if(logger.isDebugEnabled()) {
logger.debug("Stopping the sip context " + getName());
}
if(manager instanceof SipManager) {
((SipManager)manager).dumpSipSessions();
((SipManager)manager).dumpSipApplicationSessions();
logger.warn("number of active sip sessions : " + ((SipManager)manager).getActiveSipSessions());
logger.warn("number of active sip application sessions : " + ((SipManager)manager).getActiveSipApplicationSessions());
}
super.stop();
// this should happen after so that applications can still do some processing
// in destroy methods to notify that context is getting destroyed and app removed
sipListeners.deallocateServletsActingAsListeners();
sipApplicationListeners.clear();
sipServletMappings.clear();
childrenMap.clear();
childrenMapByClassName.clear();
if(sipApplicationDispatcher != null) {
if(applicationName != null) {
sipApplicationDispatcher.removeSipApplication(applicationName);
} else {
logger.error("the application name is null for the following context : " + name);
}
}
if(sasTimerService != null && sasTimerService.isStarted()) {
sasTimerService.stop();
}
// Issue 1478 : nullify the ref to avoid reusing it
sasTimerService = null;
// Issue 1791 : don't check is the service is started it makes the stop
// of tomcat hang
if(timerService != null) {
timerService.stop();
}
if(proxyTimerService != null) {
proxyTimerService.stop();
}
// Issue 1478 : nullify the ref to avoid reusing it
timerService = null;
getServletContext().setAttribute(javax.servlet.sip.SipServlet.TIMER_SERVICE, null);
if(logger.isDebugEnabled()) {
logger.debug("sip context stopped " + getName());
}
}
@Override
public void loadOnStartup(Container[] containers) {
super.loadOnStartup(containers);
}
@Override
public Wrapper createWrapper() {
return super.createWrapper();
}
@Override
public void addChild(Container container) {
if(container instanceof Wrapper) {
// Added for Issue http://code.google.com/p/mobicents/issues/detail?id=2382
Wrapper wrapper = (Wrapper) container;
SipServletImpl sipServletImpl = (SipServletImpl) childrenMap.get(container.getName());
if(sipServletImpl != null && !sipServletImpl.getServletClass().equals(wrapper.getServletClass())) {
throw new SipDeploymentException("Trying to add a servlet with name " + container.getName() + " and servlet class " + wrapper.getServletClass() +
" while there is already a SIP Servlet with the same name and a different servlet class " + sipServletImpl.getServletClass());
}
}
if(children.get(container.getName()) == null) {
super.addChild(container);
} else {
if(logger.isDebugEnabled()) {
logger.debug(container.getName() + " already present as a Sip Servlet not adding it again");
}
}
}
public void addChild(SipServletImpl sipServletImpl) {
SipServletImpl existingServlet = (SipServletImpl) childrenMap.get(sipServletImpl.getName());
if(existingServlet != null) {
logger.warn(sipServletImpl.getName() + " servlet already present, removing the previous one. " +
"This might be due to the fact that the definition of the servlet " +
"is present both in annotations and in sip.xml");
//we remove the previous one (annoations) because it may not have init parameters that has been defined in sip.xml
//See TCK Test ContextTest.testContext1
childrenMap.remove(sipServletImpl.getName());
childrenMapByClassName.remove(sipServletImpl.getServletClass());
super.removeChild(existingServlet);
}
childrenMap.put(sipServletImpl.getName(), sipServletImpl);
childrenMapByClassName.put(sipServletImpl.getServletClass(), sipServletImpl);
super.addChild(sipServletImpl);
}
public void removeChild(SipServletImpl sipServletImpl) {
super.removeChild(sipServletImpl);
childrenMap.remove(sipServletImpl.getName());
childrenMapByClassName.remove(sipServletImpl.getServletClass());
}
/**
* {@inheritDoc}
*/
public Map getChildrenMap() {
return childrenMap;
}
/**
* {@inheritDoc}
*/
public MobicentsSipServlet findSipServletByName(String name) {
if (name == null)
return (null);
return childrenMap.get(name);
}
/**
* {@inheritDoc}
*/
public MobicentsSipServlet findSipServletByClassName(String className) {
if (className == null)
return (null);
return childrenMapByClassName.get(className);
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#getApplicationName()
*/
public String getApplicationName() {
return applicationName;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#getApplicationNameHashed()
*/
public String getApplicationNameHashed() {
return sipApplicationDispatcher.getHashFromApplicationName(applicationName);
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#setApplicationName(java.lang.String)
*/
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#getDescription()
*/
public String getDescription() {
return description;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#setDescription(java.lang.String)
*/
public void setDescription(String description) {
this.description = description;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#getLargeIcon()
*/
public String getLargeIcon() {
return largeIcon;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#setLargeIcon(java.lang.String)
*/
public void setLargeIcon(String largeIcon) {
this.largeIcon = largeIcon;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#getListeners()
*/
public SipListeners getListeners() {
return sipListeners;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#setListeners(org.mobicents.servlet.sip.core.session.SipListenersHolder)
*/
public void setListeners(SipListeners listeners) {
this.sipListeners = (CatalinaSipListenersHolder) listeners;
}
/*
* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#isMainServlet()
*/
public boolean isMainServlet() {
return isMainServlet;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#getMainServlet()
*/
public String getMainServlet() {
return mainServlet;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#setMainServlet(java.lang.String)
*/
public void setMainServlet(String mainServlet) {
this.mainServlet = mainServlet;
servletHandler = mainServlet;
this.isMainServlet = true;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#getProxyTimeout()
*/
public int getProxyTimeout() {
return proxyTimeout;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#setProxyTimeout(int)
*/
public void setProxyTimeout(int proxyTimeout) {
this.proxyTimeout = proxyTimeout;
}
public void addConstraint(SipSecurityConstraint securityConstraint) {
super.addConstraint(securityConstraint);
}
public void removeConstraint(SipSecurityConstraint securityConstraint) {
super.removeConstraint(securityConstraint);
}
public void setSecurityDomain(String securityDomain) {
this.securityDomain = securityDomain;
}
public String getSecurityDomain() {
return securityDomain;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#getSmallIcon()
*/
public String getSmallIcon() {
return smallIcon;
}
/* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#setSmallIcon(java.lang.String)
*/
public void setSmallIcon(String smallIcon) {
this.smallIcon = smallIcon;
}
@Override
public void setLoginConfig(LoginConfig config) {
super.setLoginConfig(config);
}
@Override
public LoginConfig getLoginConfig() {
return super.getLoginConfig();
}
public void setSipLoginConfig(MobicentsSipLoginConfig config) {
this.sipLoginConfig = config;
}
public MobicentsSipLoginConfig getSipLoginConfig() {
return this.sipLoginConfig;
}
/**
* Add a new Listener class name to the set of Listeners
* configured for this application.
*
* @param listener Java class name of a listener class
*/
public void addSipApplicationListener(String listener) {
sipApplicationListeners.add(listener);
fireContainerEvent("addSipApplicationListener", listener);
// FIXME - add instance if already started?
}
/**
* Remove the specified application listener class from the set of
* listeners for this application.
*
* @param listener Java class name of the listener to be removed
*/
public void removeSipApplicationListener(String listener) {
sipApplicationListeners.remove(listener);
// Inform interested listeners
fireContainerEvent("removeSipApplicationListener", listener);
// FIXME - behavior if already started?
}
/**
* Return the set of sip application listener class names configured
* for this application.
*/
public String[] findSipApplicationListeners() {
return sipApplicationListeners.toArray(new String[sipApplicationListeners.size()]);
}
/**
* @return the sipApplicationDispatcher
*/
public SipApplicationDispatcher getSipApplicationDispatcher() {
return sipApplicationDispatcher;
}
/**
* @return the sipFactoryFacade
*/
public SipFactoryFacade getSipFactoryFacade() {
return sipFactoryFacade;
}
/**
* @return the sipSessionsUtil
*/
public SipSessionsUtilImpl getSipSessionsUtil() {
return sipSessionsUtil;
}
/**
* @return the timerService
*/
public TimerService getTimerService() {
return timerService;
}
/**
* @return the proxyTimerService
*/
public ProxyTimerService getProxyTimerService() {
return proxyTimerService;
}
/**
* Get naming context full name.
*/
private String getNamingContextName() {
if (namingContextName == null) {
Container parent = getParent();
if (parent == null) {
namingContextName = getName();
} else {
Stack stk = new Stack();
StringBuffer buff = new StringBuffer();
while (parent != null) {
stk.push(parent.getName());
parent = parent.getParent();
}
while (!stk.empty()) {
buff.append("/" + stk.pop());
}
buff.append(getName());
namingContextName = buff.toString();
}
}
return namingContextName;
}
@Override
public synchronized void setManager(Manager manager) {
if(getManager() != null && !manager.equals(getManager())) {
// http://code.google.com/p/mobicents/issues/detail?id=2794 : TimerService object from JDNI lookup or injection is never HATimerService. This means that timers scheduled using that object will not survive across cluster changes.
// Avoid the DistributableSipManager set by TomcatConvergedDeployment to be overriden by JBossContextConfig.processContextConfig that reset the distributable manager.
if(logger.isInfoEnabled()) {
logger.info("this context already contains a manager " + getManager() + " not setting new manager " + manager);
}
return;
}
if(manager instanceof CatalinaSipManager && sipApplicationDispatcher != null) {
((SipManager)manager).setMobicentsSipFactory(
sipApplicationDispatcher.getSipFactory());
((CatalinaSipManager)manager).setContainer(this);
}
super.setManager(manager);
if(manager instanceof DistributableSipManager) {
hasDistributableManager = true;
// if the logic comes unitl here, distributable is true, we set it to be able to start the FT timer services correctly on init
setDistributable(true);
if(logger.isInfoEnabled()) {
logger.info("this context contains a manager that allows applications to work in a distributed environment");
}
}
}
@Override
public Manager getManager() {
return super.getManager();
}
/**
* @return the sipApplicationSessionTimeout in minutes
*/
public int getSipApplicationSessionTimeout() {
return sipApplicationSessionTimeout;
}
/**
* @param sipApplicationSessionTimeout the sipApplicationSessionTimeout to set in minutes
*/
public void setSipApplicationSessionTimeout(int sipApplicationSessionTimeout) {
this.sipApplicationSessionTimeout = sipApplicationSessionTimeout;
}
public Method getSipApplicationKeyMethod() {
return sipApplicationKeyMethod;
}
public void setSipApplicationKeyMethod(Method sipApplicationKeyMethod) {
this.sipApplicationKeyMethod = sipApplicationKeyMethod;
}
public String getJbossBasePath() {
return getBasePath();
}
/**
* {@inheritDoc}
*/
public void addSipServletMapping(MobicentsSipServletMapping sipServletMapping) {
sipServletMappings.add(sipServletMapping);
isMainServlet = false;
if(servletHandler == null) {
servletHandler = sipServletMapping.getServletName();
}
}
/**
* {@inheritDoc}
*/
public List findSipServletMappings() {
return sipServletMappings;
}
/**
* {@inheritDoc}
*/
public MobicentsSipServletMapping findSipServletMappings(SipServletRequest sipServletRequest) {
if(logger.isDebugEnabled()) {
logger.debug("Checking sip Servlet Mapping for following request : " + sipServletRequest);
}
for (MobicentsSipServletMapping sipServletMapping : sipServletMappings) {
if(sipServletMapping.getMatchingRule().matches(sipServletRequest)) {
return sipServletMapping;
} else {
logger.debug("Following mapping rule didn't match : servletName => " +
sipServletMapping.getServletName() + " | expression = "+
sipServletMapping.getMatchingRule().getExpression());
}
}
return null;
}
/**
* {@inheritDoc}
*/
public void removeSipServletMapping(MobicentsSipServletMapping sipServletMapping) {
sipServletMappings.remove(sipServletMapping);
}
/**
* {@inheritDoc}
*/
public final SipManager getSipManager() {
return (SipManager)manager;
}
@Override
public String getInfo() {
return info;
}
// public AnnotationProcessor getAnnotationProcessor() {
// // TODO Auto-generated method stub
// return new DummyAnnotationProcessor();
// }
// ----------------------------------------------- DummyAnnotationProcessor Inner Class
// protected class DummyAnnotationProcessor implements AnnotationProcessor {
//
// public void postConstruct(Object instance)
// throws IllegalAccessException, InvocationTargetException {
// // Do nothing
// }
//
// public void preDestroy(Object instance) throws IllegalAccessException,
// InvocationTargetException {
// getInstanceManager().destroyInstance(instance);
// }
//
// public void processAnnotations(Object instance)
// throws IllegalAccessException, InvocationTargetException,
// NamingException {
// getInstanceManager().newInstance(instance);
// }
//
// }
/*
* (non-Javadoc)
* @see org.mobicents.servlet.sip.core.SipContext#enterSipApp(org.mobicents.servlet.sip.core.session.MobicentsSipApplicationSession, org.mobicents.servlet.sip.core.session.MobicentsSipSession, boolean, boolean)
*/
public void enterSipApp(MobicentsSipApplicationSession sipApplicationSession, MobicentsSipSession sipSession, boolean checkIsManagedThread, boolean isContainerManaged) {
switch (concurrencyControlMode) {
case SipSession:
if(sipSession != null) {
sipSession.acquire();
}
break;
case SipApplicationSession:
if(logger.isDebugEnabled()) {
logger.debug("checkIsManagedThread " + checkIsManagedThread + " , isManagedThread " + isManagedThread.get() + ", isContainerManaged " + isContainerManaged);
}
// http://code.google.com/p/mobicents/issues/detail?id=2534 && http://code.google.com/p/mobicents/issues/detail?id=2526
if(!checkIsManagedThread || (checkIsManagedThread && Boolean.TRUE.equals(isManagedThread.get()))) {
if(isManagedThread.get() == null) {
isManagedThread.set(Boolean.TRUE);
}
if(sipApplicationSession != null) {
SipApplicationSessionCreationThreadLocal sipApplicationSessionCreationThreadLocal = sipApplicationSessionsAccessedThreadLocal.get();
if(sipApplicationSessionCreationThreadLocal == null) {
sipApplicationSessionCreationThreadLocal = new SipApplicationSessionCreationThreadLocal();
sipApplicationSessionsAccessedThreadLocal.set(sipApplicationSessionCreationThreadLocal);
}
boolean notPresent = sipApplicationSessionCreationThreadLocal.getSipApplicationSessions().add(sipApplicationSession);
if(notPresent && isContainerManaged) {
if(logger.isDebugEnabled()) {
logger.debug("acquiring sipApplicationSession=" + sipApplicationSession +
" since it is not present in our local thread of accessed sip application sessions " );
}
sipApplicationSession.acquire();
} else if(logger.isDebugEnabled()) {
if(!isContainerManaged) {
logger.debug("not acquiring sipApplicationSession=" + sipApplicationSession +
" since application specified the container shouldn't manage it ");
} else {
logger.debug("not acquiring sipApplicationSession=" + sipApplicationSession +
" since it is present in our local thread of accessed sip application sessions ");
}
}
}
} else {
if(logger.isDebugEnabled()) {
logger.debug("not acquiring sipApplicationSession=" + sipApplicationSession +
" since isManagedThread is " + isManagedThread.get());
}
}
break;
case None:
break;
}
}
/*
* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#exitSipApp(org.mobicents.servlet.sip.core.session.MobicentsSipApplicationSession, org.mobicents.servlet.sip.core.session.MobicentsSipSession)
*/
public void exitSipApp(MobicentsSipApplicationSession sipApplicationSession, MobicentsSipSession sipSession) {
switch (concurrencyControlMode) {
case SipSession:
if(sipSession != null) {
sipSession.release();
} else {
if(logger.isDebugEnabled()) {
logger.debug("NOT RELEASING SipSession on exit sipApplicationSession=" + sipApplicationSession +
" sipSession=" + sipSession + " semaphore=null");
}
}
break;
case SipApplicationSession:
boolean wasSessionReleased = false;
SipApplicationSessionCreationThreadLocal sipApplicationSessionCreationThreadLocal = sipApplicationSessionsAccessedThreadLocal.get();
if(sipApplicationSessionCreationThreadLocal != null) {
for(MobicentsSipApplicationSession sipApplicationSessionAccessed : sipApplicationSessionsAccessedThreadLocal.get().getSipApplicationSessions()) {
sipApplicationSessionAccessed.release();
if(sipApplicationSessionAccessed.equals(sipApplicationSession)) {
wasSessionReleased = true;
}
}
sipApplicationSessionsAccessedThreadLocal.get().getSipApplicationSessions().clear();
sipApplicationSessionsAccessedThreadLocal.set(null);
sipApplicationSessionsAccessedThreadLocal.remove();
}
isManagedThread.set(null);
isManagedThread.remove();
if(!wasSessionReleased) {
if(sipApplicationSession != null) {
sipApplicationSession.release();
} else {
if(logger.isDebugEnabled()) {
logger.debug("NOT RELEASING SipApplicationSession on exit sipApplicationSession=" + sipApplicationSession +
" sipSession=" + sipSession + " semaphore=null");
}
}
}
break;
case None:
break;
}
}
/*
* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#enterSipAppHa(boolean)
*/
public boolean enterSipAppHa(boolean startCacheActivity) {
boolean batchStarted = false;
// FIXME: distributable not supported
// if(getDistributable() && hasDistributableManager) {
// batchStarted = startBatchTransaction();
//// if(bindSessions) {
//// ConvergedSessionReplicationContext.enterSipappAndBindSessions(sipApplicationSession,
//// getSipManager(), startCacheActivity);
//// } else {
// ConvergedSessionReplicationContext.enterSipapp(null, null, startCacheActivity);
//// }
// }
return batchStarted;
}
/*
* (non-Javadoc)
* @see org.mobicents.servlet.sip.startup.SipContext#exitSipAppHa(org.mobicents.servlet.sip.message.SipServletRequestImpl, org.mobicents.servlet.sip.message.SipServletResponseImpl, boolean)
*/
public void exitSipAppHa(MobicentsSipServletRequest request, MobicentsSipServletResponse response, boolean batchStarted) {
// FIXME: distributable not supported
// if (getDistributable() && hasDistributableManager) {
// if(logger.isInfoEnabled()) {
// if(request != null) {
// logger.info("We are now after the servlet invocation for request " + request + ", We replicate no matter what " );
// } else if (response != null) {
// logger.info("We are now after the servlet invocation for request " + response + ", We replicate no matter what " );
// } else {
// logger.info("We are now after the servlet invocation, We replicate no matter what " );
// }
// }
// try {
// ConvergedSessionReplicationContext ctx = ConvergedSessionReplicationContext
// .exitSipapp();
//
// final SnapshotSipManager snapshotSipManager = ctx.getSoleSnapshotSipManager();
// if(logger.isDebugEnabled()) {
// logger.debug("Snapshot Manager " + snapshotSipManager);
// }
// if (snapshotSipManager != null) {
// Set> sipSessions = ctx.getSipSessions();
// for (ClusteredSipSession extends OutgoingDistributableSessionData> clusteredSipSession : sipSessions) {
// snapshotSipManager.snapshot(clusteredSipSession);
// }
// Set> sipApplicationSessions = ctx.getSipApplicationSessions();
// for (ClusteredSipApplicationSession extends OutgoingDistributableSessionData> clusteredSipApplicationSession : sipApplicationSessions) {
// snapshotSipManager.snapshot(clusteredSipApplicationSession);
// }
// }
// } catch (Throwable e) {
// logger.error("A problem occured while replicating", e);
// // no need to rethrow an exception here as this is not recoverable and this could mess up the concurrency release of the semaphore on the session
// } finally {
// endBatchTransaction(batchStarted);
// if(logger.isDebugEnabled()) {
// if(request != null) {
// logger.debug("We are now after the replication finishCacheActivity for request " + request + ", We replicate no matter what " );
// } else if (response != null) {
// logger.debug("We are now after the replication finishCacheActivity for request " + response + ", We replicate no matter what " );
// } else {
// logger.debug("We are now after the replication finishCacheActivity, We replicate no matter what " );
// }
// }
// }
// }
}
// FIXME: distributable not supported
// private boolean startBatchTransaction() {
// DistributedCacheConvergedSipManager distributedConvergedManager = ((ClusteredSipManager) manager)
// .getDistributedCacheConvergedSipManager();
// BatchingManager tm = distributedConvergedManager.getBatchingManager();
// boolean started = false;
// try {
// if (tm != null && tm.isBatchInProgress() == false) {
// tm.startBatch();
// started = true;
// }
// } catch (RuntimeException re) {
// throw re;
// } catch (Exception e) {
// throw new IllegalStateException(
// "Failed to initiate batch replication transaction", e);
// }
//
// return started;
// }
// FIXME: distributable not supported
// private void endBatchTransaction(boolean wasStarted) {
// DistributedCacheConvergedSipManager extends OutgoingDistributableSessionData> distributedConvergedManager = ((ClusteredSipManager) manager)
// .getDistributedCacheConvergedSipManager();
// BatchingManager tm = distributedConvergedManager.getBatchingManager();
// try {
// if (tm != null && tm.isBatchInProgress() == true && wasStarted) {
// tm.endBatch();
// }
// } catch (Exception e) {
// logger.error("Failed to stop batch replication transaction", e);
// // no need to rethrow an exception here as this is not recoverable and this could mess up the concurrency release of the semaphore on the session
// }
// }
public boolean notifySipContextListeners(SipContextEvent event) {
boolean ok = true;
if(logger.isDebugEnabled()) {
logger.debug(childrenMap.size() + " container to notify of " + event.getEventType());
}
if(event.getEventType() == SipContextEventType.SERVLET_INITIALIZED) {
if(!timerService.isStarted()) {
timerService.start();
}
if(!proxyTimerService.isStarted()) {
proxyTimerService.start();
}
if(!sasTimerService.isStarted()) {
sasTimerService.start();
}
}
if(this.available) {
enterSipApp(null, null, false, true);
boolean batchStarted = enterSipAppHa(true);
// https://github.com/Mobicents/sip-servlets/issues/52
List sipServlets = new ArrayList(childrenMap.values());
Collections.sort(sipServlets, new SipServletLoadOnStartupComparator());
try {
for (MobicentsSipServlet container : sipServlets) {
if(logger.isDebugEnabled()) {
logger.debug("container " + container.getName() + ", class : " + container.getClass().getName() + ", load-on-startup : " + container.getLoadOnStartup());
}
if(container instanceof Wrapper) {
Wrapper wrapper = (Wrapper) container;
Servlet sipServlet = null;
try {
sipServlet = wrapper.allocate();
if(sipServlet instanceof SipServlet) {
// Fix for issue 1086 (http://code.google.com/p/mobicents/issues/detail?id=1086) :
// Cannot send a request in SipServletListener.initialize() for servlet-selection applications
boolean servletHandlerWasNull = false;
if(servletHandler == null) {
servletHandler = container.getName();
servletHandlerWasNull = true;
}
final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
try {
final ClassLoader cl = getLoader().getClassLoader();
Thread.currentThread().setContextClassLoader(cl);
// http://code.google.com/p/sipservlets/issues/detail?id=135
bindThreadBindingListener();
switch(event.getEventType()) {
case SERVLET_INITIALIZED : {
SipServletContextEvent sipServletContextEvent =
new SipServletContextEvent(getServletContext(), (SipServlet)sipServlet);
List sipServletListeners = sipListeners.getSipServletsListeners();
if(logger.isDebugEnabled()) {
logger.debug(sipServletListeners.size() + " SipServletListener to notify of servlet initialization");
}
for (SipServletListener sipServletListener : sipServletListeners) {
sipServletListener.servletInitialized(sipServletContextEvent);
}
break;
}
case SIP_CONNECTOR_ADDED : {
// reload the outbound interfaces if they have changed
this.getServletContext().setAttribute(javax.servlet.sip.SipServlet.OUTBOUND_INTERFACES,
sipApplicationDispatcher.getOutboundInterfaces());
// https://code.google.com/p/sipservlets/issues/detail?id=246
this.getServletContext().setAttribute("org.mobicents.servlet.sip.SIP_CONNECTORS",
sipApplicationDispatcher.getSipService().findSipConnectors());
List sipConnectorListeners = sipListeners.getSipConnectorListeners();
if(logger.isDebugEnabled()) {
logger.debug(sipConnectorListeners.size() + " SipConnectorListener to notify of sip connector addition");
}
for (SipConnectorListener sipConnectorListener : sipConnectorListeners) {
sipConnectorListener.sipConnectorAdded((SipConnector)event.getEventObject());
}
break;
}
case SIP_CONNECTOR_REMOVED : {
// reload the outbound interfaces if they have changed
this.getServletContext().setAttribute(javax.servlet.sip.SipServlet.OUTBOUND_INTERFACES,
sipApplicationDispatcher.getOutboundInterfaces());
// https://code.google.com/p/sipservlets/issues/detail?id=246
this.getServletContext().setAttribute("org.mobicents.servlet.sip.SIP_CONNECTORS",
sipApplicationDispatcher.getSipService().findSipConnectors());
List sipConnectorListeners = sipListeners.getSipConnectorListeners();
if(logger.isDebugEnabled()) {
logger.debug(sipConnectorListeners.size() + " SipConnectorListener to notify of sip connector removal");
}
for (SipConnectorListener sipConnectorListener : sipConnectorListeners) {
sipConnectorListener.sipConnectorRemoved((SipConnector)event.getEventObject());
}
break;
}
}
if(servletHandlerWasNull) {
servletHandler = null;
}
} finally {
// http://code.google.com/p/sipservlets/issues/detail?id=135
unbindThreadBindingListener();
Thread.currentThread().setContextClassLoader(oldClassLoader);
}
}
} catch (ServletException e) {
logger.error("Cannot allocate the servlet "+ wrapper.getServletClass() +" for notifying the listener " +
" of the event " + event.getEventType(), e);
ok = false;
} catch (Throwable e) {
logger.error("An error occured when notifying the servlet " + wrapper.getServletClass() +
" of the event " + event.getEventType(), e);
ok = false;
}
try {
if(sipServlet != null) {
wrapper.deallocate(sipServlet);
}
} catch (ServletException e) {
logger.error("Deallocate exception for servlet" + wrapper.getName(), e);
ok = false;
} catch (Throwable e) {
logger.error("Deallocate exception for servlet" + wrapper.getName(), e);
ok = false;
}
}
}
} finally {
exitSipAppHa(null, null, batchStarted);
exitSipApp(null, null);
}
}
return ok;
}
public ConcurrencyControlMode getConcurrencyControlMode() {
return concurrencyControlMode;
}
public void setConcurrencyControlMode(ConcurrencyControlMode mode) {
this.concurrencyControlMode = mode;
if(concurrencyControlMode != null && logger.isDebugEnabled()) {
logger.debug("Concurrency Control set to " + concurrencyControlMode.toString() + " for application " + applicationName);
}
}
public SipRubyController getSipRubyController() {
return rubyController;
}
public void setSipRubyController(SipRubyController sipRubyController) {
this.rubyController = sipRubyController;
}
public SipApplicationSessionTimerService getSipApplicationSessionTimerService() {
return sasTimerService;
}
/**
* @return the hasDistributableManager
*/
public boolean hasDistributableManager() {
return hasDistributableManager;
}
/**
* @return the servletHandler
*/
public String getServletHandler() {
return servletHandler;
}
/**
* @param servletHandler the servletHandler to set
*/
public void setServletHandler(String servletHandler) {
this.servletHandler = servletHandler;
}
public boolean isPackageProtectionEnabled() {
return SecurityUtil.isPackageProtectionEnabled();
}
public ClassLoader getSipContextClassLoader() {
return getLoader().getClassLoader();
}
public boolean authorize(MobicentsSipServletRequest request) {
return sipSecurityUtils.authorize(request);
}
public SipDigestAuthenticator getDigestAuthenticator() {
return sipDigestAuthenticator;
}
public SipInstanceManager getSipInstanceManager() {
return (SipInstanceManager) super.getInstanceManager();
}
@Override
public void setInstanceManager(InstanceManager instanceManager) {
super.setInstanceManager(instanceManager);
}
// http://code.google.com/p/sipservlets/issues/detail?id=135
public void bindThreadBindingListener() {
super.getThreadBindingListener().bind();
}
public void unbindThreadBindingListener() {
super.getThreadBindingListener().unbind();
}
@Override
public void enterSipContext() {
final ClassLoader cl = getSipContextClassLoader();
Thread.currentThread().setContextClassLoader(cl);
// http://code.google.com/p/sipservlets/issues/detail?id=135
bindThreadBindingListener();
}
@Override
public void exitSipContext(ClassLoader oldClassLoader) {
// http://code.google.com/p/sipservlets/issues/detail?id=135
unbindThreadBindingListener();
Thread.currentThread().setContextClassLoader(oldClassLoader);
}
// https://github.com/Mobicents/sip-servlets/issues/52
protected class SipServletLoadOnStartupComparator implements Comparator {
@Override
public int compare(MobicentsSipServlet o1, MobicentsSipServlet o2) {
if(o1 != null && o2 != null) {
if(o1.getLoadOnStartup() > o2.getLoadOnStartup()) {
return 1;
} else if(o1.getLoadOnStartup() == o2.getLoadOnStartup()) {
return 0;
} else {
return -1;
}
}
return 0;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy