//
//  ========================================================================
//  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.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
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.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.QuietServletException;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.ServletRequestHttpWrapper;
import org.eclipse.jetty.server.ServletResponseHttpWrapper;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ScopedHandler;
import org.eclipse.jetty.servlet.BaseHolder.Source;
import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

/** 
 * Servlet HttpHandler.
 * <p>
 * This handler maps requests to servlets that implement the
 * javax.servlet.http.HttpServlet API.
 * <P>
 * This handler does not implement the full J2EE features and is intended to
 * be used directly when a full web application is not required.  If a Web application is required,
 * then this handler should be used as part of a <code>org.eclipse.jetty.webapp.WebAppContext</code>.
 * <p>
 * Unless run as part of a {@link ServletContextHandler} or derivative, the {@link #initialize()}
 * method must be called manually after start().
 */
@ManagedObject("Servlet Handler")
public class ServletHandler extends ScopedHandler
{
    private static final Logger LOG = Log.getLogger(ServletHandler.class);

    /* ------------------------------------------------------------ */
    public static final String __DEFAULT_SERVLET="default";

    /* ------------------------------------------------------------ */
    private ServletContextHandler _contextHandler;
    private ServletContext _servletContext;
    private FilterHolder[] _filters=new FilterHolder[0];
    private FilterMapping[] _filterMappings;
    private int _matchBeforeIndex = -1; //index of last programmatic FilterMapping with isMatchAfter=false
    private int _matchAfterIndex = -1;  //index of 1st programmatic FilterMapping with isMatchAfter=true
    private boolean _filterChainsCached=true;
    private int _maxFilterChainsCacheSize=512;
    private boolean _startWithUnavailable=false;
    private boolean _ensureDefaultServlet=true;
    private IdentityService _identityService;
    private boolean _allowDuplicateMappings=false;

    private ServletHolder[] _servlets=new ServletHolder[0];
    private ServletMapping[] _servletMappings;
    private final Map<String,FilterHolder> _filterNameMap= new HashMap<>();
    private List<FilterMapping> _filterPathMappings;
    private MultiMap<FilterMapping> _filterNameMappings;

    private final Map<String,ServletHolder> _servletNameMap=new HashMap<>();
    private PathMap<ServletHolder> _servletPathMap;
    
    private ListenerHolder[] _listeners=new ListenerHolder[0];

    @SuppressWarnings("unchecked")
    protected final ConcurrentMap<String, FilterChain> _chainCache[] = new ConcurrentMap[FilterMapping.ALL];

    @SuppressWarnings("unchecked")
    protected final Queue<String>[] _chainLRU = new Queue[FilterMapping.ALL];



    /* ------------------------------------------------------------ */
    /** Constructor.
     */
    public ServletHandler()
    {
    }

    /* ----------------------------------------------------------------- */
    @Override
    protected synchronized void doStart()
        throws Exception
    {
        ContextHandler.Context context=ContextHandler.getCurrentContext();
        _servletContext=context==null?new ContextHandler.StaticContext():context;
        _contextHandler=(ServletContextHandler)(context==null?null:context.getContextHandler());

        if (_contextHandler!=null)
        {
            SecurityHandler security_handler = _contextHandler.getChildHandlerByClass(SecurityHandler.class);
            if (security_handler!=null)
                _identityService=security_handler.getIdentityService();
        }

        updateNameMappings();
        updateMappings();        
        
        if (getServletMapping("/")==null && _ensureDefaultServlet)
        {
            if (LOG.isDebugEnabled())
                LOG.debug("Adding Default404Servlet to {}",this);
            addServletWithMapping(Default404Servlet.class,"/");
            updateMappings();  
            getServletMapping("/").setDefault(true);
        }

        if(_filterChainsCached)
        {
            _chainCache[FilterMapping.REQUEST]=new ConcurrentHashMap<String,FilterChain>();
            _chainCache[FilterMapping.FORWARD]=new ConcurrentHashMap<String,FilterChain>();
            _chainCache[FilterMapping.INCLUDE]=new ConcurrentHashMap<String,FilterChain>();
            _chainCache[FilterMapping.ERROR]=new ConcurrentHashMap<String,FilterChain>();
            _chainCache[FilterMapping.ASYNC]=new ConcurrentHashMap<String,FilterChain>();

            _chainLRU[FilterMapping.REQUEST]=new ConcurrentLinkedQueue<String>();
            _chainLRU[FilterMapping.FORWARD]=new ConcurrentLinkedQueue<String>();
            _chainLRU[FilterMapping.INCLUDE]=new ConcurrentLinkedQueue<String>();
            _chainLRU[FilterMapping.ERROR]=new ConcurrentLinkedQueue<String>();
            _chainLRU[FilterMapping.ASYNC]=new ConcurrentLinkedQueue<String>();
        }

        if (_contextHandler==null)
            initialize();
        
        super.doStart();
    }
    
    
    /* ------------------------------------------------------------ */
    /**
     * @return true if ServletHandler always has a default servlet, using {@link Default404Servlet} if no other
     * default servlet is configured.
     */
    public boolean isEnsureDefaultServlet()
    {
        return _ensureDefaultServlet;
    }

    /* ------------------------------------------------------------ */
    /**
     * @param ensureDefaultServlet true if ServletHandler always has a default servlet, using {@link Default404Servlet} if no other
     * default servlet is configured.
     */
    public void setEnsureDefaultServlet(boolean ensureDefaultServlet)
    {
        _ensureDefaultServlet=ensureDefaultServlet;
    }

    /* ----------------------------------------------------------------- */
    @Override
    protected void start(LifeCycle l) throws Exception
    {
        //Don't start the whole object tree (ie all the servlet and filter Holders) when
        //this handler starts. They have a slightly special lifecycle, and should only be
        //started AFTER the handlers have all started (and the ContextHandler has called
        //the context listeners).
        if (!(l instanceof Holder))
            super.start(l);
    }

    /* ----------------------------------------------------------------- */
    @Override
    protected synchronized void doStop()
        throws Exception
    {
        super.doStop();

        // Stop filters
        List<FilterHolder> filterHolders = new ArrayList<FilterHolder>();
        List<FilterMapping> filterMappings = ArrayUtil.asMutableList(_filterMappings);      
        if (_filters!=null)
        {
            for (int i=_filters.length; i-->0;)
            {
                try 
                {
                    _filters[i].stop(); 
                }
                catch(Exception e)
                {
                    LOG.warn(Log.EXCEPTION,e);
                }
                if (_filters[i].getSource() != Source.EMBEDDED)
                {
                    //remove all of the mappings that were for non-embedded filters
                    _filterNameMap.remove(_filters[i].getName());
                    //remove any mappings associated with this filter
                    ListIterator<FilterMapping> fmitor = filterMappings.listIterator();
                    while (fmitor.hasNext())
                    {
                        FilterMapping fm = fmitor.next();
                        if (fm.getFilterName().equals(_filters[i].getName()))
                            fmitor.remove();
                    }
                }
                else
                    filterHolders.add(_filters[i]); //only retain embedded
            }
        }
        
        //Retain only filters and mappings that were added using jetty api (ie Source.EMBEDDED)
        FilterHolder[] fhs = (FilterHolder[]) LazyList.toArray(filterHolders, FilterHolder.class);
        updateBeans(_filters, fhs);
        _filters = fhs;
        FilterMapping[] fms = (FilterMapping[]) LazyList.toArray(filterMappings, FilterMapping.class);
        updateBeans(_filterMappings, fms);
        _filterMappings = fms;
        
        _matchAfterIndex = (_filterMappings == null || _filterMappings.length == 0 ? -1 : _filterMappings.length-1);
        _matchBeforeIndex = -1;

        // Stop servlets
        List<ServletHolder> servletHolders = new ArrayList<ServletHolder>();  //will be remaining servlets
        List<ServletMapping> servletMappings = ArrayUtil.asMutableList(_servletMappings); //will be remaining mappings
        if (_servlets!=null)
        {
            for (int i=_servlets.length; i-->0;)
            {
                try 
                { 
                    _servlets[i].stop(); 
                }
                catch(Exception e)
                {
                    LOG.warn(Log.EXCEPTION,e);
                }
                
                if (_servlets[i].getSource() != Source.EMBEDDED)
                {
                    //remove from servlet name map
                    _servletNameMap.remove(_servlets[i].getName());
                    //remove any mappings associated with this servlet
                    ListIterator<ServletMapping> smitor = servletMappings.listIterator();
                    while (smitor.hasNext())
                    {
                        ServletMapping sm = smitor.next();
                        if (sm.getServletName().equals(_servlets[i].getName()))
                            smitor.remove();
                    }
                }
                else
                    servletHolders.add(_servlets[i]); //only retain embedded 
            }
        }

        //Retain only Servlets and mappings added via jetty apis (ie Source.EMBEDDED)
        ServletHolder[] shs = (ServletHolder[]) LazyList.toArray(servletHolders, ServletHolder.class);
        updateBeans(_servlets, shs);
        _servlets = shs;
        ServletMapping[] sms = (ServletMapping[])LazyList.toArray(servletMappings, ServletMapping.class); 
        updateBeans(_servletMappings, sms);
        _servletMappings = sms;

        //Retain only Listeners added via jetty apis (is Source.EMBEDDED)
        List<ListenerHolder> listenerHolders = new ArrayList<ListenerHolder>();
        if (_listeners != null)
        { 
            for (int i=_listeners.length; i-->0;)
            {
                try
                {
                    _listeners[i].stop();
                } 
                catch(Exception e)
                {
                    LOG.warn(Log.EXCEPTION,e);
                }
                if (_listeners[i].getSource() == Source.EMBEDDED)
                    listenerHolders.add(_listeners[i]);
            }
        }
        ListenerHolder[] listeners = (ListenerHolder[])LazyList.toArray(listenerHolders, ListenerHolder.class);
        updateBeans(_listeners, listeners);
        _listeners = listeners;

        //will be regenerated on next start
        _filterPathMappings=null;
        _filterNameMappings=null;
        _servletPathMap=null;
    }

    /* ------------------------------------------------------------ */
    protected IdentityService getIdentityService()
    {
        return _identityService;
    }

    /* ------------------------------------------------------------ */
    /**
     * @return Returns the contextLog.
     */
    public Object getContextLog()
    {
        return null;
    }

    /* ------------------------------------------------------------ */
    /**
     * @return Returns the filterMappings.
     */
    @ManagedAttribute(value="filters", readonly=true)
    public FilterMapping[] getFilterMappings()
    {
        return _filterMappings;
    }

    /* ------------------------------------------------------------ */
    /** Get Filters.
     * @return Array of defined servlets
     */
    @ManagedAttribute(value="filters", readonly=true)
    public FilterHolder[] getFilters()
    {
        return _filters;
    }

    /* ------------------------------------------------------------ */
    /** ServletHolder matching path.
     * @param pathInContext Path within _context.
     * @return PathMap Entries pathspec to ServletHolder
     */
    public PathMap.MappedEntry<ServletHolder> getHolderEntry(String pathInContext)
    {
        if (_servletPathMap==null)
            return null;
        return _servletPathMap.getMatch(pathInContext);
    }

    /* ------------------------------------------------------------ */
    public ServletContext getServletContext()
    {
        return _servletContext;
    }

    /* ------------------------------------------------------------ */
    /**
     * @return Returns the servletMappings.
     */
    @ManagedAttribute(value="mappings of servlets", readonly=true)
    public ServletMapping[] getServletMappings()
    {
        return _servletMappings;
    }
    
    /* ------------------------------------------------------------ */
    /**
     * Get the ServletMapping matching the path
     * 
     * @param pathSpec the path spec
     * @return the servlet mapping for the path spec (or null if not found)
     */
    public ServletMapping getServletMapping(String pathSpec)
    {
        if (pathSpec == null || _servletMappings == null)
            return null;
        
        ServletMapping mapping = null;
        for (int i=0; i<_servletMappings.length && mapping == null; i++)
        {
            ServletMapping m = _servletMappings[i];
            if (m.getPathSpecs() != null)
            {
                for (String p:m.getPathSpecs())
                {
                    if (pathSpec.equals(p))
                    {
                        mapping = m;
                        break;
                    }
                }
            }
        }
        return mapping;
    }
    
    /* ------------------------------------------------------------ */
    /** Get Servlets.
     * @return Array of defined servlets
     */
    @ManagedAttribute(value="servlets", readonly=true)
    public ServletHolder[] getServlets()
    {
        return _servlets;
    }

    /* ------------------------------------------------------------ */
    public ServletHolder getServlet(String name)
    {
        return _servletNameMap.get(name);
    }

    /* ------------------------------------------------------------ */
    @Override
    public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        // Get the base requests
        final String old_servlet_path=baseRequest.getServletPath();
        final String old_path_info=baseRequest.getPathInfo();

        DispatcherType type = baseRequest.getDispatcherType();

        ServletHolder servlet_holder=null;
        UserIdentity.Scope old_scope=null;

        // find the servlet
        if (target.startsWith("/"))
        {
            // Look for the servlet by path
            PathMap.MappedEntry<ServletHolder> entry=getHolderEntry(target);
            if (entry!=null)
            {
                servlet_holder=entry.getValue();

                String servlet_path_spec= entry.getKey();
                String servlet_path=entry.getMapped()!=null?entry.getMapped():PathMap.pathMatch(servlet_path_spec,target);
                String path_info=PathMap.pathInfo(servlet_path_spec,target);

                if (DispatcherType.INCLUDE.equals(type))
                {
                    baseRequest.setAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH,servlet_path);
                    baseRequest.setAttribute(RequestDispatcher.INCLUDE_PATH_INFO, path_info);
                }
                else
                {
                    baseRequest.setServletPath(servlet_path);
                    baseRequest.setPathInfo(path_info);
                }
            }
        }
        else
        {
            // look for a servlet by name!
            servlet_holder= _servletNameMap.get(target);
        }

        if (LOG.isDebugEnabled())
            LOG.debug("servlet {}|{}|{} -> {}",baseRequest.getContextPath(),baseRequest.getServletPath(),baseRequest.getPathInfo(),servlet_holder);

        try
        {
            // Do the filter/handling thang
            old_scope=baseRequest.getUserIdentityScope();
            baseRequest.setUserIdentityScope(servlet_holder);

            // start manual inline of nextScope(target,baseRequest,request,response);
            if (never())
                nextScope(target,baseRequest,request,response);
            else if (_nextScope!=null)
                _nextScope.doScope(target,baseRequest,request, response);
            else if (_outerScope!=null)
                _outerScope.doHandle(target,baseRequest,request, response);
            else
                doHandle(target,baseRequest,request, response);
            // end manual inline (pathentic attempt to reduce stack depth)
        }
        finally
        {
            if (old_scope!=null)
                baseRequest.setUserIdentityScope(old_scope);

            if (!(DispatcherType.INCLUDE.equals(type)))
            {
                baseRequest.setServletPath(old_servlet_path);
                baseRequest.setPathInfo(old_path_info);
            }
        }
    }

    /* ------------------------------------------------------------ */
    /*
     * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
     */
    @Override
    public void doHandle(String target, Request baseRequest,HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException
    {
        DispatcherType type = baseRequest.getDispatcherType();

        ServletHolder servlet_holder=(ServletHolder) baseRequest.getUserIdentityScope();
        FilterChain chain=null;

        // find the servlet
        if (target.startsWith("/"))
        {
            if (servlet_holder!=null && _filterMappings!=null && _filterMappings.length>0)
                chain=getFilterChain(baseRequest, target, servlet_holder);
        }
        else
        {
            if (servlet_holder!=null)
            {
                if (_filterMappings!=null && _filterMappings.length>0)
                {
                    chain=getFilterChain(baseRequest, null,servlet_holder);
                }
            }
        }

        if (LOG.isDebugEnabled())
            LOG.debug("chain={}",chain);

        Throwable th=null;
        try
        {
            if (servlet_holder==null)
                notFound(baseRequest,request, response);
            else
            {
                // unwrap any tunnelling of base Servlet request/responses
                ServletRequest req = request;
                if (req instanceof ServletRequestHttpWrapper)
                    req = ((ServletRequestHttpWrapper)req).getRequest();
                ServletResponse res = response;
                if (res instanceof ServletResponseHttpWrapper)
                    res = ((ServletResponseHttpWrapper)res).getResponse();

                // Do the filter/handling thang
                servlet_holder.prepare(baseRequest, req, res);
                
                if (chain!=null)
                    chain.doFilter(req, res);
                else
                    servlet_holder.handle(baseRequest,req,res);
            }
        }
        catch(EofException e)
        {
            throw e;
        }
        catch(RuntimeIOException e)
        {
            if (e.getCause() instanceof IOException)
            {
                LOG.debug(e);
                throw (IOException)e.getCause();
            }
            throw e;
        }
        catch(Exception e)
        {
            //TODO, can we let all error handling fall through to HttpChannel?
            
            if (baseRequest.isAsyncStarted() || !(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
            {
                if (e instanceof IOException)
                    throw (IOException)e;
                if (e instanceof RuntimeException)
                    throw (RuntimeException)e;
                if (e instanceof ServletException)
                    throw (ServletException)e;
            }

            // unwrap cause
            th=e;
            if (th instanceof ServletException)
            {
                if (th instanceof QuietServletException)
                { 
                    LOG.warn(th.toString());
                    LOG.debug(th);
                }
                else
                    LOG.warn(th);
            }
            else if (th instanceof EofException)
            {
                throw (EofException)th;
            }
            else
            {
                LOG.warn(request.getRequestURI(),th);
                if (LOG.isDebugEnabled())
                    LOG.debug(request.toString());
            }

            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,th.getClass());
            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,th);
            if (!response.isCommitted())
            {
                baseRequest.getResponse().getHttpFields().put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
                if (th instanceof UnavailableException)
                {
                    UnavailableException ue = (UnavailableException)th;
                    if (ue.isPermanent())
                        response.sendError(HttpServletResponse.SC_NOT_FOUND);
                    else
                        response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
                }
                else
                    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
            else
            {
                if (th instanceof IOException)
                    throw (IOException)th;
                if (th instanceof RuntimeException)
                    throw (RuntimeException)th;
                if (th instanceof ServletException)
                    throw (ServletException)th;
                throw new IllegalStateException("response already committed",th);
            }
        }
        catch(Error e)
        {
            if ("ContinuationThrowable".equals(e.getClass().getSimpleName()))
                throw e;
            th=e;
            if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
                throw e;
            LOG.warn("Error for "+request.getRequestURI(),e);
            if(LOG.isDebugEnabled())
                LOG.debug(request.toString());

            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,e.getClass());
            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,e);
            if (!response.isCommitted())
            {
                baseRequest.getResponse().getHttpFields().put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
            else
                LOG.debug("Response already committed for handling ",e);
        }
        finally
        {
            // Complete async errored requests 
            if (th!=null && request.isAsyncStarted())
                baseRequest.getHttpChannelState().errorComplete();
            
            if (servlet_holder!=null)
                baseRequest.setHandled(true);
        }
    }

    /* ------------------------------------------------------------ */
    protected FilterChain getFilterChain(Request baseRequest, String pathInContext, ServletHolder servletHolder)
    {
        String key=pathInContext==null?servletHolder.getName():pathInContext;
        int dispatch = FilterMapping.dispatch(baseRequest.getDispatcherType());

        if (_filterChainsCached && _chainCache!=null)
        {
            FilterChain chain = (FilterChain)_chainCache[dispatch].get(key);
            if (chain!=null)
                return chain;
        }

        // Build list of filters (list of FilterHolder objects)
        List<FilterHolder> filters = new ArrayList<>();

        // Path filters
        if (pathInContext!=null && _filterPathMappings!=null)
        {
            for (FilterMapping filterPathMapping : _filterPathMappings)
            {
                if (filterPathMapping.appliesTo(pathInContext, dispatch))
                    filters.add(filterPathMapping.getFilterHolder());
            }
        }

        // Servlet name filters
        if (servletHolder != null && _filterNameMappings!=null && _filterNameMappings.size() > 0)
        {
            // Servlet name filters
            if (_filterNameMappings.size() > 0)
            {
                Object o= _filterNameMappings.get(servletHolder.getName());

                for (int i=0; i<LazyList.size(o);i++)
                {
                    FilterMapping mapping = (FilterMapping)LazyList.get(o,i);
                    if (mapping.appliesTo(dispatch))
                        filters.add(mapping.getFilterHolder());
                }

                o= _filterNameMappings.get("*");
                for (int i=0; i<LazyList.size(o);i++)
                {
                    FilterMapping mapping = (FilterMapping)LazyList.get(o,i);
                    if (mapping.appliesTo(dispatch))
                        filters.add(mapping.getFilterHolder());
                }
            }
        }

        if (filters.isEmpty())
            return null;


        FilterChain chain = null;
        if (_filterChainsCached)
        {
            if (filters.size() > 0)
                chain= new CachedChain(filters, servletHolder);

            final Map<String,FilterChain> cache=_chainCache[dispatch];
            final Queue<String> lru=_chainLRU[dispatch];

                // Do we have too many cached chains?
                while (_maxFilterChainsCacheSize>0 && cache.size()>=_maxFilterChainsCacheSize)
                {
                    // The LRU list is not atomic with the cache map, so be prepared to invalidate if
                    // a key is not found to delete.
                    // Delete by LRU (where U==created)
                    String k=lru.poll();
                    if (k==null)
                    {
                        cache.clear();
                        break;
                    }
                    cache.remove(k);
                }

                cache.put(key,chain);
                lru.add(key);
        }
        else if (filters.size() > 0)
            chain = new Chain(baseRequest,filters, servletHolder);

        return chain;
    }

    /* ------------------------------------------------------------ */
    protected void invalidateChainsCache()
    {
        if (_chainLRU[FilterMapping.REQUEST]!=null)
        {
            _chainLRU[FilterMapping.REQUEST].clear();
            _chainLRU[FilterMapping.FORWARD].clear();
            _chainLRU[FilterMapping.INCLUDE].clear();
            _chainLRU[FilterMapping.ERROR].clear();
            _chainLRU[FilterMapping.ASYNC].clear();

            _chainCache[FilterMapping.REQUEST].clear();
            _chainCache[FilterMapping.FORWARD].clear();
            _chainCache[FilterMapping.INCLUDE].clear();
            _chainCache[FilterMapping.ERROR].clear();
            _chainCache[FilterMapping.ASYNC].clear();
        }
    }

    /* ------------------------------------------------------------ */
    /**
     * @return true if the handler is started and there are no unavailable servlets
     */
    public boolean isAvailable()
    {
        if (!isStarted())
            return false;
        ServletHolder[] holders = getServlets();
        for (ServletHolder holder : holders)
        {
            if (holder != null && !holder.isAvailable())
                return false;
        }
        return true;
    }

    /* ------------------------------------------------------------ */
    /**
     * @param start True if this handler will start with unavailable servlets
     */
    public void setStartWithUnavailable(boolean start)
    {
        _startWithUnavailable=start;
    }

    /**
     * @return the allowDuplicateMappings
     */
    public boolean isAllowDuplicateMappings()
    {
        return _allowDuplicateMappings;
    }

    /**
     * @param allowDuplicateMappings the allowDuplicateMappings to set
     */
    public void setAllowDuplicateMappings(boolean allowDuplicateMappings)
    {
        _allowDuplicateMappings = allowDuplicateMappings;
    }

    /* ------------------------------------------------------------ */
    /**
     * @return True if this handler will start with unavailable servlets
     */
    public boolean isStartWithUnavailable()
    {
        return _startWithUnavailable;
    }



    /* ------------------------------------------------------------ */
    /** Initialize filters and load-on-startup servlets.
     * @throws Exception if unable to initialize
     */
    public void initialize()
        throws Exception
    {
        MultiException mx = new MultiException();

        //start filter holders now
        if (_filters != null)
        {
            for (FilterHolder f: _filters)
            {
                try
                {
                    f.start();
                    f.initialize();
                }
                catch (Exception e)
                {
                    mx.add(e);
                }
            }
        }
        
        // Sort and Initialize servlets
        if (_servlets!=null)
        {
            ServletHolder[] servlets = _servlets.clone();
            Arrays.sort(servlets);
            for (ServletHolder servlet : servlets)
            {
                try
                {
                    servlet.start();
                    servlet.initialize();
                }
                catch (Throwable e)
                {
                    LOG.debug(Log.EXCEPTION, e);
                    mx.add(e);
                }
            }
        }

        //any other beans
        for (Holder<?> h: getBeans(Holder.class))
        {
            try
            {
                if (!h.isStarted())
                {
                    h.start();
                    h.initialize();
                }
            }
            catch (Exception e)
            {
                mx.add(e);
            }
        }
        
        mx.ifExceptionThrow();
    }

    /* ------------------------------------------------------------ */
    /**
     * @return Returns the filterChainsCached.
     */
    public boolean isFilterChainsCached()
    {
        return _filterChainsCached;
    }
    
    /* ------------------------------------------------------------ */
    /** Add a holder for a listener
     * @param listener the listener for the holder
     */
    public void addListener (ListenerHolder listener)
    {
        if (listener != null)
            setListeners(ArrayUtil.addToArray(getListeners(), listener, ListenerHolder.class));
    }
    
    
    /* ------------------------------------------------------------ */
    public ListenerHolder[] getListeners()
    {
        return _listeners;
    }
    
    /* ------------------------------------------------------------ */
    public void setListeners(ListenerHolder[] listeners)
    {
        if (listeners!=null)
            for (ListenerHolder holder:listeners)
                holder.setServletHandler(this);

        updateBeans(_listeners,listeners);
        _listeners = listeners;
    }
    
    /* ------------------------------------------------------------ */
    public ListenerHolder newListenerHolder(Holder.Source source)
    {
        return new ListenerHolder(source);
    }

    /* ------------------------------------------------------------ */
    /**
     * Add a new servlet holder
     * @param source the holder source
     * @return the servlet holder
     */
    public ServletHolder newServletHolder(Holder.Source source)
    {
        return new ServletHolder(source);
    }

    /* ------------------------------------------------------------ */
    /** Convenience method to add a servlet.
     * @param className the class name
     * @param pathSpec the path spec
     * @return The servlet holder.
     */
    public ServletHolder addServletWithMapping (String className,String pathSpec)
    {
        ServletHolder holder = newServletHolder(Source.EMBEDDED);
        holder.setClassName(className);
        addServletWithMapping(holder,pathSpec);
        return holder;
    }

    /* ------------------------------------------------------------ */
    /** Convenience method to add a servlet.
     * @param servlet the servlet class
     * @param pathSpec the path spec
     * @return The servlet holder.
     */
    public ServletHolder addServletWithMapping (Class<? extends Servlet> servlet,String pathSpec)
    {
        ServletHolder holder = newServletHolder(Source.EMBEDDED);
        holder.setHeldClass(servlet);
        addServletWithMapping(holder,pathSpec);

        return holder;
    }

    /* ------------------------------------------------------------ */
    /** Convenience method to add a servlet.
     * @param servlet servlet holder to add
     * @param pathSpec servlet mappings for the servletHolder
     */
    public void addServletWithMapping (ServletHolder servlet,String pathSpec)
    {
        ServletHolder[] holders=getServlets();
        if (holders!=null)
            holders = holders.clone();

        try
        {
            synchronized (this)
            {
                if (servlet != null && !containsServletHolder(servlet))
                    setServlets(ArrayUtil.addToArray(holders, servlet, ServletHolder.class));
            }

            ServletMapping mapping = new ServletMapping();
            mapping.setServletName(servlet.getName());
            mapping.setPathSpec(pathSpec);
            setServletMappings(ArrayUtil.addToArray(getServletMappings(), mapping, ServletMapping.class));
        }
        catch (Exception e)
        {
            setServlets(holders);
            if (e instanceof RuntimeException)
                throw (RuntimeException)e;
            throw new RuntimeException(e);
        }
    }


    /* ------------------------------------------------------------ */
    /**
     * Convenience method to add a pre-constructed ServletHolder.
     * @param holder the servlet holder
     */
    public void addServlet(ServletHolder holder)
    {
        if (holder == null)
            return;
        
        synchronized (this)
        {
            if (!containsServletHolder(holder))
                setServlets(ArrayUtil.addToArray(getServlets(), holder, ServletHolder.class));
        }
    }

    /* ------------------------------------------------------------ */
    /** 
     * Convenience method to add a pre-constructed ServletMapping.
     * @param mapping the servlet mapping
     */
    public void addServletMapping (ServletMapping mapping)
    {
        setServletMappings(ArrayUtil.addToArray(getServletMappings(), mapping, ServletMapping.class));
    }
    
    /* ------------------------------------------------------------ */
    public Set<String>  setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement) 
    {
        if (_contextHandler != null) 
        {
            return _contextHandler.setServletSecurity(registration, servletSecurityElement);
        }
        return Collections.emptySet();
    }

    /* ------------------------------------------------------------ */
    public FilterHolder newFilterHolder(Holder.Source source)
    {
        return new FilterHolder(source);
    }

    /* ------------------------------------------------------------ */
    public FilterHolder getFilter(String name)
    {
        return _filterNameMap.get(name);
    }


    /* ------------------------------------------------------------ */
    /** Convenience method to add a filter.
     * @param filter  class of filter to create
     * @param pathSpec filter mappings for filter
     * @param dispatches see {@link FilterMapping#setDispatches(int)}
     * @return The filter holder.
     */
    public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,EnumSet<DispatcherType> dispatches)
    {
        FilterHolder holder = newFilterHolder(Source.EMBEDDED);
        holder.setHeldClass(filter);
        addFilterWithMapping(holder,pathSpec,dispatches);

        return holder;
    }

    /* ------------------------------------------------------------ */
    /** Convenience method to add a filter.
     * @param className of filter
     * @param pathSpec filter mappings for filter
     * @param dispatches see {@link FilterMapping#setDispatches(int)}
     * @return The filter holder.
     */
    public FilterHolder addFilterWithMapping (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
    {
        FilterHolder holder = newFilterHolder(Source.EMBEDDED);
        holder.setClassName(className);

        addFilterWithMapping(holder,pathSpec,dispatches);
        return holder;
    }

    /* ------------------------------------------------------------ */
    /** Convenience method to add a filter.
     * @param holder filter holder to add
     * @param pathSpec filter mappings for filter
     * @param dispatches see {@link FilterMapping#setDispatches(int)}
     */
    public void addFilterWithMapping (FilterHolder holder,String pathSpec,EnumSet<DispatcherType> dispatches)
    {
        FilterHolder[] holders = getFilters();
        if (holders!=null)
            holders = holders.clone();

        try
        {
            synchronized (this)
            {
                if (holder != null && !containsFilterHolder(holder))
                    setFilters(ArrayUtil.addToArray(holders, holder, FilterHolder.class));
            }

            FilterMapping mapping = new FilterMapping();
            mapping.setFilterName(holder.getName());
            mapping.setPathSpec(pathSpec);
            mapping.setDispatcherTypes(dispatches);
            addFilterMapping(mapping);
            
        }
        catch (RuntimeException e)
        {
            setFilters(holders);
            throw e;
        }
        catch (Error e)
        {
            setFilters(holders);
            throw e;
        }

    }

    /* ------------------------------------------------------------ */
    /** Convenience method to add a filter.
     * @param filter  class of filter to create
     * @param pathSpec filter mappings for filter
     * @param dispatches see {@link FilterMapping#setDispatches(int)}
     * @return The filter holder.
     */
    public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,int dispatches)
    {
        FilterHolder holder = newFilterHolder(Source.EMBEDDED);
        holder.setHeldClass(filter);
        addFilterWithMapping(holder,pathSpec,dispatches);

        return holder;
    }

    /* ------------------------------------------------------------ */
    /** Convenience method to add a filter.
     * @param className of filter
     * @param pathSpec filter mappings for filter
     * @param dispatches see {@link FilterMapping#setDispatches(int)}
     * @return The filter holder.
     */
    public FilterHolder addFilterWithMapping (String className,String pathSpec,int dispatches)
    {
        FilterHolder holder = newFilterHolder(Source.EMBEDDED);
        holder.setClassName(className);

        addFilterWithMapping(holder,pathSpec,dispatches);
        return holder;
    }

    /* ------------------------------------------------------------ */
    /** Convenience method to add a filter.
     * @param holder filter holder to add
     * @param pathSpec filter mappings for filter
     * @param dispatches see {@link FilterMapping#setDispatches(int)}
     */
    public void addFilterWithMapping (FilterHolder holder,String pathSpec,int dispatches)
    {
        FilterHolder[] holders = getFilters();
        if (holders!=null)
            holders = holders.clone();

        try
        {
            synchronized (this)
            {
                if (holder != null && !containsFilterHolder(holder))
                    setFilters(ArrayUtil.addToArray(holders, holder, FilterHolder.class));
            }

            FilterMapping mapping = new FilterMapping();
            mapping.setFilterName(holder.getName());
            mapping.setPathSpec(pathSpec);
            mapping.setDispatches(dispatches);
            addFilterMapping(mapping);
        }
        catch (RuntimeException e)
        {
            setFilters(holders);
            throw e;
        }
        catch (Error e)
        {
            setFilters(holders);
            throw e;
        }

    }

    /* ------------------------------------------------------------ */
    /** 
     * Convenience method to add a filter with a mapping
     * @param className the filter class name
     * @param pathSpec the path spec
     * @param dispatches the dispatcher types for this filter
     * @return the filter holder created
     * @deprecated use {@link #addFilterWithMapping(Class, String, EnumSet)} instead
     */
    @Deprecated
    public FilterHolder addFilter (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
    {
        return addFilterWithMapping(className, pathSpec, dispatches);
    }

    /* ------------------------------------------------------------ */
    /**
     * Convenience method to add a filter and mapping
     * @param filter the filter holder
     * @param filterMapping the filter mapping
     */
    public void addFilter (FilterHolder filter, FilterMapping filterMapping)
    {
        if (filter != null)
        {
            synchronized (this)
            {
                if (!containsFilterHolder(filter))
                    setFilters(ArrayUtil.addToArray(getFilters(), filter, FilterHolder.class));
            }
        }
        if (filterMapping != null)
            addFilterMapping(filterMapping);
    }

    /* ------------------------------------------------------------ */
    /** 
     * Convenience method to add a preconstructed FilterHolder
     * @param filter the filter holder
     */
    public void addFilter (FilterHolder filter)
    {
        if (filter == null)
            return;

        synchronized (this)
        {
            if (!containsFilterHolder(filter))
                setFilters(ArrayUtil.addToArray(getFilters(), filter, FilterHolder.class));
        }
    }

    /* ------------------------------------------------------------ */
    /** 
     * Convenience method to add a preconstructed FilterMapping
     * @param mapping the filter mapping
     */
    public void addFilterMapping (FilterMapping mapping)
    {
        if (mapping != null)
        {
            Source source = (mapping.getFilterHolder()==null?null:mapping.getFilterHolder().getSource());
            FilterMapping[] mappings =getFilterMappings();
            if (mappings==null || mappings.length==0)
            {
                setFilterMappings(insertFilterMapping(mapping,0,false));
                if (source != null && source == Source.JAVAX_API)
                    _matchAfterIndex = 0;
            }
            else
            {
                //there are existing entries. If this is a programmatic filtermapping, it is added at the end of the list.
                //If this is a normal filtermapping, it is inserted after all the other filtermappings (matchBefores and normals), 
                //but before the first matchAfter filtermapping.
                if (source != null && Source.JAVAX_API == source)
                {
                    setFilterMappings(insertFilterMapping(mapping,mappings.length-1, false));
                    if (_matchAfterIndex < 0)
                        _matchAfterIndex = getFilterMappings().length-1;
                }
                else
                {
                    //insert non-programmatic filter mappings before any matchAfters, if any
                    if (_matchAfterIndex < 0)
                        setFilterMappings(insertFilterMapping(mapping,mappings.length-1, false));
                    else
                    {
                        FilterMapping[] new_mappings = insertFilterMapping(mapping, _matchAfterIndex, true);
                        ++_matchAfterIndex;
                        setFilterMappings(new_mappings);
                    }
                }
            }
        }
    }
    

    /* ------------------------------------------------------------ */
    /** 
     * Convenience method to add a preconstructed FilterMapping
     * @param mapping the filter mapping
     */
    public void prependFilterMapping (FilterMapping mapping)
    {
        if (mapping != null)
        {
            Source source = (mapping.getFilterHolder()==null?null:mapping.getFilterHolder().getSource());
            FilterMapping[] mappings = getFilterMappings();
            if (mappings==null || mappings.length==0)
            {
                setFilterMappings(insertFilterMapping(mapping, 0, false));
                if (source != null && Source.JAVAX_API == source)
                    _matchBeforeIndex = 0;
            }
            else
            {
                if (source != null && Source.JAVAX_API == source)
                {
                    //programmatically defined filter mappings are prepended to mapping list in the order
                    //in which they were defined. In other words, insert this mapping at the tail of the 
                    //programmatically prepended filter mappings, BEFORE the first web.xml defined filter mapping.

                    if (_matchBeforeIndex < 0)
                    { 
                        //no programmatically defined prepended filter mappings yet, prepend this one
                        _matchBeforeIndex = 0;
                        FilterMapping[] new_mappings = insertFilterMapping(mapping, 0, true);
                        setFilterMappings(new_mappings);
                    }
                    else
                    {
                        FilterMapping[] new_mappings = insertFilterMapping(mapping,_matchBeforeIndex, false);
                        ++_matchBeforeIndex;
                        setFilterMappings(new_mappings);
                    }
                }
                else
                {
                    //non programmatically defined, just prepend to list
                    FilterMapping[] new_mappings = insertFilterMapping(mapping, 0, true);
                    setFilterMappings(new_mappings);
                }
                
                //adjust matchAfterIndex ptr to take account of the mapping we just prepended
                if (_matchAfterIndex >= 0)
                    ++_matchAfterIndex;
            }
        }
    }
    
    
    
    /**
     * Insert a filtermapping in the list
     * @param mapping the FilterMapping to add
     * @param pos the position in the existing arry at which to add it
     * @param before if true, insert before  pos, if false insert after it
     * @return the new FilterMappings post-insert
     */
    protected FilterMapping[] insertFilterMapping (FilterMapping mapping, int pos, boolean before)
    {
        if (pos < 0)
            throw new IllegalArgumentException("FilterMapping insertion pos < 0");
        FilterMapping[] mappings = getFilterMappings();
        
        if (mappings==null || mappings.length==0)
        {
            return new FilterMapping[] {mapping};
        }
        FilterMapping[] new_mappings = new FilterMapping[mappings.length+1];

    
        if (before)
        {
            //copy existing filter mappings up to but not including the pos
            System.arraycopy(mappings,0,new_mappings,0,pos);

            //add in the new mapping
            new_mappings[pos] = mapping; 

            //copy the old pos mapping and any remaining existing mappings
            System.arraycopy(mappings,pos,new_mappings,pos+1, mappings.length-pos);

        }
        else
        {
            //copy existing filter mappings up to and including the pos
            System.arraycopy(mappings,0,new_mappings,0,pos+1);
            //add in the new mapping after the pos
            new_mappings[pos+1] = mapping;   

            //copy the remaining existing mappings
            if (mappings.length > pos+1)
                System.arraycopy(mappings,pos+1,new_mappings,pos+2, mappings.length-(pos+1));
        }
        return new_mappings;
    }
    
    
    /* ------------------------------------------------------------ */
    protected synchronized void updateNameMappings()
    {
        // update filter name map
        _filterNameMap.clear();
        if (_filters!=null)
        {
            for (FilterHolder filter : _filters)
            {
                _filterNameMap.put(filter.getName(), filter);
                filter.setServletHandler(this);
            }
        }

        // Map servlet names to holders
        _servletNameMap.clear();
        if (_servlets!=null)
        {
            // update the maps
            for (ServletHolder servlet : _servlets)
            {
                _servletNameMap.put(servlet.getName(), servlet);
                servlet.setServletHandler(this);
            }
        }
    }

    /* ------------------------------------------------------------ */
    protected synchronized void updateMappings()
    {
        // update filter mappings
        if (_filterMappings==null)
        {
            _filterPathMappings=null;
            _filterNameMappings=null;
        }
        else
        {
            _filterPathMappings=new ArrayList<>();
            _filterNameMappings=new MultiMap<FilterMapping>();
            for (FilterMapping filtermapping : _filterMappings)
            {
                FilterHolder filter_holder = _filterNameMap.get(filtermapping.getFilterName());
                if (filter_holder == null)
                    throw new IllegalStateException("No filter named " + filtermapping.getFilterName());
                filtermapping.setFilterHolder(filter_holder);
                if (filtermapping.getPathSpecs() != null)
                    _filterPathMappings.add(filtermapping);

                if (filtermapping.getServletNames() != null)
                {
                    String[] names = filtermapping.getServletNames();
                    for (String name : names)
                    {
                        if (name != null)
                            _filterNameMappings.add(name, filtermapping);
                    }
                }
            }
        }

        // Map servlet paths to holders
        if (_servletMappings==null || _servletNameMap==null)
        {
            _servletPathMap=null;
        }
        else
        {
            PathMap<ServletHolder> pm = new PathMap<>();
            Map<String,ServletMapping> servletPathMappings = new HashMap<String,ServletMapping>();
            
            //create a map of paths to set of ServletMappings that define that mapping
            HashMap<String, List<ServletMapping>> sms = new HashMap<String, List<ServletMapping>>();
            for (ServletMapping servletMapping : _servletMappings)
            {
                String[] pathSpecs = servletMapping.getPathSpecs();
                if (pathSpecs != null)
                {
                    for (String pathSpec : pathSpecs)
                    {
                        List<ServletMapping> mappings = sms.get(pathSpec);
                        if (mappings == null)
                        {
                            mappings = new ArrayList<ServletMapping>();
                            sms.put(pathSpec, mappings);
                        }
                        mappings.add(servletMapping);
                    }
                }
            }
         
            //evaluate path to servlet map based on servlet mappings
            for (String pathSpec : sms.keySet())
            {
                //for each path, look at the mappings where it is referenced
                //if a mapping is for a servlet that is not enabled, skip it
                List<ServletMapping> mappings = sms.get(pathSpec);

                ServletMapping finalMapping = null;
                for (ServletMapping mapping : mappings)
                {
                    //Get servlet associated with the mapping and check it is enabled
                    ServletHolder servlet_holder = _servletNameMap.get(mapping.getServletName());
                    if (servlet_holder == null)
                        throw new IllegalStateException("No such servlet: " + mapping.getServletName());
                    //if the servlet related to the mapping is not enabled, skip it from consideration
                    if (!servlet_holder.isEnabled())
                        continue;

                    //only accept a default mapping if we don't have any other 
                    if (finalMapping == null)
                        finalMapping = mapping;
                    else
                    {
                        //already have a candidate - only accept another one 
                        //if the candidate is a default, or we're allowing duplicate mappings
                        if (finalMapping.isDefault())
                            finalMapping = mapping;
                        else if (isAllowDuplicateMappings())
                        {
                            LOG.warn("Multiple servlets map to path {}: {} and {}, choosing {}", pathSpec, finalMapping.getServletName(), mapping.getServletName(), mapping);
                            finalMapping = mapping;
                        }
                        else
                        {
                            //existing candidate isn't a default, if the one we're looking at isn't a default either, then its an error
                            if (!mapping.isDefault())
                                throw new IllegalStateException("Multiple servlets map to path: "+pathSpec+": "+finalMapping.getServletName()+","+mapping.getServletName());
                        }
                    }
                }
                if (finalMapping == null)
                    throw new IllegalStateException ("No acceptable servlet mappings for "+pathSpec);
           
                if (LOG.isDebugEnabled()) LOG.debug("Chose path={} mapped to servlet={} from default={}", pathSpec, finalMapping.getServletName(), finalMapping.isDefault());
               
                servletPathMappings.put(pathSpec, finalMapping);
                pm.put(pathSpec,_servletNameMap.get(finalMapping.getServletName()));
            }
     
            _servletPathMap=pm;
        }

        // flush filter chain cache
        if (_chainCache!=null)
        {
            for (int i=_chainCache.length;i-->0;)
            {
                if (_chainCache[i]!=null)
                    _chainCache[i].clear();
            }
        }

        if (LOG.isDebugEnabled())
        {
            LOG.debug("filterNameMap="+_filterNameMap);
            LOG.debug("pathFilters="+_filterPathMappings);
            LOG.debug("servletFilterMap="+_filterNameMappings);
            LOG.debug("servletPathMap="+_servletPathMap);
            LOG.debug("servletNameMap="+_servletNameMap);
        }

        try
        {
            if (_contextHandler!=null && _contextHandler.isStarted() || _contextHandler==null && isStarted())
                initialize();
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }

    /* ------------------------------------------------------------ */
    protected void notFound(Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        if (LOG.isDebugEnabled())
            LOG.debug("Not Found {}",request.getRequestURI());
        if (getHandler()!=null)
            nextHandle(URIUtil.addPaths(request.getServletPath(),request.getPathInfo()),baseRequest,request,response);
    }
    
    
    protected synchronized boolean containsFilterHolder (FilterHolder holder)
    {
        if (_filters == null)
            return false;
        boolean found = false;
        for (FilterHolder f:_filters)
        {
            if (f == holder)
                found = true;
        }
        return found;
    }

    
    protected synchronized boolean containsServletHolder (ServletHolder holder)
    {
        if (_servlets == null)
            return false;
        boolean found = false;
        for (ServletHolder s:_servlets)
        {
            if (s == holder)
                found = true;
        }
        return found;
    }
    
    
    /* ------------------------------------------------------------ */
    /**
     * @param filterChainsCached The filterChainsCached to set.
     */
    public void setFilterChainsCached(boolean filterChainsCached)
    {
        _filterChainsCached = filterChainsCached;
    }

    /* ------------------------------------------------------------ */
    /**
     * @param filterMappings The filterMappings to set.
     */
    public void setFilterMappings(FilterMapping[] filterMappings)
    {
        updateBeans(_filterMappings,filterMappings);
        _filterMappings = filterMappings;
        if (isStarted()) updateMappings();
        invalidateChainsCache();
    }

    /* ------------------------------------------------------------ */
    public synchronized void setFilters(FilterHolder[] holders)
    {
        if (holders!=null)
            for (FilterHolder holder:holders)
                holder.setServletHandler(this);
        
        updateBeans(_filters,holders);
        _filters=holders;
        updateNameMappings();
        invalidateChainsCache();
    }

    /* ------------------------------------------------------------ */
    /**
     * @param servletMappings The servletMappings to set.
     */
    public void setServletMappings(ServletMapping[] servletMappings)
    {
        updateBeans(_servletMappings,servletMappings);
        _servletMappings = servletMappings;
        if (isStarted()) updateMappings();
        invalidateChainsCache();
    }

    /* ------------------------------------------------------------ */
    /** Set Servlets.
     * @param holders Array of servlets to define
     */
    public synchronized void setServlets(ServletHolder[] holders)
    {
        if (holders!=null)
            for (ServletHolder holder:holders)
                holder.setServletHandler(this);
        
        updateBeans(_servlets,holders);
        _servlets=holders;
        updateNameMappings();
        invalidateChainsCache();
    }

    /* ------------------------------------------------------------ */
    /* ------------------------------------------------------------ */
    private class CachedChain implements FilterChain
    {
        FilterHolder _filterHolder;
        CachedChain _next;
        ServletHolder _servletHolder;

        /* ------------------------------------------------------------ */
        /**
         * @param filters list of {@link FilterHolder} objects
         * @param servletHolder
         */
        CachedChain(List<FilterHolder> filters, ServletHolder servletHolder)
        {
            if (filters.size()>0)
            {
                _filterHolder=filters.get(0);
                filters.remove(0);
                _next=new CachedChain(filters,servletHolder);
            }
            else
                _servletHolder=servletHolder;
        }

        /* ------------------------------------------------------------ */
        @Override
        public void doFilter(ServletRequest request, ServletResponse response)
            throws IOException, ServletException
        {
            final Request baseRequest=Request.getBaseRequest(request);

            // pass to next filter
            if (_filterHolder!=null)
            {
                if (LOG.isDebugEnabled())
                    LOG.debug("call filter {}", _filterHolder);
                Filter filter= _filterHolder.getFilter();
                
                //if the request already does not support async, then the setting for the filter
                //is irrelevant. However if the request supports async but this filter does not
                //temporarily turn it off for the execution of the filter
                if (baseRequest.isAsyncSupported() && !_filterHolder.isAsyncSupported())
                { 
                    try
                    {
                        baseRequest.setAsyncSupported(false,_filterHolder.toString());
                        filter.doFilter(request, response, _next);
                    }
                    finally
                    {
                        baseRequest.setAsyncSupported(true,null);
                    }
                }
                else
                    filter.doFilter(request, response, _next);

                return;
            }

            // Call servlet
            HttpServletRequest srequest = (HttpServletRequest)request;
            if (_servletHolder == null)
                notFound(baseRequest, srequest, (HttpServletResponse)response);
            else
            {
                if (LOG.isDebugEnabled())
                    LOG.debug("call servlet " + _servletHolder);
                _servletHolder.handle(baseRequest,request, response);
            }
        }

        @Override
        public String toString()
        {
            if (_filterHolder!=null)
                return _filterHolder+"->"+_next.toString();
            if (_servletHolder!=null)
                return _servletHolder.toString();
            return "null";
        }
    }

    /* ------------------------------------------------------------ */
    /* ------------------------------------------------------------ */
    private class Chain implements FilterChain
    {
        final Request _baseRequest;
        final List<FilterHolder> _chain;
        final ServletHolder _servletHolder;
        int _filter= 0;

        /* ------------------------------------------------------------ */
        Chain(Request baseRequest, List<FilterHolder> filters, ServletHolder servletHolder)
        {
            _baseRequest=baseRequest;
            _chain= filters;
            _servletHolder= servletHolder;
        }

        /* ------------------------------------------------------------ */
        @Override
        public void doFilter(ServletRequest request, ServletResponse response)
            throws IOException, ServletException
        {
            if (LOG.isDebugEnabled())
                LOG.debug("doFilter " + _filter);

            // pass to next filter
            if (_filter < _chain.size())
            {
                FilterHolder holder= _chain.get(_filter++);
                if (LOG.isDebugEnabled())
                    LOG.debug("call filter " + holder);
                Filter filter= holder.getFilter();

                //if the request already does not support async, then the setting for the filter
                //is irrelevant. However if the request supports async but this filter does not
                //temporarily turn it off for the execution of the filter
                if (!holder.isAsyncSupported() && _baseRequest.isAsyncSupported())
                {
                    try
                    {
                        _baseRequest.setAsyncSupported(false,holder.toString());
                        filter.doFilter(request, response, this);
                    }
                    finally
                    {
                        _baseRequest.setAsyncSupported(true,null);
                    }
                }
                else
                    filter.doFilter(request, response, this);

                return;
            }

            // Call servlet
            HttpServletRequest srequest = (HttpServletRequest)request;
            if (_servletHolder == null)
                notFound(Request.getBaseRequest(request), srequest, (HttpServletResponse)response);
            else
            {
                if (LOG.isDebugEnabled())
                    LOG.debug("call servlet {}", _servletHolder);
                _servletHolder.handle(_baseRequest,request, response);
            }    
        }

        /* ------------------------------------------------------------ */
        @Override
        public String toString()
        {
            StringBuilder b = new StringBuilder();
            for(FilterHolder f: _chain)
            {
                b.append(f.toString());
                b.append("->");
            }
            b.append(_servletHolder);
            return b.toString();
        }
    }

    /* ------------------------------------------------------------ */
    /**
     * @return The maximum entries in a filter chain cache.
     */
    public int getMaxFilterChainsCacheSize()
    {
        return _maxFilterChainsCacheSize;
    }

    /* ------------------------------------------------------------ */
    /** Set the maximum filter chain cache size.
     * Filter chains are cached if {@link #isFilterChainsCached()} is true. If the max cache size
     * is greater than zero, then the cache is flushed whenever it grows to be this size.
     *
     * @param maxFilterChainsCacheSize  the maximum number of entries in a filter chain cache.
     */
    public void setMaxFilterChainsCacheSize(int maxFilterChainsCacheSize)
    {
        _maxFilterChainsCacheSize = maxFilterChainsCacheSize;
    }

    /* ------------------------------------------------------------ */
    void destroyServlet(Servlet servlet)
    {
        if (_contextHandler!=null)
            _contextHandler.destroyServlet(servlet);
    }

    /* ------------------------------------------------------------ */
    void destroyFilter(Filter filter)
    {
        if (_contextHandler!=null)
            _contextHandler.destroyFilter(filter);
    }

    /* ------------------------------------------------------------ */
    /* ------------------------------------------------------------ */
    /* ------------------------------------------------------------ */
    public static class Default404Servlet extends HttpServlet
    {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException
        {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
    }
}
