Package com.ericsson.ssa.container.sim

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

/*
* 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 com.ericsson.ssa.config.SipFactoryFacade;
import com.ericsson.ssa.sip.AuthModule;

import com.ericsson.ssa.sip.SecurityInterceptor;
import com.ericsson.ssa.fm.FmEventSender;
import com.ericsson.ssa.sip.AddressImpl;
import com.ericsson.ssa.sip.DialogFragment;
import com.ericsson.ssa.sip.DialogSet;
import com.ericsson.ssa.sip.RemoteLockException;
import com.ericsson.ssa.sip.SipApplicationSessionImpl;
import com.ericsson.ssa.sip.SipFactoryImpl;
import com.ericsson.ssa.sip.SipServletRequestImpl;
import com.ericsson.ssa.sip.SipSessionImplBase;
import com.ericsson.ssa.sip.SipSessionManager;

import com.ericsson.ssa.sip.dialog.DialogLifeCycle;
import com.ericsson.ssa.sip.transaction.ContainerTransaction;
import org.apache.catalina.Context;
import org.apache.catalina.InstanceListener;
import org.apache.catalina.Wrapper;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardWrapper;
import org.apache.catalina.valves.ValveBase;

import org.jvnet.glassfish.comms.deployment.backend.ServletMapping;
import org.jvnet.glassfish.comms.deployment.backend.SipApplication;

import java.io.IOException;
import java.lang.reflect.Method;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.logging.Level;

// inserted by hockey (automatic)
import org.jvnet.glassfish.comms.util.LogUtil;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.sip.ServletParseException;
import javax.servlet.sip.ar.SipApplicationRouterInfo;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.TooManyHopsException;
import javax.servlet.sip.URI;

public class ServletDispatcher extends ValveBase {

    private static final Logger logger = LogUtil.SIP_LOGGER.getLogger();
    /**
     * The parsed sip.xml object model
     */
    SipApplication sipApplicationModel;
    private SipFactoryFacade m_sipFactory = null;
    private HashMap<String, Wrapper> wrappers = new HashMap<String, Wrapper>(5,
            0.75f);
    private AuthModule authModule = null;
    private SipSessionManager m_SipSessionManager = null;
    private String contextId = null;
    String appName = null;

    /**
     * Constructor.
     */
    public ServletDispatcher(SipSessionManager manager) {
        super();
        m_SipSessionManager = manager;
        appName = m_SipSessionManager.getContext().getAppName();
    }

    /**
     * @return Returns the sipApplicationModel.
     */
    public SipApplication getSipApplicationModel() {
        return sipApplicationModel;
    }

    /**
     * @param sipApplicationModel
     *            The sipApplicationModel to set.
     */
    public void setSipApplicationModel(SipApplication sipApplicationModel) {
        this.sipApplicationModel = sipApplicationModel;
    }

    /**
     * For HTTP the next valve is invoked
     *
     */
    @Override
    public int invoke(org.apache.catalina.Request request,
            org.apache.catalina.Response response)
            throws IOException, ServletException {
        return INVOKE_NEXT;
    }

    /**
     * Creates a Session and atach it to the Request.
     *
     * @param req
     *            Request
     * @param appSess
     *            Application Session
     * @param handlerName
     *            Servlet to handle the request
     * @param info
     *            Application Router info used to initiate the session
     * @throws RemoteLockException
     */
    private void createSession(SipServletRequestImpl req,
            SipApplicationSessionImpl appSess, String handlerName,
            URI subscriberURI) {
        SipSessionImplBase s = (SipSessionImplBase) req.getSessionImpl();

        if (s == null) {
            // check if we are spiraling: look up early dialog
            String id = DialogSet.createKey(req.getCallId(),
                    req.getFromImpl().getParameter(AddressImpl.TAG_PARAM));
            DialogSet existingDs = DialogSet.getEarlyDialog(id);

            if (existingDs != null) {
                // spiraling indeed!
                req.setDialog(existingDs.createAdditionalDialogFragment());
            } else {
                // not spiraling
                // creates a new sip session and dialog structure
                DialogSet ds = new DialogSet(req.getMethod(), req.getCallId(), req.getFromImpl(),
                        req.getBeKey(), SipFactoryImpl.isDialogCreational(req.getMethod()));               
                req.setDialog(ds.getInitialDialogFragment());
                DialogSet.registerEarlyDialog(req);
            }
        }

        // creates a new sip session
        DialogFragment d = req.getDialog();
        s = m_SipSessionManager.createSipSession(d.getDialogSet(), req.getToImpl(),
                appSess, handlerName);
        // Initial request from outside the container.
        // So, swap the local-remote.
        s.swapLocalRemote();
        if (handlerName != null && !handlerName.equals("")) {
            TargettedRequestHandler.linkCorrespondingSession(req, s);
        }
        s.setSubscriberURI(subscriberURI);

        req.setSession(s);

        final DialogLifeCycle dialogLifeCycle = d.getDialogLifeCycle();
        dialogLifeCycle.associateTransaction(req.getTransactionId());
        dialogLifeCycle.initUnitOfWork(appSess);
        dialogLifeCycle.setThreadLocalUnitOfWork();
        if (appSess != null) {
            appSess.setShouldBePersisted();
        }
    }

    private URI getSubscriberURI(SipApplicationRouterInfo info) {
        // JSR 289 chapter 15.4.1
        //
        // TODO what about region?

        String subscriberURIStr = info.getSubscriberURI();

        URI subscriberURI = null;
        if (!("".equals(subscriberURIStr)) && subscriberURIStr != null) {
            try {
                subscriberURI = m_sipFactory.createURI(subscriberURIStr);
            } catch (ServletParseException e) {
                if (logger.isLoggable(Level.WARNING)) {
                    logger.warning(
                   "Invalid subscriber URI specified in router " +
                   "info, using null: " + e);
                }
            }
        }
        return subscriberURI;
    }

    /**
     * This method checks the servlet mapping roles and call the service method
     * of the servlet (wrapper).
     *
     * @param request
     * @param application
     * @throws ServletInvocationException
     * @throws RemoteLockException
     * @throws IOException
     * @throws Exception
     */
    public boolean invoke(SipServletRequestImpl request,
            SipApplicationRouterInfo info) throws TooManyHopsException, ServletInvocationException, IOException {

        boolean matched = false;
        //authentication based on login-config only for M1. 
        if (sipApplicationModel != null) {
            if (authModule == null) {
                authModule = new AuthModule(sipApplicationModel, this.appName, contextId);
            }
        }



        SipApplicationSessionImpl as = null;
        List<String> servlets = findServlets(request);

        // Found servlet(s) in an application which can handle the request
        // (mapping roles),
        // but if empty WE DO NOT need to do anything here. AD will invoke
        // this method with next the application.
        if (!servlets.isEmpty()) {
            URI subscriberURI = getSubscriberURI(info);
            request.setSubscriberURI(subscriberURI);

            as = TargettedRequestHandler.getApplicationSession(request, info);
            if (as == null) {
                as = m_sipFactory.createApplicationSession(request);
            }

            Iterator<String> i = servlets.iterator();

            if (i.hasNext()) {
                String servletToInvoke = i.next();
                matched = true;
                // Setting a current servlet in the AS to be used as

                // DefaultHandler.              
             
               

                as.setCurrentServlet(servletToInvoke);

                createSession(request, as, servletToInvoke, subscriberURI);
                SecurityInterceptor si = SecurityInterceptor.getInstance();

                if (!si.verifyRequest(request, authModule, servletToInvoke)) {
                    return matched;
                }
                request.setRegion(info.getRoutingRegion());               
                // XXX why not set the subscriber URI here as well?
                // is there really any use of setting the subscriberURI for error responses?
                // who will ever look into these, before the reinvocation?
               
                SipServletWrapper wrap = (SipServletWrapper) wrappers.get(servletToInvoke);
                //Object securityContext = authModule.preSetRunAsIdentity(servletToInvoke);
                doPreInvoke(request);
                // wrap.allocate().service(request, null);
                wrap.invokeServlet(request);
                doPostInvoke(request);
//                if(securityContext == null){
//                    authModule.postSetRunAsIdentity(securityContext);
//                }
                // If the invoked Servlet has not sent a response/request
                // Need to put in a 64*T1 guard
                if (!request.hasSentOnThread()) {
                    new ContainerTransaction(request);
                }
            }
        }
        return matched;
    }

    /**
     * The method will check the deployment discriptors of the servlets and
     * initialize the corresponding wrappers.
     */
    public void initialize() {
        Map<String, org.jvnet.glassfish.comms.deployment.backend.Servlet> servlets = sipApplicationModel.getServlets();

        for (Iterator<String> it = servlets.keySet().iterator(); it.hasNext();) {
            String servletName = it.next();
            Wrapper wrapper = initializeWrapper(servletName);
            wrappers.put(servletName, wrapper);
            getContainer().addChild(wrapper);
        }

        // Register Application with Application Dispatcher
        ApplicationDispatcher.getInstance().addServletDispatcher(appName, this);

        // Set Session Key in SipFactory
       
        Method sasKey = sipApplicationModel.getSipApplicationKey();
        if (sasKey != null) {
            if (logger.isLoggable(Level.FINE)) {
                logger.log(Level.FINE,
                        "Found @SipApplicationKey method :" + sasKey.getName());
            }
        } else {
            if (logger.isLoggable(Level.FINE)) {
                logger.log(Level.FINE,
                        "No @SipApplicationKey method found");
            }
        }
       
        m_sipFactory.initKeyMethod(sipApplicationModel.getSipApplicationKey());
    }

    public void unInitialize() {

        // Stop SipServlets
        Iterator<Wrapper> it = wrappers.values().iterator();
        while (it.hasNext()) {
            getContainer().removeChild(it.next());
        }
        wrappers.clear();

        // Unregister this ServletDispatcher from the Application Dispatcher
        // if it has not already been removed.
        // During undeployment, a call to ConvergedContext.setAvailable(false)
        // will have already unregistered this ServletDispatcher.
        // See SailFin Issue 1270       
        if (ApplicationDispatcher.getInstance().getServletDispatcher(appName) != null) {

            ApplicationDispatcher.getInstance().removeServletDispatcher(appName);
        }
    }

    /**
     * Initializes the SipServlet Wrappers with servlet class, loader and parent
     *
     * @param servletName
     * @return
     */
    protected Wrapper initializeWrapper(String servletName) {
        Wrapper wrapper = new SipServletWrapper(m_sipFactory,
                sipApplicationModel.getServlet(servletName));

        StandardContext context = (StandardContext) getContainer();

        String[] instanceListeners = context.findInstanceListeners();

        for (int i = 0; i < instanceListeners.length; i++) {
            try {
                Class clazz = Class.forName(instanceListeners[i]);
                InstanceListener listener = (InstanceListener) clazz.newInstance();
                wrapper.addInstanceListener(listener);
            } catch (Throwable t) {
                logger.log(Level.SEVERE,
                        "Failed creating instance listener for Wrapper", t);
            }
        }

        wrapper.setServletClass(sipApplicationModel.getServlet(servletName).getServletClass());
        wrapper.setParent(container);

        return wrapper;
    }

    /**
     * Find all servlets that trigerring rules matches a particular request, and
     * keeping the order of the servlets in the sip.xml file.
     *
     * @param request
     *            The request
     * @return A <code>List</code> of servlet name to invoke
     */
    protected List<String> findServlets(SipServletRequest request) {
        // We should keep the ordering of the servlets as it is
        // in the sip.xml. Do not trust the ordering of the mapping
        // getServletMapping return a HashMap but getServlet return
        // a LinkedHashMap which support a insertion-ordering. So itertation
        // should be on the servlets, not on the mapping (SSA1.0 chap. 11.1).
        ArrayList<String> matchingServlets = new ArrayList<String>();
        Map<String, org.jvnet.glassfish.comms.deployment.backend.Servlet> servlets = sipApplicationModel.getServlets();
        Map<String, ServletMapping> mappings = sipApplicationModel.getServletMappings();
        Iterator<String> itr = servlets.keySet().iterator();

        while (itr.hasNext()) {
            String servletName = itr.next();
            ServletMapping mapping = mappings.get(servletName);

            if ((mapping != null) &&
                    mapping.getPattern().getTopCondition().evaluate(request)) {
                matchingServlets.add(servletName);

                if (logger.isLoggable(Level.FINE)) {
                    logger.log(Level.FINE, "Matched Servlet " + servletName +
                        " with incoming request");
                }
            }
        }

        return matchingServlets;
    }


    /**
     * Check if a given servlet name included within the same application. This
     * method will be called from the application session or more correct from
     * sip session setHandler() method.
     *
     * @param servletName
     * @return boolean if the servlet name included within the same application.
     */
    public boolean findServlet(String servletName) {
        Map<String, org.jvnet.glassfish.comms.deployment.backend.Servlet> servlets = sipApplicationModel.getServlets();

        return servlets.containsKey(servletName);
    }

    /**
     * Loads all the <code>SipServlet</code>s that have a <i>load-on-startup</i>
     * attribute greater or equal to 0. There is no guarantee on the load order
     * of servlets with equal <i>load-on-startup</i> values.
     */
    public void loadServletsMarkedOnStartup() throws ServletException {
        TreeSet<org.jvnet.glassfish.comms.deployment.backend.Servlet> set = new TreeSet<org.jvnet.glassfish.comms.deployment.backend.Servlet>(new ServletStartupOrderComparator());
        set.addAll(sipApplicationModel.getServlets().values());

        for (Iterator it = set.iterator(); it.hasNext();) {
            org.jvnet.glassfish.comms.deployment.backend.Servlet servlet =
                    (org.jvnet.glassfish.comms.deployment.backend.Servlet) it.next();

            if (servlet.getLoadOnStartup() >= 0) {
                Wrapper wrapper = getWrapper(servlet.getServletName());

                try {
                    wrapper.allocate();
                } catch (ServletException e) {
                    // NOTE: load errors (including a servlet that throws
                    // UnavailableException from the init() method) are NOT
                    // fatal to application startup
                    logger.log(Level.WARNING,
                            String.format(
                            "Servlet '%1$s' threw an exception during initialization.",
                            wrapper.getName()), StandardWrapper.getRootCause(e));

                    // Generate a servlet initialization failure notification.
                    Context context = (Context) container;
                    FmEventSender.servletInitializationFailed(context.getName(),
                            wrapper.getName(), e.getMessage());
                    throw e;
                }
            }
        }
    }

    /**
     * The method map a wrapper for a servlet.
     *
     * @param servlet
     *            Name The name of the servlet.
     * @return A <code>Wrapper</code> associated with the servlet name.
     */
    protected Wrapper getWrapper(String servletName) {
        Wrapper wrapper = (Wrapper) wrappers.get(servletName);

        if (wrapper == null) {
            wrapper = initializeWrapper(servletName);
            wrappers.put(servletName, wrapper);
        }

        return wrapper;
    }

    /**
     * Add a wrapper to the map.
     *
     * @param ServletName
     * @param wrapper
     */
    public void addWrapper(String servletName, Wrapper wrapper) {
        wrappers.put(servletName, wrapper);
    }

    /**
     * The method allocate a servlet instance.
     *
     * @param handler
     * @return A <code>Servlet</code> associated with handler.
     */
    public javax.servlet.Servlet getHandler(String handler) {
        javax.servlet.Servlet servlet = null;
        Wrapper wrap = (Wrapper) wrappers.get(handler);

        if (wrap != null) {
            try {
                servlet = wrap.allocate();
            } catch (ServletException e) {
                logger.log(Level.SEVERE, "Error allocating Servlet " + handler,
                        e);
            }
        }
        return servlet;
    }

    /**
     * The method return a <code>SipFactoryFacade</code>.
     *
     * @return A <code>SipFacotryFacade</code>
     */
    public SipFactoryFacade getSipFactory() {
        return m_sipFactory;
    }

    public void setContextId(String contextId) {
        this.contextId = contextId;
    }

    public String getContextId() {
        return this.contextId;
    }

    /**
     * The method set a <code>SipFactoryFacade</code>.
     *
     * @param sipFactory
     *            A <code>SipFacotryFacade</code>.
     */
    public void setSipFactory(SipFactoryFacade sipFactory) {
        this.m_sipFactory = sipFactory;
    }

    public AuthModule getAuthModule() {
        if (sipApplicationModel != null) {
            if (authModule == null) {               
                authModule = new AuthModule(sipApplicationModel, appName, contextId);
            }
        }
        return authModule;
    }
    /*
     * public void registerListener(String servletName, String servletClass,
     * Servlet instance) { if (instance instanceof TimerListener) {
     * m_sipFactory.getSipApplicationListeners().setTimerListener((TimerListener)
     * instance); } else if (instance instanceof SipApplicationSessionListener) {
     * m_sipFactory.getSipApplicationListeners().addSipApplicationSessionListener(
     * (SipApplicationSessionListener) instance); } else if (instance instanceof
     * SipSessionListener) {
     * m_sipFactory.getSipApplicationListeners().addSipSessionListener(
     * (SipSessionListener) instance); } else if (instance instanceof
     * SipErrorListener) {
     * m_sipFactory.getSipApplicationListeners().addSipErrorListener((SipErrorListener)
     * instance); } else if (instance instanceof SipSessionAttributeListener) {
     * m_sipFactory.getSipApplicationListeners().addSipSessionAttributeListener(
     * (SipSessionAttributeListener) instance); } }
     */

    public void doPreInvoke(SipServletRequest request) {
        StandardContext context = (StandardContext) getContainer();

        Object[] instances = context.getApplicationEventListeners();

        ServletRequestEvent event = null;

        if ((instances != null) && (instances.length > 0)) {
            event = new ServletRequestEvent(((StandardContext) container).getServletContext(),
                    request);

            // create pre-service event
            for (int i = 0; i < instances.length; i++) {
                if (instances[i] == null) {
                    continue;
                }

                if (!(instances[i] instanceof ServletRequestListener)) {
                    continue;
                }

                ServletRequestListener listener = (ServletRequestListener) instances[i];

                // START SJSAS 6329662
                context.fireContainerEvent("beforeRequestInitialized", listener);

                try {
                    listener.requestInitialized(event);
                } catch (Throwable t) {
                    logger.log(Level.SEVERE,
                            "Failed calling requestInitialized()", t);
                }
            }
        }
    }

    public void doPostInvoke(SipServletRequest request) {
        StandardContext context = (StandardContext) getContainer();

        Object[] instances = context.getApplicationEventListeners();

        ServletRequestEvent event = new ServletRequestEvent(context.getServletContext(),
                request);

        if ((instances != null) && (instances.length > 0)) {
            // create post-service event
            for (int i = 0; i < instances.length; i++) {
                if (instances[i] == null) {
                    continue;
                }

                if (!(instances[i] instanceof ServletRequestListener)) {
                    continue;
                }

                ServletRequestListener listener = (ServletRequestListener) instances[i];
                // START SJSAS 6329662
                context.fireContainerEvent("beforeRequestDestroyed", listener);

                // END SJSAS 6329662
                try {
                    listener.requestDestroyed(event);
                } catch (Throwable t) {
                    logger.log(Level.SEVERE,
                            "Failed calling requestDestroyed()", t);

                // START SJSAS 6329662
                } finally {
                    context.fireContainerEvent("afterRequestDestroyed", listener);

                // END SJSAS 6329662
                }
            }
        }
    }

    public void logActiveCaches() {
        if (m_SipSessionManager != null) {
            m_SipSessionManager.logActiveObjects();
        }
    }
}
TOP

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

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.