Package com.ericsson.ssa.container.sim

Source Code of com.ericsson.ssa.container.sim.ApplicationDispatcher

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.ericsson.ssa.container.sim;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.spi.ServiceRegistry;
import javax.servlet.Servlet;
import javax.servlet.sip.Address;
import javax.servlet.sip.ServletParseException;
import javax.servlet.sip.SipURI;
import javax.servlet.sip.TooManyHopsException;
import javax.servlet.sip.ar.SipApplicationRouter;
import javax.servlet.sip.ar.SipApplicationRouterInfo;
import javax.servlet.sip.ar.SipApplicationRoutingDirective;
import javax.servlet.sip.ar.SipApplicationRoutingRegion;
import javax.servlet.sip.ar.SipRouteModifier;
import javax.servlet.sip.ar.SipTargetedRequestInfo;
import javax.servlet.sip.ar.SipTargetedRequestType;
import javax.servlet.sip.ar.spi.SipApplicationRouterProvider;

import org.apache.catalina.ContainerEvent;
import org.apache.catalina.ContainerListener;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.jvnet.glassfish.comms.util.LogUtil;

import com.ericsson.ssa.container.reporter.ReporterResolver;
import com.ericsson.ssa.container.reporter.Reporter;
import com.ericsson.ssa.container.reporter.ReporterSet;
import com.ericsson.ssa.sip.AddressImpl;
import com.ericsson.ssa.sip.DialogManager;
import com.ericsson.ssa.sip.Dispatcher;
import com.ericsson.ssa.sip.Header;
import com.ericsson.ssa.sip.Layer;
import com.ericsson.ssa.sip.LayerHelper;
import com.ericsson.ssa.sip.RemoteLockException;
import com.ericsson.ssa.sip.RemoteLockRuntimeException;
import com.ericsson.ssa.sip.ServiceHandler;
import com.ericsson.ssa.sip.SipApplicationSessionImpl;
import com.ericsson.ssa.sip.SipApplicationSessionUtil;
import com.ericsson.ssa.sip.SipFactoryImpl;
import com.ericsson.ssa.sip.SipServletRequestImpl;
import com.ericsson.ssa.sip.SipServletResponseImpl;
import com.ericsson.ssa.sip.SipSessionBase;
import com.ericsson.ssa.sip.SipSessionManagerRegistry;
import com.ericsson.ssa.sip.SipURIImpl;
import com.ericsson.ssa.sip.URIImpl;
import com.ericsson.ssa.sip.UriUtil;
import com.ericsson.ssa.sip.dns.SipTransports;
import com.ericsson.ssa.sip.dns.TargetTuple;
import com.ericsson.ssa.sip.persistence.IncompleteDialogException;

/**
* The ApplicationDispatcher is the Layer in the sip-stack that is responsible
* for invoking applications. It uses the Application Router to determine which
* application to invoke.
*
* ApplicationDispatcher maintains two references to application routers.
* One is the application router that is present in the system by default,
* typically the AlphabeticalRouter (unless configured otherwise).
*
* The administrator has the possibility of deploying a custom application
* router by using the 'asadmin deploy' command line.
*
* @author Robert Handl, Per Pettersson, Kristoffer Gronowski, Yvo Bogers
*/
public class ApplicationDispatcher implements Layer,
    ContainerListener, LifecycleListener, ServiceHandler {
    public static final String APPLICATION_DISPATCHER = "com.ericsson.ssa.container.sim.ApplicationDispatcher/1.0";
   
    private static final String AR_STATE = "x-ar-state";

    /* Singleton instance */
    private static ApplicationDispatcher m_singletonInstance = new ApplicationDispatcher();
    private static TreeMap<String, ServletDispatcher> m_contextMapping = new TreeMap<String, ServletDispatcher>();
    private static final Logger m_logger = LogUtil.SIP_LOGGER.getLogger();
    private Layer m_nextLayer = null;
   
    private ClassLoader saved = null;

    private Reporter _layerReporterSet;
    private Reporter _servletReporterSet;

    public void setReporters(String reporters) {
        ReporterResolver resolver = ReporterResolver.getInstance();
        ReporterSet repSet = resolver.getReporter(reporters);
        _layerReporterSet = repSet.getFilteredSet(Reporter.InterceptionType.LAYER);
        _servletReporterSet = repSet.getFilteredSet(Reporter.InterceptionType.SERVLET);
    }

    public Reporter getReporter() {
        return _layerReporterSet;
    }

    public Reporter getServletReporters() {
        return _servletReporterSet;
    }
       
    protected ApplicationDispatcher() {
        super();
    }
  
    public synchronized void start() {
       ApplicationRouterSelector.getInstance().start();
    }

    public synchronized void stop() {
       ApplicationRouterSelector.getInstance().stop();
    }

    public void lifecycleEvent(LifecycleEvent event) {
        if (m_logger.isLoggable(Level.FINE)) m_logger.log(Level.FINE, "Got lifecycle event!");
    }

    public void containerEvent(ContainerEvent event) {
        if (m_logger.isLoggable(Level.FINER)) m_logger.log(Level.FINER, "Got Container event!");
    }

    /**
     * The method is a part of the dispatch chain. For the initial request the
     * method will try to call the ServletDispatcher to invoke some servlets,
     * otherwise it will pop up the next dispatcher to invoke.
     *
     * @param request
     *           A <code>SipServletRequestImpl</code>.
     */
    public void dispatch(SipServletRequestImpl request) {
        // Check if request is initial
        if (request.isInitial()) {
            // JSR 289, ask the Application Router which application to invoke.
            invokeServletDispatchers(request);
        } else {
           
            // Subsequent request, should go through the default proxy.
            dispatchViaStatelessProxy(request);
        }
    }

    /*
     *  This method implements section 15.4.1 of JSR289.
     */
    private void invokeServletDispatchers(SipServletRequestImpl request) {
        request.setSentOnThread(false);
        SipApplicationRouter runtimeRouter = ApplicationRouterSelector.getInstance().getRuntimeRouter();
        // this resets the flag that the routing directive was explicitly set
        // e.g., in a B2B case the app explicitly sets the directive after
        // we set it implicitly
        // then if we clone the request after the AD was invoked we no longer
        // want this flag to be set, so implicit setting of the directive becomes
        // possible again.
        request.resetExplicit();

        SipSessionBase session = request.getSessionImpl();
       
        if (session != null){
                session.access(); // modify the access times
        }

        SipApplicationRoutingRegion region = null;
        Serializable newStateInfo = null;
        SipApplicationRouterInfo info = null;
        boolean targetedApp = false;

       
        // If routing directive is NEW, we should treat this as a new request
        // i.e. reset the Application Router state.
        if (SipApplicationRoutingDirective.NEW.equals(
            request.getRoutingDirective())){
            Address initialPoppedRoute = request.getInitialPoppedRoute();
            if (initialPoppedRoute != null && initialPoppedRoute.getParameter(AR_STATE) != null) {
               try {
                       ApplicationRouterSelector.getInstance().setRouterContext();
                       ArInfo restoredArInfo = ArInfo.fromString(initialPoppedRoute.getParameter(AR_STATE));
                       newStateInfo = restoredArInfo.getStateInfo();
                       region = restoredArInfo.getRegion();
                       request.setInternalRoutingDirective(SipApplicationRoutingDirective.CONTINUE, null);
               } finally {
                       ApplicationRouterSelector.getInstance().resetRouterContext();
               }
                if (m_logger.isLoggable(Level.FINEST)) {
                    m_logger.log(Level.FINEST, "routing based on restored AR routing info region {0} and stateinfo {1} ", new Object[] {region, newStateInfo});
                }
            } else {
               
                // try the targeted request first                                                     
                SipTargetedRequestInfo stri = TargettedRequestHandler.get(request);
                //TODO. Complete formatting after review is done.
                if (stri != null) {
                    String appName = stri.getApplicationName();
                    info = runtimeRouter.getNextApplication(
                            request,
                            region,
                            SipApplicationRoutingDirective.CONTINUE,
                            stri,
                            newStateInfo);
                    if (appName.equals(info.getNextApplicationName())) {
                        targetedApp = true;
                    } else {
                        if (m_logger.isLoggable(Level.FINEST)) {
                            m_logger.log(Level.FINEST,
                            "AR selected app {0} expected {1}, continuing non-targeted",
                            new Object[]{info.getNextApplicationName(), appName});
                        }
                        // no match in what the AR returns.
                        // let's skip this appname and continue with the normal selection.
                        // remove the parameter from the request to ensure that the request is no longer
                        // targeted
                        request.getRequestURI().removeParameter(URIImpl.SASID_PARAM);
                    }
                }
 
                // clear the stateInfo
                request.setArInfo(new ArInfo(null,null));
                region = determineRegion(request);
                newStateInfo = null;
                if (m_logger.isLoggable(Level.FINEST)) {
                    m_logger.log(Level.FINEST, "clearing the state info and setting intial region {0}", new Object[] {region});
                }
            }
        } else {
            // CONTINUE or REVERSE
            // TODO: what about reverse, should we also reverse the regions?
            region = request.getArInfo().getRegion();
            newStateInfo = request.getArInfo().getStateInfo();
            if (m_logger.isLoggable(Level.FINEST)) {
                m_logger.log(Level.FINEST, "continueing internal routing: region {0} and stateinfo {1} ", new Object[] {region, newStateInfo});
            }
        }
       
                    

        SipApplicationRoutingDirective rDirective = request.getRoutingDirective();

        boolean appSelectionComplete = true;
        do {           
            // No match, cleanup and take another round in the Application Router
            ApplicationRouterSelector.getInstance().setRouterContext();
            // issue 192, guard for malicious application routers
            try {

                if (!targetedApp) {
                    if (m_logger.isLoggable(Level.FINEST)) {
                        m_logger.log(Level.FINEST, "non-targeted request to AR with region {0} and directive {1} ", new Object[] {region, rDirective});
                    }
                    info = runtimeRouter.getNextApplication(
                            request,
                            region,
                            rDirective,
                            null,
                            newStateInfo);
                } else {
                    targetedApp = false; //only the first one is targeted
                }
            } catch (RuntimeException e) {
                m_logger.log(Level.SEVERE,
                        "Application Router threw RuntimeException: " + e.getMessage(),
                        e);
                sendARFailed(request);
                // give up
                return;
            } finally {
                ApplicationRouterSelector.getInstance().resetRouterContext();
            }

            if (info != null) {
                newStateInfo = info.getStateInfo();
                region = info.getRoutingRegion();
            } else {
                if (m_logger.isLoggable(Level.FINEST)) {
                    m_logger.log(Level.FINEST, "AR did not return any info. no application deployed??");
                }
                break;
            }
            rDirective = SipApplicationRoutingDirective.CONTINUE;
            request.setArInfo(new ArInfo(newStateInfo, region));
            request.setRegion(region);
           
            if (modifyRouteSet(request, info, region)) {
                break;
            }          

            // else treat as NO_ROUTE and look for application name
            String application = info.getNextApplicationName();

            if (application == null) {
//                if (m_logger.isLoggable(Level.FINE)){
//                    m_logger.log(Level.FINE,
//                        "Application Dispatcher: no application and NO_ROUTE");
//                }
                break;
            }

            ServletDispatcher sd = m_contextMapping.get(application);           
            if (sd==null){
                m_logger.log(
                        Level.SEVERE, "Unable to invoke application " + application
                + ", check your AR configuration!");

                sendARFailed(request);
                return;
            }
           
            //used to remember to put back the popped route when the last application in case no more application was actually visited
            boolean wasRoutePopped = false;
           
            try {
                request.activateSentOnThread(); //Activate the function

                if (appSelectionComplete) {
                    if (!request.isFirstInvocation()) {
                        modifyRemoteAddress(request);
                        wasRoutePopped = popTopRoute(request);
                    } else {
                        request.setFirstInvocation(false);
                    }
                }

                // Push the ApplicationDispatcher on to the application stack
                // so we come back into the dispatch() method when the request
                // is proxied, for example.
                request.pushApplicationDispatcher(this);
                appSelectionComplete = sd.invoke(request, info);
               
            } catch (TooManyHopsException tmhe) {
                if (m_logger.isLoggable(Level.FINE)) {
                    m_logger.log(Level.FINE, "Too Many Hops Exception ", tmhe);
                }
                sendResponse(request, SipServletResponseImpl.SC_TOO_MANY_HOPS);               
                return;
            } catch (RemoteLockRuntimeException e) {
                if (m_logger.isLoggable(Level.FINE)) {
                    m_logger.log(Level.FINE, "Dialog was remotely locked ", e);
                }

                SipServletResponseImpl response = request.createTerminatingResponse(SipServletResponseImpl.SC_SERVER_INTERNAL_ERROR);
                response.setHeader(Header.RETRY_AFTER, "5");
                response.popDispatcher().dispatch(response);

                return;
            } catch (IncompleteDialogException e) {
                if (m_logger.isLoggable(Level.FINE)) {
                    m_logger.log(Level.FINE, "Dialog was incomplete", e);
                }

                sendResponse(request, SipServletResponseImpl.SC_CALL_LEG_DONE);               
                return;
            } catch (Exception e) {
                if (m_logger.isLoggable(Level.WARNING)) {
                    m_logger.log(Level.WARNING, "Error invoking service ", e);
                }
                sendARFailed(request);
                return;
            } finally {
                request.clearSentOnThread(); //Important not to leak mem
            }

            if (appSelectionComplete) {
                // The invoked application has either proxied the request, or
                // replied with a response.
                // the proxies request or any new request by a B2B will enter this
                // loop in a new thread
                if (m_logger.isLoggable(Level.FINE)){
                    m_logger.log(Level.FINE,
                        "Application Dispatcher did invoke a servlet in app {0}, stopping this loop", new Object[]{application});
                }
                return;
            }           
               
            //pop the ApplicationDispatcher since the application was not invoked
            request.popDispatcher();

            //also take back the popped header
            if (wasRoutePopped) {
                request.pushRoute(request.getPoppedRoute());
            }
           
        } while (info != null);
       
        //No apps matching, doing stateless SIP proxying. If not the correct behavior
        //then it is up to the user to deploy an app that always returns 404!
        dispatchViaStatelessProxy(request);
    }
   
    private SipApplicationRoutingRegion determineRegion(
            SipServletRequestImpl anRequest) {
        switch (anRequest.getSessionCase()) {
        case ORIGINATING:
            return SipApplicationRoutingRegion.ORIGINATING_REGION;
        case TERMINATING:
        case TERMINATING_UNREGISTERED:
            return SipApplicationRoutingRegion.TERMINATING_REGION;
        default:
            // internal or external
            // we do not know which region.
            // just choose one
            // TODO we could make this configurable
            // OR we could look at other indications like the port or host
            // on which the request is received or the domain used...
            return SipApplicationRoutingRegion.TERMINATING_REGION;
        }
    }

    private void modifyRemoteAddress(SipServletRequestImpl request) {
        TargetTuple remoteHop = null;
        // TODO verify if this is correct
        if (request.getInitialRemote() != null) {
            if (request.getLocal() != null) {
                remoteHop = new TargetTuple(
                        request.getInitialRemote().getProtocol(),
                        request.getLocal().getAddress().getHostAddress(), 0);
            } else {
                // initialremote is set, but local is not?
                // should not happen
            }
        } else {
            // initialRemote not set
            if (request.getLocal() != null) {
                // remote not set and local is
                remoteHop = new TargetTuple(
                        SipTransports.TCP_PROT,
                        request.getLocal().getAddress().getHostAddress(), 0);
            } else {
                // both not set
                // should this happen?
            }
        }
        request.setRemoteHop(remoteHop);
    }

    private boolean popTopRoute(SipServletRequestImpl request) {
        if (request.isLocalRoute()) {
            Address popped = request.popRouteHeader();
            request.setPoppedRoute(popped);
            if (popped != null) {
                return true;
            }
        } else
            //reset the popped route
            request.setPoppedRoute(null);
        }
        return false;
    }
   
    /**
     * modify the routes based on the routerinfo returned by the AR
     * @param request the request that was passed to the AR
     * @param info the router info returned by the AR
     * @return true if the routerinfo indicates that the request must be
     * routed externally.
     */
    private boolean modifyRouteSet(SipServletRequestImpl request,
            SipApplicationRouterInfo info,
            SipApplicationRoutingRegion region) {

        SipRouteModifier mod = info.getRouteModifier();
        String[] routes = info.getRoutes();

        if (mod == null) {
            return false;
        }

        try {
            switch (mod) {
            case ROUTE:
                if (routes.length==0 || routes[0] == null) {
                    // what is the intention.
                    // assume route external without push
                    if (m_logger.isLoggable(Level.FINEST)) {
                        m_logger.log(Level.FINEST, "AR returned empty route. Routing externally");
                    }
                    return true;
                } else if (isInternal(routes[0])) {
                    // internal route indicated. Push this
                    // TODO or setInitialPoppedRoute???
                   
                    Address popRoute = SipFactoryImpl.getInstance().createAddress(routes[0]);
                    request.setPoppedRoute(popRoute);
                    if (m_logger.isLoggable(Level.FINEST)) {
                        m_logger.log(Level.FINEST, "AR returned internal route {0}. Setting popped route. Continuing.", new Object[] {popRoute});
                    }
                    return false;
                } else {
                    // External routes indicated; push in reversed order
                    pushRoutesReversed(request,routes);
                    if (m_logger.isLoggable(Level.FINEST)) {
                        m_logger.log(Level.FINEST, "AR returned external routes {0}. Routing externally", new Object[] {routes});
                    }
                    return true;
                }
            case ROUTE_BACK:
                SipURIImpl routebackUri = (SipURIImpl) DialogManager.getInstance().getVipSipUri();
                routebackUri.setLrParam(true);
                Address routeBackAddress = SipFactoryImpl.getInstance().createAddress(routebackUri);
                routeBackAddress.setParameter(AR_STATE, new ArInfo(info.getStateInfo(), region).toString());
                String hashKey = request.getBeKeyFromSession();
                URIImpl uriImpl = (URIImpl) routeBackAddress.getURI();
                if(uriImpl != null){
                    uriImpl.encodeBeKey(hashKey);
                }
                request.pushRoute(routeBackAddress);
                pushRoutesReversed(request, routes);
                if (m_logger.isLoggable(Level.FINEST)) {
                    m_logger.log(Level.FINEST, "AR indicated routeback with external routes {0}. Routing externally", new Object[] {routes});
                }
                return true;
            default: // NO_ROUTE
//                if (m_logger.isLoggable(Level.FINEST)) {
//                    m_logger.log(Level.FINEST, "AR indicated no route {0}. Continuing", new Object[] {mod});
//                }
                return false;
            }
        } catch (ServletParseException e) {
            m_logger.log(Level.SEVERE, e.getMessage(), e);
            return true;
        }
    }
   
    private boolean isInternal(String aRoute) throws ServletParseException {
        // precondition: aRoute != null
         AddressImpl adr = (AddressImpl)SipFactoryImpl.getInstance().createAddress(aRoute);
        return adr.isLocal();
    }

    private void pushRoutesReversed(SipServletRequestImpl aRequest,
            String[] aRoutes) throws ServletParseException {
        for (int i = aRoutes.length-1; i >= 0; i--) {
            if (aRoutes[i] != null) {
                aRequest.pushRoute(
                        SipFactoryImpl.getInstance().createAddress(aRoutes[i]));
            }
        }
    }

    private void sendResponse(SipServletRequestImpl request,
        int code) {
        SipServletResponseImpl response =
            request.createTerminatingResponse(code);
        response.sendError(); // fix for 1816 -- call sendError() instead of doing direct pop dispatch.
    }
   
    private void sendARFailed(SipServletRequestImpl request) {
        //sendResponse(request, SipServletResponseImpl.SC_SERVER_INTERNAL_ERROR,
        //"Application Router error");
        sendResponse(request, SipServletResponseImpl.SC_SERVER_INTERNAL_ERROR);       
    }
   

    /**
     * The method will pop up and invoke the next <code>Dispatcher</code>.
     *
     * @param response
     *           A <code>SipServletResponseImpl</code>.
     */
    public void dispatch(SipServletResponseImpl response) {
        // The transaction layer populates the dispatchers
        // for the request, so here we pop the dispatchers
        try {
            response.popDispatcher().dispatch(response);
        } catch (Exception ex) {
            m_logger.log(Level.SEVERE, "Unhandled exception ", ex);
        }
    }

    private void dispatchViaStatelessProxy(SipServletRequestImpl request) {
       
        // Internal stateless proxy, decrease Max-Forwards by one.
        int maxForwards = request.getMaxForwards();
        --maxForwards;

        if (maxForwards <= 0) {
            SipServletResponseImpl response = request.createTerminatingResponse(
                SipServletResponseImpl.SC_TOO_MANY_HOPS);

            if (response != null) {
                dispatch(response);
            }

            return;
        }
       
        if (m_logger.isLoggable(Level.FINER)){
            m_logger.log(Level.FINER,
                "ApplicationDispatcher: dispatching " + request.getMethod() +
                " request via internal stateless proxy. The Max-forwards " +
                "header value is decreased by one.");
        }

        request.setMaxForwards(maxForwards);
        SipSessionBase session = request.getSessionImpl();
        if (session != null){
            session.access(); // modify the access times
        }

        Dispatcher dispatcher = request.popDispatcher();
        dispatcher.dispatch(request);
    }

    /**
     * Registers a Servlet Dispatcher associated to a application Name
     *
     * @param applicationName
     *           The application name.
     * @param servletDispatcher
     *           A <code>ServletDispatcher</code>.
     */
    public void addServletDispatcher(String applicationName,
        ServletDispatcher servletDispatcher) {
        m_contextMapping.put(applicationName, servletDispatcher);

        // Notify the application router
        ApplicationRouterSelector.getInstance().addServletDispatcher(applicationName, servletDispatcher);
    }

    /**
     * Deregisters a Servlet Dispatcher for a specified application
     *
     * @param applicationName
     */
    public void removeServletDispatcher(String applicationName) {
        ServletDispatcher sd = m_contextMapping.remove(applicationName);
       
        // Notify the application router
        ApplicationRouterSelector.getInstance().removeServletDispatcher(applicationName);
    }

    // Helper method for serialization
    public ServletDispatcher getServletDispatcher(String applicationName) {
        return m_contextMapping.get(applicationName);
    }

    /**
     * Returns the SipServlet of the application name and SipSession handler
     *
     * @param applicationName
     *           the application name
     * @param handler
     *           the SipSession handler
     * @return SipServlet of the application name and SipSession handler
     */
    public Servlet getHandler(String applicationName, String handler) {
        ServletDispatcher disp = m_contextMapping.get(applicationName);

        if (disp != null) {
            return disp.getHandler(handler);
        }

        return null;
    }

    /**
     * @param request
     */
    public void next(SipServletRequestImpl request) {
        LayerHelper.next(request, this, m_nextLayer);
    }

    /**
     * @param response
     */
    public void next(SipServletResponseImpl response) {
        LayerHelper.next(response, this, m_nextLayer);
    }

    /**
     * @param layer
     */
    public void registerNext(Layer layer) {
        m_nextLayer = layer;
    }

    /**
     * Return an instance of <code>ApplicationDispatcher</code>.
     *
     * @return A <code>ApplicationDispatcher</code>.
     */
    public static ApplicationDispatcher getInstance() {
        return m_singletonInstance;
    }      
  
    /**
     * Specify the default Application Router classname. The Application
     * Dispatcher will use java reflection to instantiate the default
     * application router. The default application router is used for routing
     * SIP traffic. It is possible to override this behaviour by calling
     * setCustomApplicationRouter.
     *
     * This method will not initialize the router yet. This will happen when
     * the start() method is called.
     *
     * @param className
     */
    public void setApplicationRouterClass(String className) {
        ApplicationRouterSelector.getInstance().setApplicationRouterClass(className);
    }

    /**
     * Push a service dispatcher on top of the application stack.
     *
     * @param request
     *           On which the service dispatcher will be pushed.
     */
//    public void pushServiceDispatcher(SipServletRequestImpl request) {
//        request.pushApplicationDispatcher(m_serviceDispatcher);
//    }

    /**
     * Return descriptive information about this Valve implementation.
     */
    public String getInfo() {
        return (APPLICATION_DISPATCHER);
    }
  
    public void logActiveCaches() {
        for (ServletDispatcher sd : m_contextMapping.values()) {
            sd.logActiveCaches();
        }
    }
   

}
TOP

Related Classes of com.ericsson.ssa.container.sim.ApplicationDispatcher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.