//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.servlet;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import javax.servlet.MultipartConfigElement;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.ServletSecurityElement;
import javax.servlet.SingleThreadModel;
import javax.servlet.UnavailableException;

import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.RunAsToken;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;




/* --------------------------------------------------------------------- */
/** Servlet Instance and Context Holder.
 * Holds the name, params and some state of a javax.servlet.Servlet
 * instance. It implements the ServletConfig interface.
 * This class will organise the loading of the servlet when needed or
 * requested.
 *
 *
 */
@ManagedObject("Servlet Holder")
public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope, Comparable<ServletHolder>
{

    /* ---------------------------------------------------------------- */
    private static final Logger LOG = Log.getLogger(ServletHolder.class);
    private int _initOrder = -1;
    private boolean _initOnStartup=false;
    private boolean _initialized = false;
    private Map<String, String> _roleMap;
    private String _forcedPath;
    private String _runAsRole;
    private RunAsToken _runAsToken;
    private IdentityService _identityService;
    private ServletRegistration.Dynamic _registration;
    private JspContainer _jspContainer;

    private transient Servlet _servlet;
    private transient Config _config;
    private transient long _unavailable;
    private transient boolean _enabled = true;
    private transient UnavailableException _unavailableEx;

    public static final String GLASSFISH_SENTINEL_CLASS = "org.glassfish.jsp.api.ResourceInjector";
    public static final String APACHE_SENTINEL_CLASS = "org.apache.tomcat.InstanceManager";
    public static final  String JSP_GENERATED_PACKAGE_NAME = "org.eclipse.jetty.servlet.jspPackagePrefix";
    public static final Map<String,String> NO_MAPPED_ROLES = Collections.emptyMap();
    public static enum JspContainer {GLASSFISH, APACHE, OTHER}; 

    /* ---------------------------------------------------------------- */
    /** Constructor .
     */
    public ServletHolder()
    {
        this(Source.EMBEDDED);
    }

    /* ---------------------------------------------------------------- */
    /** Constructor .
     */
    public ServletHolder(Holder.Source creator)
    {
        super(creator);
    }

    /* ---------------------------------------------------------------- */
    /** Constructor for existing servlet.
     */
    public ServletHolder(Servlet servlet)
    {
        this(Source.EMBEDDED);
        setServlet(servlet);
    }

    /* ---------------------------------------------------------------- */
    /** Constructor for servlet class.
     */
    public ServletHolder(String name, Class<? extends Servlet> servlet)
    {
        this(Source.EMBEDDED);
        setName(name);
        setHeldClass(servlet);
    }

    /* ---------------------------------------------------------------- */
    /** Constructor for servlet class.
     */
    public ServletHolder(String name, Servlet servlet)
    {
        this(Source.EMBEDDED);
        setName(name);
        setServlet(servlet);
    }

    /* ---------------------------------------------------------------- */
    /** Constructor for servlet class.
     */
    public ServletHolder(Class<? extends Servlet> servlet)
    {
        this(Source.EMBEDDED);
        setHeldClass(servlet);
    }

    /* ---------------------------------------------------------------- */
    /**
     * @return The unavailable exception or null if not unavailable
     */
    public UnavailableException getUnavailableException()
    {
        return _unavailableEx;
    }

    /* ------------------------------------------------------------ */
    public synchronized void setServlet(Servlet servlet)
    {
        if (servlet==null || servlet instanceof SingleThreadModel)
            throw new IllegalArgumentException();

        _extInstance=true;
        _servlet=servlet;
        setHeldClass(servlet.getClass());
        if (getName()==null)
            setName(servlet.getClass().getName()+"-"+super.hashCode());
    }

    /* ------------------------------------------------------------ */
    @ManagedAttribute(value="initialization order", readonly=true)
    public int getInitOrder()
    {
        return _initOrder;
    }

    /* ------------------------------------------------------------ */
    /** Set the initialize order.
     * Holders with order<0, are initialized on use. Those with
     * order>=0 are initialized in increasing order when the handler
     * is started.
     */
    public void setInitOrder(int order)
    {
        _initOnStartup=order>=0;
        _initOrder = order;
    }

    /* ------------------------------------------------------------ */
    /** Comparitor by init order.
     */
    @Override
    public int compareTo(ServletHolder sh)
    {
        if (sh==this)
            return 0;
        if (sh._initOrder<_initOrder)
            return 1;
        if (sh._initOrder>_initOrder)
            return -1;

        int c=(_className!=null && sh._className!=null)?_className.compareTo(sh._className):0;
        if (c==0)
            c=_name.compareTo(sh._name);
            return c;
    }

    /* ------------------------------------------------------------ */
    public boolean equals(Object o)
    {
        return o instanceof ServletHolder && compareTo((ServletHolder)o)==0;
    }

    /* ------------------------------------------------------------ */
    public int hashCode()
    {
        return _name==null?System.identityHashCode(this):_name.hashCode();
    }

    /* ------------------------------------------------------------ */
    /** Link a user role.
     * Translate the role name used by a servlet, to the link name
     * used by the container.
     * @param name The role name as used by the servlet
     * @param link The role name as used by the container.
     */
    public synchronized void setUserRoleLink(String name,String link)
    {
        if (_roleMap==null)
            _roleMap=new HashMap<String, String>();
        _roleMap.put(name,link);
    }

    /* ------------------------------------------------------------ */
    /** get a user role link.
     * @param name The name of the role
     * @return The name as translated by the link. If no link exists,
     * the name is returned.
     */
    public String getUserRoleLink(String name)
    {
        if (_roleMap==null)
            return name;
        String link= _roleMap.get(name);
        return (link==null)?name:link;
    }

    /* ------------------------------------------------------------ */
    /**
     * @return Returns the forcedPath.
     */
    @ManagedAttribute(value="forced servlet path", readonly=true)
    public String getForcedPath()
    {
        return _forcedPath;
    }

    /* ------------------------------------------------------------ */
    /**
     * @param forcedPath The forcedPath to set.
     */
    public void setForcedPath(String forcedPath)
    {
        _forcedPath = forcedPath;
    }

    public boolean isEnabled()
    {
        return _enabled;
    }


    public void setEnabled(boolean enabled)
    {
        _enabled = enabled;
    }

    
    /* ------------------------------------------------------------ */
    public void doStart()
        throws Exception
    {
        _unavailable=0;
        if (!_enabled)
            return;
        
        // Handle JSP file forced paths
        if (_forcedPath != null)
        {
            // Look for a precompiled JSP Servlet
            String precompiled=getClassNameForJsp(_forcedPath);
            if (LOG.isDebugEnabled())
                LOG.debug("Checking for precompiled servlet {} for jsp {}", precompiled, _forcedPath);
            ServletHolder jsp=getServletHandler().getServlet(precompiled);
            if (jsp!=null && jsp.getClassName() !=  null)
            {
                if (LOG.isDebugEnabled())
                    LOG.debug("JSP file {} for {} mapped to Servlet {}",_forcedPath, getName(),jsp.getClassName());
                // set the className for this servlet to the precompiled one
                setClassName(jsp.getClassName());
            }
            else
            { 
                if (getClassName() == null)
                {
                    // Look for normal JSP servlet
                    jsp=getServletHandler().getServlet("jsp");
                    if (jsp!=null)
                    {
                        if (LOG.isDebugEnabled())
                            LOG.debug("JSP file {} for {} mapped to Servlet class {}",_forcedPath, getName(),jsp.getClassName());
                        setClassName(jsp.getClassName());
                        //copy jsp init params that don't exist for this servlet
                        for (Map.Entry<String, String> entry:jsp.getInitParameters().entrySet())
                        {
                            if (!_initParams.containsKey(entry.getKey()))
                                setInitParameter(entry.getKey(), entry.getValue());
                        }
                        //jsp specific: set up the jsp-file on the JspServlet. If load-on-startup is >=0 and the jsp container supports
                        //precompilation, the jsp will be compiled when this holder is initialized. If not load on startup, or the
                        //container does not support startup precompilation, it will be compiled at runtime when handling a request for this jsp.
                        //See also adaptForcedPathToJspContainer
                        setInitParameter("jspFile", _forcedPath);
                    }                       
                }
            }
        }
        
        
        //check servlet has a class (ie is not a preliminary registration). If preliminary, fail startup.
        try
        {
            super.doStart();
        }
        catch (UnavailableException ue)
        {
            makeUnavailable(ue);
            if (_servletHandler.isStartWithUnavailable())
            {
                LOG.ignore(ue);
                return;
            }
            else
                throw ue;
        }


        //servlet is not an instance of javax.servlet.Servlet
        try
        {
            checkServletType();
        }
        catch (UnavailableException ue)
        {
            makeUnavailable(ue);
            if (_servletHandler.isStartWithUnavailable())
            {
                LOG.ignore(ue);
                return;
            }
            else
                throw ue;
        }

        //check if we need to forcibly set load-on-startup
        checkInitOnStartup();

        _identityService = _servletHandler.getIdentityService();
        if (_identityService!=null && _runAsRole!=null)
            _runAsToken=_identityService.newRunAsToken(_runAsRole);

        _config=new Config();

        if (_class!=null && javax.servlet.SingleThreadModel.class.isAssignableFrom(_class))
            _servlet = new SingleThreadedWrapper();

    }
    
    
    /* ------------------------------------------------------------ */
    @Override
    public void initialize ()
    throws Exception
    {
        if(!_initialized){
            super.initialize();
            if (_extInstance || _initOnStartup)
            {
                try
                {
                    initServlet();
                }
                catch(Exception e)
                {
                    if (_servletHandler.isStartWithUnavailable())
                        LOG.ignore(e);
                    else
                        throw e;
                }
            }
        }
        _initialized = true;
    }
    
    
    /* ------------------------------------------------------------ */
    public void doStop()
        throws Exception
    {
        Object old_run_as = null;
        if (_servlet!=null)
        {
            try
            {
                if (_identityService!=null)
                    old_run_as=_identityService.setRunAs(_identityService.getSystemUserIdentity(),_runAsToken);

                destroyInstance(_servlet);
            }
            catch (Exception e)
            {
                LOG.warn(e);
            }
            finally
            {
                if (_identityService!=null)
                    _identityService.unsetRunAs(old_run_as);
            }
        }

        if (!_extInstance)
            _servlet=null;

        _config=null;
        _initialized = false;
    }

    /* ------------------------------------------------------------ */
    @Override
    public void destroyInstance (Object o)
    throws Exception
    {
        if (o==null)
            return;
        Servlet servlet =  ((Servlet)o);
        getServletHandler().destroyServlet(servlet);
        servlet.destroy();
    }

    /* ------------------------------------------------------------ */
    /** Get the servlet.
     * @return The servlet
     */
    public synchronized Servlet getServlet()
        throws ServletException
    {
        // Handle previous unavailability
        if (_unavailable!=0)
        {
            if (_unavailable<0 || _unavailable>0 && System.currentTimeMillis()<_unavailable)
                throw _unavailableEx;
            _unavailable=0;
            _unavailableEx=null;
        }

        if (_servlet==null)
            initServlet();
        return _servlet;
    }

    /* ------------------------------------------------------------ */
    /** Get the servlet instance (no initialization done).
     * @return The servlet or null
     */
    public Servlet getServletInstance()
    {
        return _servlet;
    }

    /* ------------------------------------------------------------ */
    /**
     * Check to ensure class of servlet is acceptable.
     * @throws UnavailableException
     */
    public void checkServletType ()
        throws UnavailableException
    {
        if (_class==null || !javax.servlet.Servlet.class.isAssignableFrom(_class))
        {
            throw new UnavailableException("Servlet "+_class+" is not a javax.servlet.Servlet");
        }
    }

    /* ------------------------------------------------------------ */
    /**
     * @return true if the holder is started and is not unavailable
     */
    public boolean isAvailable()
    {
        if (isStarted()&& _unavailable==0)
            return true;
        try
        {
            getServlet();
        }
        catch(Exception e)
        {
            LOG.ignore(e);
        }

        return isStarted()&& _unavailable==0;
    }
    
    /* ------------------------------------------------------------ */
    /**
     * Check if there is a javax.servlet.annotation.ServletSecurity
     * annotation on the servlet class. If there is, then we force
     * it to be loaded on startup, because all of the security 
     * constraints must be calculated as the container starts.
     * 
     */
    private void checkInitOnStartup()
    {
        if (_class==null)
            return;
        
        if ((_class.getAnnotation(javax.servlet.annotation.ServletSecurity.class) != null) && !_initOnStartup)
            setInitOrder(Integer.MAX_VALUE);    
    }

    /* ------------------------------------------------------------ */
    private void makeUnavailable(UnavailableException e)
    {
        if (_unavailableEx==e && _unavailable!=0)
            return;

        _servletHandler.getServletContext().log("unavailable",e);

        _unavailableEx=e;
        _unavailable=-1;
        if (e.isPermanent())
            _unavailable=-1;
        else
        {
            if (_unavailableEx.getUnavailableSeconds()>0)
                _unavailable=System.currentTimeMillis()+1000*_unavailableEx.getUnavailableSeconds();
            else
                _unavailable=System.currentTimeMillis()+5000; // TODO configure
        }
    }

    /* ------------------------------------------------------------ */

    private void makeUnavailable(final Throwable e)
    {
        if (e instanceof UnavailableException)
            makeUnavailable((UnavailableException)e);
        else
        {
            ServletContext ctx = _servletHandler.getServletContext();
            if (ctx==null)
                LOG.info("unavailable",e);
            else
                ctx.log("unavailable",e);
            _unavailableEx=new UnavailableException(String.valueOf(e),-1)
            {
                {
                    initCause(e);
                }
            };
            _unavailable=-1;
        }
    }

    /* ------------------------------------------------------------ */
    private void initServlet()
        throws ServletException
    {
        Object old_run_as = null;
        try
        {
            if (_servlet==null)
                _servlet=newInstance();
            if (_config==null)
                _config=new Config();
            
          

            // Handle run as
            if (_identityService!=null)
            {
                old_run_as=_identityService.setRunAs(_identityService.getSystemUserIdentity(),_runAsToken);
            }

            // Handle configuring servlets that implement org.apache.jasper.servlet.JspServlet
            if (isJspServlet())
            {
                initJspServlet();
                detectJspContainer();
            }

            initMultiPart();

            if (_forcedPath != null && _jspContainer == null)
            {
                detectJspContainer();
            }

            if (LOG.isDebugEnabled())
                LOG.debug("Servlet.init {} for {}",_servlet,getName());
            _servlet.init(_config);
        }
        catch (UnavailableException e)
        {
            makeUnavailable(e);
            _servlet=null;
            _config=null;
            throw e;
        }
        catch (ServletException e)
        {
            makeUnavailable(e.getCause()==null?e:e.getCause());
            _servlet=null;
            _config=null;
            throw e;
        }
        catch (Exception e)
        {
            makeUnavailable(e);
            _servlet=null;
            _config=null;
            throw new ServletException(this.toString(),e);
        }
        finally
        {
            // pop run-as role
            if (_identityService!=null)
                _identityService.unsetRunAs(old_run_as);
        }
    }


    /* ------------------------------------------------------------ */
    /**
     * @throws Exception
     */
    protected void initJspServlet () throws Exception
    {
        ContextHandler ch = ContextHandler.getContextHandler(getServletHandler().getServletContext());
            
        /* Set the webapp's classpath for Jasper */
        ch.setAttribute("org.apache.catalina.jsp_classpath", ch.getClassPath());

        /* Set the system classpath for Jasper */
        setInitParameter("com.sun.appserv.jsp.classpath", Loader.getClassPath(ch.getClassLoader().getParent()));

        /* Set up other classpath attribute */
        if ("?".equals(getInitParameter("classpath")))
        {
            String classpath = ch.getClassPath();
            if (LOG.isDebugEnabled())
                LOG.debug("classpath=" + classpath);
            if (classpath != null)
                setInitParameter("classpath", classpath);
        }
        
        /* ensure scratch dir */
        File scratch = null;
        if (getInitParameter("scratchdir") == null)
        {
            File tmp = (File)getServletHandler().getServletContext().getAttribute(ServletContext.TEMPDIR);
            scratch = new File(tmp, "jsp");
            setInitParameter("scratchdir", scratch.getAbsolutePath());
        }
     
        scratch = new File (getInitParameter("scratchdir"));
        if (!scratch.exists()) scratch.mkdir();
    }

    /* ------------------------------------------------------------ */
    /**
     * Register a ServletRequestListener that will ensure tmp multipart
     * files are deleted when the request goes out of scope.
     * 
     * @throws Exception
     */
    protected void initMultiPart () throws Exception
    {
        //if this servlet can handle multipart requests, ensure tmp files will be
        //cleaned up correctly
        if (((Registration)getRegistration()).getMultipartConfig() != null)
        {
            //Register a listener to delete tmp files that are created as a result of this
            //servlet calling Request.getPart() or Request.getParts()

            ContextHandler ch = ContextHandler.getContextHandler(getServletHandler().getServletContext());
            ch.addEventListener(new Request.MultiPartCleanerListener());
        }
    }

    /* ------------------------------------------------------------ */
    /**
     * @see org.eclipse.jetty.server.UserIdentity.Scope#getContextPath()
     */
    @Override
    public String getContextPath()
    {
        return _config.getServletContext().getContextPath();
    }

    /* ------------------------------------------------------------ */
    /**
     * @see org.eclipse.jetty.server.UserIdentity.Scope#getRoleRefMap()
     */
    @Override
    public Map<String, String> getRoleRefMap()
    {
        return _roleMap;
    }

    /* ------------------------------------------------------------ */
    @ManagedAttribute(value="role to run servlet as", readonly=true)
    public String getRunAsRole()
    {
        return _runAsRole;
    }

    /* ------------------------------------------------------------ */
    public void setRunAsRole(String role)
    {
        _runAsRole = role;
    }
    
    /* ------------------------------------------------------------ */
    /**
     * Prepare to service a request.
     * 
     * @param baseRequest
     * @param request
     * @param response
     * @throws ServletException
     * @throws UnavailableException
     */
    protected void prepare (Request baseRequest, ServletRequest request, ServletResponse response)
    throws ServletException, UnavailableException
    {
        ensureInstance();
        MultipartConfigElement mpce = ((Registration)getRegistration()).getMultipartConfig();
        if (mpce != null)
            baseRequest.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
    }
    
    public synchronized Servlet ensureInstance()
    throws ServletException, UnavailableException
    {
        if (_class==null)
            throw new UnavailableException("Servlet Not Initialized");
        Servlet servlet=_servlet;
        if (!isStarted())
            throw new UnavailableException("Servlet not initialized", -1);
        if (_unavailable!=0 || (!_initOnStartup && servlet==null))
            servlet=getServlet();
        if (servlet==null)
            throw new UnavailableException("Could not instantiate "+_class);    
        
        return servlet;
    }

    /* ------------------------------------------------------------ */
    /** Service a request with this servlet.
     * @param baseRequest
     * @param request
     * @param response
     * @throws ServletException
     * @throws UnavailableException
     * @throws IOException
     */
    public void handle(Request baseRequest,
                       ServletRequest request,
                       ServletResponse response)
        throws ServletException,
               UnavailableException,
               IOException
    {
        if (_class==null)
            throw new UnavailableException("Servlet Not Initialized");

        Servlet servlet = ensureInstance();

        // Service the request
        boolean servlet_error=true;
        Object old_run_as = null;
        boolean suspendable = baseRequest.isAsyncSupported();
        try
        {
            // Handle aliased path
            if (_forcedPath!=null)
                adaptForcedPathToJspContainer(request);

            // Handle run as
            if (_identityService!=null)
                old_run_as=_identityService.setRunAs(baseRequest.getResolvedUserIdentity(),_runAsToken);

            if (!isAsyncSupported())
                baseRequest.setAsyncSupported(false);

            servlet.service(request,response);
            servlet_error=false;
        }
        catch(UnavailableException e)
        {
            makeUnavailable(e);
            throw _unavailableEx;
        }
        finally
        {
            baseRequest.setAsyncSupported(suspendable);

            // pop run-as role
            if (_identityService!=null)
                _identityService.unsetRunAs(old_run_as);

            // Handle error params.
            if (servlet_error)
                request.setAttribute("javax.servlet.error.servlet_name",getName());
        }
    }


    /* ------------------------------------------------------------ */
    private boolean isJspServlet ()
    {
        if (_servlet == null)
            return false;

        Class<?> c = _servlet.getClass();

        boolean result = false;
        while (c != null && !result)
        {
            result = isJspServlet(c.getName());
            c = c.getSuperclass();
        }

        return result;
    }


    /* ------------------------------------------------------------ */
    private boolean isJspServlet (String classname)
    {
        if (classname == null)
            return false;
        return ("org.apache.jasper.servlet.JspServlet".equals(classname));
    }

    /* ------------------------------------------------------------ */
    private void adaptForcedPathToJspContainer (ServletRequest request)
    {
        if (_forcedPath != null && _jspContainer != null && JspContainer.GLASSFISH.equals(_jspContainer))
        {
            //if container is glassfish, set the request attribute org.apache.catalina.jsp_file to
            //ensure the delegate jsp will be compiled

            request.setAttribute("org.apache.catalina.jsp_file",_forcedPath);
        }
    }

    /* ------------------------------------------------------------ */
    private void detectJspContainer ()
    {
        if (_jspContainer == null)
        {
            //check for glassfish
            try
            {
                //if container is glassfish, set the request attribute org.apache.catalina.jsp_file to
                //ensure the delegate jsp will be compiled
                Loader.loadClass(Holder.class, GLASSFISH_SENTINEL_CLASS);
                if (LOG.isDebugEnabled())LOG.debug("Glassfish jasper detected");
                _jspContainer = JspContainer.GLASSFISH;
            }
            catch (ClassNotFoundException e)
            {
                try
                {
                    //check for apache
                    Loader.loadClass(Holder.class, APACHE_SENTINEL_CLASS);
                    if (LOG.isDebugEnabled())LOG.debug("Apache jasper detected");
                    _jspContainer = JspContainer.APACHE;
                }
                catch (ClassNotFoundException x)
                {
                    if (LOG.isDebugEnabled())LOG.debug("Other jasper detected");
                    _jspContainer = JspContainer.OTHER;
                }
            }
        }
    }

    /* ------------------------------------------------------------ */
    private String getNameOfJspClass (String jsp)
    {
        if (jsp == null)
            return "";
        
        int i = jsp.lastIndexOf('/') + 1;
        jsp = jsp.substring(i);
        try
        {
            Class<?> jspUtil = Loader.loadClass(Holder.class, "org.apache.jasper.compiler.JspUtil");
            Method makeJavaIdentifier = jspUtil.getMethod("makeJavaIdentifier", String.class);
            return (String)makeJavaIdentifier.invoke(null, jsp);
        }
        catch (Exception e)
        {
            String tmp = jsp.replace('.','_');
            LOG.warn("Unable to make identifier for jsp "+jsp +" trying "+tmp+" instead");
            if (LOG.isDebugEnabled())
                LOG.warn(e);
            return tmp;
        }
    }
    
    
    /* ------------------------------------------------------------ */
    private String getPackageOfJspClass (String jsp)
    {
        if (jsp == null)
            return "";
        
        int i = jsp.lastIndexOf('/');
        if (i <= 0)
            return "";
        try
        {
            Class<?> jspUtil = Loader.loadClass(Holder.class, "org.apache.jasper.compiler.JspUtil");
            Method makeJavaPackage = jspUtil.getMethod("makeJavaPackage", String.class);
            return (String)makeJavaPackage.invoke(null, jsp.substring(0,i));
        } 
        catch (Exception e)
        {
            String tmp = jsp.substring(1).replace('/','.');
            LOG.warn("Unable to make package for jsp "+jsp +" trying "+tmp+" instead");
            if (LOG.isDebugEnabled())
                LOG.warn(e);
            return tmp;
        }
    }
    
    
    /* ------------------------------------------------------------ */
    private String getJspPackagePrefix ()
    {
        String jspPackageName = (String)getServletHandler().getServletContext().getInitParameter(JSP_GENERATED_PACKAGE_NAME );
        if (jspPackageName == null)
            jspPackageName = "org.apache.jsp";
        
        return jspPackageName;
    }
    
    
    /* ------------------------------------------------------------ */
    private String getClassNameForJsp (String jsp)
    {
        if (jsp == null)
            return null; 
        
        return getJspPackagePrefix() + "." +getPackageOfJspClass(jsp) + "." + getNameOfJspClass(jsp);
    }


    /* ------------------------------------------------------------ */
    /* ------------------------------------------------------------ */
    /* ------------------------------------------------------------ */
    protected class Config extends HolderConfig implements ServletConfig
    {
        /* -------------------------------------------------------- */
        @Override
        public String getServletName()
        {
            return getName();
        }

    }

    /* -------------------------------------------------------- */
    /* -------------------------------------------------------- */
    /* -------------------------------------------------------- */
    public class Registration extends HolderRegistration implements ServletRegistration.Dynamic
    {
        protected MultipartConfigElement _multipartConfig;

        @Override
        public Set<String> addMapping(String... urlPatterns)
        {
            illegalStateIfContextStarted();
            Set<String> clash=null;
            for (String pattern : urlPatterns)
            {
                ServletMapping mapping = _servletHandler.getServletMapping(pattern);
                if (mapping!=null)
                {
                    //if the servlet mapping was from a default descriptor, then allow it to be overridden
                    if (!mapping.isDefault())
                    {
                        if (clash==null)
                            clash=new HashSet<String>();
                        clash.add(pattern);
                    }
                }
            }

            //if there were any clashes amongst the urls, return them
            if (clash!=null)
                return clash;

            //otherwise apply all of them
            ServletMapping mapping = new ServletMapping();
            mapping.setServletName(ServletHolder.this.getName());
            mapping.setPathSpecs(urlPatterns);
            _servletHandler.addServletMapping(mapping);

            return Collections.emptySet();
        }

        @Override
        public Collection<String> getMappings()
        {
            ServletMapping[] mappings =_servletHandler.getServletMappings();
            List<String> patterns=new ArrayList<String>();
            if (mappings!=null)
            {
                for (ServletMapping mapping : mappings)
                {
                    if (!mapping.getServletName().equals(getName()))
                        continue;
                    String[] specs=mapping.getPathSpecs();
                    if (specs!=null && specs.length>0)
                        patterns.addAll(Arrays.asList(specs));
                }
            }
            return patterns;
        }

        @Override
        public String getRunAsRole()
        {
            return _runAsRole;
        }

        @Override
        public void setLoadOnStartup(int loadOnStartup)
        {
            illegalStateIfContextStarted();
            ServletHolder.this.setInitOrder(loadOnStartup);
        }

        public int getInitOrder()
        {
            return ServletHolder.this.getInitOrder();
        }

        @Override
        public void setMultipartConfig(MultipartConfigElement element)
        {
            _multipartConfig = element;
        }

        public MultipartConfigElement getMultipartConfig()
        {
            return _multipartConfig;
        }

        @Override
        public void setRunAsRole(String role)
        {
            _runAsRole = role;
        }

        @Override
        public Set<String> setServletSecurity(ServletSecurityElement securityElement)
        {
            return _servletHandler.setServletSecurity(this, securityElement);
        }
    }

    public ServletRegistration.Dynamic getRegistration()
    {
        if (_registration == null)
            _registration = new Registration();
        return _registration;
    }

    /* -------------------------------------------------------- */
    /* -------------------------------------------------------- */
    /* -------------------------------------------------------- */
    private class SingleThreadedWrapper implements Servlet
    {
        Stack<Servlet> _stack=new Stack<Servlet>();

        @Override
        public void destroy()
        {
            synchronized(this)
            {
                while(_stack.size()>0)
                    try { (_stack.pop()).destroy(); } catch (Exception e) { LOG.warn(e); }
            }
        }

        @Override
        public ServletConfig getServletConfig()
        {
            return _config;
        }

        @Override
        public String getServletInfo()
        {
            return null;
        }

        @Override
        public void init(ServletConfig config) throws ServletException
        {
            synchronized(this)
            {
                if(_stack.size()==0)
                {
                    try
                    {
                        Servlet s = newInstance();
                        s.init(config);
                        _stack.push(s);
                    }
                    catch (ServletException e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        throw new ServletException(e);
                    }
                }
            }
        }

        @Override
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
        {
            Servlet s;
            synchronized(this)
            {
                if(_stack.size()>0)
                    s=(Servlet)_stack.pop();
                else
                {
                    try
                    {
                        s = newInstance();
                        s.init(_config);
                    }
                    catch (ServletException e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        throw new ServletException(e);
                    }
                }
            }

            try
            {
                s.service(req,res);
            }
            finally
            {
                synchronized(this)
                {
                    _stack.push(s);
                }
            }
        }
    }

    /* ------------------------------------------------------------ */
    /**
     * @return the newly created Servlet instance
     * @throws ServletException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    protected Servlet newInstance() throws ServletException, IllegalAccessException, InstantiationException
    {
        try
        {
            ServletContext ctx = getServletHandler().getServletContext();
            if (ctx instanceof ServletContextHandler.Context)
                return ((ServletContextHandler.Context)ctx).createServlet(getHeldClass());
            return getHeldClass().newInstance();
        }
        catch (ServletException se)
        {
            Throwable cause = se.getRootCause();
            if (cause instanceof InstantiationException)
                throw (InstantiationException)cause;
            if (cause instanceof IllegalAccessException)
                throw (IllegalAccessException)cause;
            throw se;
        }
    }
    

    /* ------------------------------------------------------------ */
    @Override
    public String toString()
    {
        return String.format("%s@%x==%s,%d,%b",_name,hashCode(),_className,_initOrder,_servlet!=null);
    }
}
