103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.servlet;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.ArrayList;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Arrays;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Collections;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.EnumSet;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashMap;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashSet;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.ListIterator;
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Set;
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Map;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Queue;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.concurrent.ConcurrentHashMap;
3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.concurrent.ConcurrentLinkedQueue;
3503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.concurrent.ConcurrentMap;
3603928aee4356845252ac6b662d5c72c29903813eJake Slack
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.AsyncContext;
3803928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.DispatcherType;
3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.Filter;
4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.FilterChain;
4103928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.RequestDispatcher;
4203928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.Servlet;
4303928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletContext;
4403928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletException;
4503928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletRegistration;
4603928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletRequest;
4703928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletResponse;
4803928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletSecurityElement;
4903928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.UnavailableException;
5003928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletRequest;
5103928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletResponse;
5203928aee4356845252ac6b662d5c72c29903813eJake Slack
5303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.continuation.ContinuationThrowable;
5403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.HttpException;
5503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.PathMap;
5603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EofException;
5703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.RuntimeIOException;
5803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.security.IdentityService;
5903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.security.SecurityHandler;
6003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.AbstractHttpConnection;
6103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.AsyncContinuation;
6203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Dispatcher;
6303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.AbstractHttpConnection;
6403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Request;
6503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Server;
6603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.ServletRequestHttpWrapper;
6703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.ServletResponseHttpWrapper;
6803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.UserIdentity;
6903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.handler.ContextHandler;
7003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.handler.ScopedHandler;
7103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.servlet.Holder.Source;
7203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.LazyList;
7303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.MultiException;
7403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.MultiMap;
7503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.TypeUtil;
7603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.URIUtil;
7703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
7803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
7903928aee4356845252ac6b662d5c72c29903813eJake Slack
8003928aee4356845252ac6b662d5c72c29903813eJake Slack/* --------------------------------------------------------------------- */
8103928aee4356845252ac6b662d5c72c29903813eJake Slack/** Servlet HttpHandler.
8203928aee4356845252ac6b662d5c72c29903813eJake Slack * This handler maps requests to servlets that implement the
8303928aee4356845252ac6b662d5c72c29903813eJake Slack * javax.servlet.http.HttpServlet API.
8403928aee4356845252ac6b662d5c72c29903813eJake Slack * <P>
8503928aee4356845252ac6b662d5c72c29903813eJake Slack * This handler does not implement the full J2EE features and is intended to
8603928aee4356845252ac6b662d5c72c29903813eJake Slack * be used directly when a full web application is not required.  If a Web application is required,
8703928aee4356845252ac6b662d5c72c29903813eJake Slack * then this handler should be used as part of a <code>org.eclipse.jetty.webapp.WebAppContext</code>.
8803928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
8903928aee4356845252ac6b662d5c72c29903813eJake Slack * Unless run as part of a {@link ServletContextHandler} or derivative, the {@link #initialize()}
9003928aee4356845252ac6b662d5c72c29903813eJake Slack * method must be called manually after start().
9103928aee4356845252ac6b662d5c72c29903813eJake Slack */
9203928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class ServletHandler extends ScopedHandler
9303928aee4356845252ac6b662d5c72c29903813eJake Slack{
9403928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(ServletHandler.class);
9503928aee4356845252ac6b662d5c72c29903813eJake Slack
9603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9703928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final String __DEFAULT_SERVLET="default";
9803928aee4356845252ac6b662d5c72c29903813eJake Slack
9903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10003928aee4356845252ac6b662d5c72c29903813eJake Slack    private ServletContextHandler _contextHandler;
10103928aee4356845252ac6b662d5c72c29903813eJake Slack    private ContextHandler.Context _servletContext;
10203928aee4356845252ac6b662d5c72c29903813eJake Slack    private FilterHolder[] _filters=new FilterHolder[0];
10303928aee4356845252ac6b662d5c72c29903813eJake Slack    private FilterMapping[] _filterMappings;
10403928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _matchBeforeIndex = -1; //index of last programmatic FilterMapping with isMatchAfter=false
10503928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _matchAfterIndex = -1;  //index of 1st programmatic FilterMapping with isMatchAfter=true
10603928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _filterChainsCached=true;
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _maxFilterChainsCacheSize=512;
10803928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _startWithUnavailable=false;
10903928aee4356845252ac6b662d5c72c29903813eJake Slack    private IdentityService _identityService;
11003928aee4356845252ac6b662d5c72c29903813eJake Slack
11103928aee4356845252ac6b662d5c72c29903813eJake Slack    private ServletHolder[] _servlets=new ServletHolder[0];
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    private ServletMapping[] _servletMappings;
11303928aee4356845252ac6b662d5c72c29903813eJake Slack
11403928aee4356845252ac6b662d5c72c29903813eJake Slack    private final Map<String,FilterHolder> _filterNameMap= new HashMap<String,FilterHolder>();
11503928aee4356845252ac6b662d5c72c29903813eJake Slack    private List<FilterMapping> _filterPathMappings;
11603928aee4356845252ac6b662d5c72c29903813eJake Slack    private MultiMap<String> _filterNameMappings;
11703928aee4356845252ac6b662d5c72c29903813eJake Slack
11803928aee4356845252ac6b662d5c72c29903813eJake Slack    private final Map<String,ServletHolder> _servletNameMap=new HashMap<String,ServletHolder>();
11903928aee4356845252ac6b662d5c72c29903813eJake Slack    private PathMap _servletPathMap;
12003928aee4356845252ac6b662d5c72c29903813eJake Slack
12103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected final ConcurrentMap<String,FilterChain> _chainCache[] = new ConcurrentMap[FilterMapping.ALL];
12203928aee4356845252ac6b662d5c72c29903813eJake Slack    protected final Queue<String>[] _chainLRU = new Queue[FilterMapping.ALL];
12303928aee4356845252ac6b662d5c72c29903813eJake Slack
12403928aee4356845252ac6b662d5c72c29903813eJake Slack
12503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
12603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Constructor.
12703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletHandler()
12903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13103928aee4356845252ac6b662d5c72c29903813eJake Slack
13203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
13303928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
13403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.server.handler.AbstractHandler#setServer(org.eclipse.jetty.server.Server)
13503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
13603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setServer(Server server)
13703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13803928aee4356845252ac6b662d5c72c29903813eJake Slack        Server old=getServer();
13903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (old!=null && old!=server)
14003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
14103928aee4356845252ac6b662d5c72c29903813eJake Slack            getServer().getContainer().update(this, _filters, null, "filter",true);
14203928aee4356845252ac6b662d5c72c29903813eJake Slack            getServer().getContainer().update(this, _filterMappings, null, "filterMapping",true);
14303928aee4356845252ac6b662d5c72c29903813eJake Slack            getServer().getContainer().update(this, _servlets, null, "servlet",true);
14403928aee4356845252ac6b662d5c72c29903813eJake Slack            getServer().getContainer().update(this, _servletMappings, null, "servletMapping",true);
14503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
14603928aee4356845252ac6b662d5c72c29903813eJake Slack
14703928aee4356845252ac6b662d5c72c29903813eJake Slack        super.setServer(server);
14803928aee4356845252ac6b662d5c72c29903813eJake Slack
14903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (server!=null && old!=server)
15003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
15103928aee4356845252ac6b662d5c72c29903813eJake Slack            server.getContainer().update(this, null, _filters, "filter",true);
15203928aee4356845252ac6b662d5c72c29903813eJake Slack            server.getContainer().update(this, null, _filterMappings, "filterMapping",true);
15303928aee4356845252ac6b662d5c72c29903813eJake Slack            server.getContainer().update(this, null, _servlets, "servlet",true);
15403928aee4356845252ac6b662d5c72c29903813eJake Slack            server.getContainer().update(this, null, _servletMappings, "servletMapping",true);
15503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
15603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
15703928aee4356845252ac6b662d5c72c29903813eJake Slack
15803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ----------------------------------------------------------------- */
15903928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
16003928aee4356845252ac6b662d5c72c29903813eJake Slack    protected synchronized void doStart()
16103928aee4356845252ac6b662d5c72c29903813eJake Slack        throws Exception
16203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16303928aee4356845252ac6b662d5c72c29903813eJake Slack        _servletContext=ContextHandler.getCurrentContext();
16403928aee4356845252ac6b662d5c72c29903813eJake Slack        _contextHandler=(ServletContextHandler)(_servletContext==null?null:_servletContext.getContextHandler());
16503928aee4356845252ac6b662d5c72c29903813eJake Slack
16603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_contextHandler!=null)
16703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
16803928aee4356845252ac6b662d5c72c29903813eJake Slack            SecurityHandler security_handler = (SecurityHandler)_contextHandler.getChildHandlerByClass(SecurityHandler.class);
16903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (security_handler!=null)
17003928aee4356845252ac6b662d5c72c29903813eJake Slack                _identityService=security_handler.getIdentityService();
17103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
17203928aee4356845252ac6b662d5c72c29903813eJake Slack
17303928aee4356845252ac6b662d5c72c29903813eJake Slack        updateNameMappings();
17403928aee4356845252ac6b662d5c72c29903813eJake Slack        updateMappings();
17503928aee4356845252ac6b662d5c72c29903813eJake Slack
17603928aee4356845252ac6b662d5c72c29903813eJake Slack        if(_filterChainsCached)
17703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
17803928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainCache[FilterMapping.REQUEST]=new ConcurrentHashMap<String,FilterChain>();
17903928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainCache[FilterMapping.FORWARD]=new ConcurrentHashMap<String,FilterChain>();
18003928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainCache[FilterMapping.INCLUDE]=new ConcurrentHashMap<String,FilterChain>();
18103928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainCache[FilterMapping.ERROR]=new ConcurrentHashMap<String,FilterChain>();
18203928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainCache[FilterMapping.ASYNC]=new ConcurrentHashMap<String,FilterChain>();
18303928aee4356845252ac6b662d5c72c29903813eJake Slack
18403928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainLRU[FilterMapping.REQUEST]=new ConcurrentLinkedQueue<String>();
18503928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainLRU[FilterMapping.FORWARD]=new ConcurrentLinkedQueue<String>();
18603928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainLRU[FilterMapping.INCLUDE]=new ConcurrentLinkedQueue<String>();
18703928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainLRU[FilterMapping.ERROR]=new ConcurrentLinkedQueue<String>();
18803928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainLRU[FilterMapping.ASYNC]=new ConcurrentLinkedQueue<String>();
18903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
19003928aee4356845252ac6b662d5c72c29903813eJake Slack
19103928aee4356845252ac6b662d5c72c29903813eJake Slack        super.doStart();
19203928aee4356845252ac6b662d5c72c29903813eJake Slack
19303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_contextHandler==null || !(_contextHandler instanceof ServletContextHandler))
19403928aee4356845252ac6b662d5c72c29903813eJake Slack            initialize();
19503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
19603928aee4356845252ac6b662d5c72c29903813eJake Slack
19703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ----------------------------------------------------------------- */
19803928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
19903928aee4356845252ac6b662d5c72c29903813eJake Slack    protected synchronized void doStop()
20003928aee4356845252ac6b662d5c72c29903813eJake Slack        throws Exception
20103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20203928aee4356845252ac6b662d5c72c29903813eJake Slack        super.doStop();
20303928aee4356845252ac6b662d5c72c29903813eJake Slack
20403928aee4356845252ac6b662d5c72c29903813eJake Slack        // Stop filters
20503928aee4356845252ac6b662d5c72c29903813eJake Slack        List<FilterHolder> filterHolders = new ArrayList<FilterHolder>();
20603928aee4356845252ac6b662d5c72c29903813eJake Slack        List<FilterMapping> filterMappings = LazyList.array2List(_filterMappings);
20703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_filters!=null)
20803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
20903928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=_filters.length; i-->0;)
21003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
21103928aee4356845252ac6b662d5c72c29903813eJake Slack                try { _filters[i].stop(); }catch(Exception e){LOG.warn(Log.EXCEPTION,e);}
21203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_filters[i].getSource() != Source.EMBEDDED)
21303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
21403928aee4356845252ac6b662d5c72c29903813eJake Slack                    //remove all of the mappings that were for non-embedded filters
21503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _filterNameMap.remove(_filters[i].getName());
21603928aee4356845252ac6b662d5c72c29903813eJake Slack                    //remove any mappings associated with this filter
21703928aee4356845252ac6b662d5c72c29903813eJake Slack                    ListIterator<FilterMapping> fmitor = filterMappings.listIterator();
21803928aee4356845252ac6b662d5c72c29903813eJake Slack                    while (fmitor.hasNext())
21903928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
22003928aee4356845252ac6b662d5c72c29903813eJake Slack                        FilterMapping fm = fmitor.next();
22103928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (fm.getFilterName().equals(_filters[i].getName()))
22203928aee4356845252ac6b662d5c72c29903813eJake Slack                            fmitor.remove();
22303928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
22403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
22503928aee4356845252ac6b662d5c72c29903813eJake Slack                else
22603928aee4356845252ac6b662d5c72c29903813eJake Slack                    filterHolders.add(_filters[i]); //only retain embedded
22703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
22803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
22903928aee4356845252ac6b662d5c72c29903813eJake Slack        _filters = (FilterHolder[]) LazyList.toArray(filterHolders, FilterHolder.class);
23003928aee4356845252ac6b662d5c72c29903813eJake Slack        _filterMappings = (FilterMapping[]) LazyList.toArray(filterMappings, FilterMapping.class);
23103928aee4356845252ac6b662d5c72c29903813eJake Slack        _matchAfterIndex = (_filterMappings == null || _filterMappings.length == 0 ? -1 : _filterMappings.length-1);
23203928aee4356845252ac6b662d5c72c29903813eJake Slack        _matchBeforeIndex = -1;
23303928aee4356845252ac6b662d5c72c29903813eJake Slack
23403928aee4356845252ac6b662d5c72c29903813eJake Slack
23503928aee4356845252ac6b662d5c72c29903813eJake Slack        // Stop servlets
23603928aee4356845252ac6b662d5c72c29903813eJake Slack        List<ServletHolder> servletHolders = new ArrayList<ServletHolder>();  //will be remaining servlets
23703928aee4356845252ac6b662d5c72c29903813eJake Slack        List<ServletMapping> servletMappings = LazyList.array2List(_servletMappings); //will be remaining mappings
23803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_servlets!=null)
23903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
24003928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=_servlets.length; i-->0;)
24103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
24203928aee4356845252ac6b662d5c72c29903813eJake Slack                try { _servlets[i].stop(); }catch(Exception e){LOG.warn(Log.EXCEPTION,e);}
24303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_servlets[i].getSource() != Source.EMBEDDED)
24403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
24503928aee4356845252ac6b662d5c72c29903813eJake Slack                    //remove from servlet name map
24603928aee4356845252ac6b662d5c72c29903813eJake Slack                    _servletNameMap.remove(_servlets[i].getName());
24703928aee4356845252ac6b662d5c72c29903813eJake Slack                    //remove any mappings associated with this servlet
24803928aee4356845252ac6b662d5c72c29903813eJake Slack                    ListIterator<ServletMapping> smitor = servletMappings.listIterator();
24903928aee4356845252ac6b662d5c72c29903813eJake Slack                    while (smitor.hasNext())
25003928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
25103928aee4356845252ac6b662d5c72c29903813eJake Slack                        ServletMapping sm = smitor.next();
25203928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (sm.getServletName().equals(_servlets[i].getName()))
25303928aee4356845252ac6b662d5c72c29903813eJake Slack                            smitor.remove();
25403928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
25503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
25603928aee4356845252ac6b662d5c72c29903813eJake Slack                else
25703928aee4356845252ac6b662d5c72c29903813eJake Slack                    servletHolders.add(_servlets[i]); //only retain embedded
25803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
25903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
26003928aee4356845252ac6b662d5c72c29903813eJake Slack        _servlets = (ServletHolder[]) LazyList.toArray(servletHolders, ServletHolder.class);
26103928aee4356845252ac6b662d5c72c29903813eJake Slack        _servletMappings = (ServletMapping[])LazyList.toArray(servletMappings, ServletMapping.class);
26203928aee4356845252ac6b662d5c72c29903813eJake Slack
26303928aee4356845252ac6b662d5c72c29903813eJake Slack
26403928aee4356845252ac6b662d5c72c29903813eJake Slack        //will be regenerated on next start
26503928aee4356845252ac6b662d5c72c29903813eJake Slack        _filterPathMappings=null;
26603928aee4356845252ac6b662d5c72c29903813eJake Slack        _filterNameMappings=null;
26703928aee4356845252ac6b662d5c72c29903813eJake Slack        _servletPathMap=null;
26803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
26903928aee4356845252ac6b662d5c72c29903813eJake Slack
27003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
27103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected IdentityService getIdentityService()
27203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
27303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _identityService;
27403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
27503928aee4356845252ac6b662d5c72c29903813eJake Slack
27603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
27703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
27803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the contextLog.
27903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
28003928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object getContextLog()
28103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
28203928aee4356845252ac6b662d5c72c29903813eJake Slack        return null;
28303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
28403928aee4356845252ac6b662d5c72c29903813eJake Slack
28503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
28603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
28703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the filterMappings.
28803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
28903928aee4356845252ac6b662d5c72c29903813eJake Slack    public FilterMapping[] getFilterMappings()
29003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
29103928aee4356845252ac6b662d5c72c29903813eJake Slack        return _filterMappings;
29203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
29303928aee4356845252ac6b662d5c72c29903813eJake Slack
29403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
29503928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Get Filters.
29603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Array of defined servlets
29703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
29803928aee4356845252ac6b662d5c72c29903813eJake Slack    public FilterHolder[] getFilters()
29903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
30003928aee4356845252ac6b662d5c72c29903813eJake Slack        return _filters;
30103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
30203928aee4356845252ac6b662d5c72c29903813eJake Slack
30303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
30403928aee4356845252ac6b662d5c72c29903813eJake Slack    /** ServletHolder matching path.
30503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pathInContext Path within _context.
30603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return PathMap Entries pathspec to ServletHolder
30703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
30803928aee4356845252ac6b662d5c72c29903813eJake Slack    public PathMap.Entry getHolderEntry(String pathInContext)
30903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
31003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_servletPathMap==null)
31103928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
31203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _servletPathMap.getMatch(pathInContext);
31303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
31403928aee4356845252ac6b662d5c72c29903813eJake Slack
31503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
31603928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletContext getServletContext()
31703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
31803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _servletContext;
31903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
32003928aee4356845252ac6b662d5c72c29903813eJake Slack
32103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
32203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
32303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the servletMappings.
32403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
32503928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletMapping[] getServletMappings()
32603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
32703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _servletMappings;
32803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
32903928aee4356845252ac6b662d5c72c29903813eJake Slack
33003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
33103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
33203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the servletMappings.
33303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
33403928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletMapping getServletMapping(String pattern)
33503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
33603928aee4356845252ac6b662d5c72c29903813eJake Slack        ServletMapping theMapping = null;
33703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_servletMappings!=null)
33803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
33903928aee4356845252ac6b662d5c72c29903813eJake Slack            for (ServletMapping m:_servletMappings)
34003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
34103928aee4356845252ac6b662d5c72c29903813eJake Slack                String[] paths=m.getPathSpecs();
34203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (paths!=null)
34303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
34403928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (String path:paths)
34503928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
34603928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (pattern.equals(path))
34703928aee4356845252ac6b662d5c72c29903813eJake Slack                            theMapping = m;
34803928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
34903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
35003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
35103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
35203928aee4356845252ac6b662d5c72c29903813eJake Slack        return theMapping;
35303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
35403928aee4356845252ac6b662d5c72c29903813eJake Slack
35503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
35603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Get Servlets.
35703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Array of defined servlets
35803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
35903928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletHolder[] getServlets()
36003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
36103928aee4356845252ac6b662d5c72c29903813eJake Slack        return _servlets;
36203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36303928aee4356845252ac6b662d5c72c29903813eJake Slack
36403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
36503928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletHolder getServlet(String name)
36603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
36703928aee4356845252ac6b662d5c72c29903813eJake Slack        return (ServletHolder)_servletNameMap.get(name);
36803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36903928aee4356845252ac6b662d5c72c29903813eJake Slack
37003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
37103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
37203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
37303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
37403928aee4356845252ac6b662d5c72c29903813eJake Slack        // Get the base requests
37503928aee4356845252ac6b662d5c72c29903813eJake Slack        final String old_servlet_path=baseRequest.getServletPath();
37603928aee4356845252ac6b662d5c72c29903813eJake Slack        final String old_path_info=baseRequest.getPathInfo();
37703928aee4356845252ac6b662d5c72c29903813eJake Slack
37803928aee4356845252ac6b662d5c72c29903813eJake Slack        DispatcherType type = baseRequest.getDispatcherType();
37903928aee4356845252ac6b662d5c72c29903813eJake Slack
38003928aee4356845252ac6b662d5c72c29903813eJake Slack        ServletHolder servlet_holder=null;
38103928aee4356845252ac6b662d5c72c29903813eJake Slack        UserIdentity.Scope old_scope=null;
38203928aee4356845252ac6b662d5c72c29903813eJake Slack
38303928aee4356845252ac6b662d5c72c29903813eJake Slack        // find the servlet
38403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (target.startsWith("/"))
38503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
38603928aee4356845252ac6b662d5c72c29903813eJake Slack            // Look for the servlet by path
38703928aee4356845252ac6b662d5c72c29903813eJake Slack            PathMap.Entry entry=getHolderEntry(target);
38803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (entry!=null)
38903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
39003928aee4356845252ac6b662d5c72c29903813eJake Slack                servlet_holder=(ServletHolder)entry.getValue();
39103928aee4356845252ac6b662d5c72c29903813eJake Slack
39203928aee4356845252ac6b662d5c72c29903813eJake Slack                String servlet_path_spec=(String)entry.getKey();
39303928aee4356845252ac6b662d5c72c29903813eJake Slack                String servlet_path=entry.getMapped()!=null?entry.getMapped():PathMap.pathMatch(servlet_path_spec,target);
39403928aee4356845252ac6b662d5c72c29903813eJake Slack                String path_info=PathMap.pathInfo(servlet_path_spec,target);
39503928aee4356845252ac6b662d5c72c29903813eJake Slack
39603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (DispatcherType.INCLUDE.equals(type))
39703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
39803928aee4356845252ac6b662d5c72c29903813eJake Slack                    baseRequest.setAttribute(Dispatcher.INCLUDE_SERVLET_PATH,servlet_path);
39903928aee4356845252ac6b662d5c72c29903813eJake Slack                    baseRequest.setAttribute(Dispatcher.INCLUDE_PATH_INFO, path_info);
40003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
40103928aee4356845252ac6b662d5c72c29903813eJake Slack                else
40203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
40303928aee4356845252ac6b662d5c72c29903813eJake Slack                    baseRequest.setServletPath(servlet_path);
40403928aee4356845252ac6b662d5c72c29903813eJake Slack                    baseRequest.setPathInfo(path_info);
40503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
40603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
40703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
40803928aee4356845252ac6b662d5c72c29903813eJake Slack        else
40903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
41003928aee4356845252ac6b662d5c72c29903813eJake Slack            // look for a servlet by name!
41103928aee4356845252ac6b662d5c72c29903813eJake Slack            servlet_holder=(ServletHolder)_servletNameMap.get(target);
41203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
41303928aee4356845252ac6b662d5c72c29903813eJake Slack
41403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (LOG.isDebugEnabled())
41503928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("servlet {}|{}|{} -> {}",baseRequest.getContextPath(),baseRequest.getServletPath(),baseRequest.getPathInfo(),servlet_holder);
41603928aee4356845252ac6b662d5c72c29903813eJake Slack
41703928aee4356845252ac6b662d5c72c29903813eJake Slack        try
41803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
41903928aee4356845252ac6b662d5c72c29903813eJake Slack            // Do the filter/handling thang
42003928aee4356845252ac6b662d5c72c29903813eJake Slack            old_scope=baseRequest.getUserIdentityScope();
42103928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setUserIdentityScope(servlet_holder);
42203928aee4356845252ac6b662d5c72c29903813eJake Slack
42303928aee4356845252ac6b662d5c72c29903813eJake Slack            // start manual inline of nextScope(target,baseRequest,request,response);
42403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (never())
42503928aee4356845252ac6b662d5c72c29903813eJake Slack                nextScope(target,baseRequest,request,response);
42603928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (_nextScope!=null)
42703928aee4356845252ac6b662d5c72c29903813eJake Slack                _nextScope.doScope(target,baseRequest,request, response);
42803928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (_outerScope!=null)
42903928aee4356845252ac6b662d5c72c29903813eJake Slack                _outerScope.doHandle(target,baseRequest,request, response);
43003928aee4356845252ac6b662d5c72c29903813eJake Slack            else
43103928aee4356845252ac6b662d5c72c29903813eJake Slack                doHandle(target,baseRequest,request, response);
43203928aee4356845252ac6b662d5c72c29903813eJake Slack            // end manual inline (pathentic attempt to reduce stack depth)
43303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
43403928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
43503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
43603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (old_scope!=null)
43703928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setUserIdentityScope(old_scope);
43803928aee4356845252ac6b662d5c72c29903813eJake Slack
43903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!(DispatcherType.INCLUDE.equals(type)))
44003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
44103928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setServletPath(old_servlet_path);
44203928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setPathInfo(old_path_info);
44303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
44403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
44503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
44603928aee4356845252ac6b662d5c72c29903813eJake Slack
44703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
44803928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
44903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
45003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
45103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
45203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void doHandle(String target, Request baseRequest,HttpServletRequest request, HttpServletResponse response)
45303928aee4356845252ac6b662d5c72c29903813eJake Slack        throws IOException, ServletException
45403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
45503928aee4356845252ac6b662d5c72c29903813eJake Slack        DispatcherType type = baseRequest.getDispatcherType();
45603928aee4356845252ac6b662d5c72c29903813eJake Slack
45703928aee4356845252ac6b662d5c72c29903813eJake Slack        ServletHolder servlet_holder=(ServletHolder) baseRequest.getUserIdentityScope();
45803928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterChain chain=null;
45903928aee4356845252ac6b662d5c72c29903813eJake Slack
46003928aee4356845252ac6b662d5c72c29903813eJake Slack        // find the servlet
46103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (target.startsWith("/"))
46203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
46303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (servlet_holder!=null && _filterMappings!=null && _filterMappings.length>0)
46403928aee4356845252ac6b662d5c72c29903813eJake Slack                chain=getFilterChain(baseRequest, target, servlet_holder);
46503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
46603928aee4356845252ac6b662d5c72c29903813eJake Slack        else
46703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
46803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (servlet_holder!=null)
46903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
47003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_filterMappings!=null && _filterMappings.length>0)
47103928aee4356845252ac6b662d5c72c29903813eJake Slack                {
47203928aee4356845252ac6b662d5c72c29903813eJake Slack                    chain=getFilterChain(baseRequest, null,servlet_holder);
47303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
47403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
47503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
47603928aee4356845252ac6b662d5c72c29903813eJake Slack
47703928aee4356845252ac6b662d5c72c29903813eJake Slack        LOG.debug("chain={}",chain);
47803928aee4356845252ac6b662d5c72c29903813eJake Slack
47903928aee4356845252ac6b662d5c72c29903813eJake Slack        Throwable th=null;
48003928aee4356845252ac6b662d5c72c29903813eJake Slack        try
48103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
48203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (servlet_holder==null)
48303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
48403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (getHandler()==null)
48503928aee4356845252ac6b662d5c72c29903813eJake Slack                    notFound(request, response);
48603928aee4356845252ac6b662d5c72c29903813eJake Slack                else
48703928aee4356845252ac6b662d5c72c29903813eJake Slack                    nextHandle(target,baseRequest,request,response);
48803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
48903928aee4356845252ac6b662d5c72c29903813eJake Slack            else
49003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
49103928aee4356845252ac6b662d5c72c29903813eJake Slack                // unwrap any tunnelling of base Servlet request/responses
49203928aee4356845252ac6b662d5c72c29903813eJake Slack                ServletRequest req = request;
49303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (req instanceof ServletRequestHttpWrapper)
49403928aee4356845252ac6b662d5c72c29903813eJake Slack                    req = ((ServletRequestHttpWrapper)req).getRequest();
49503928aee4356845252ac6b662d5c72c29903813eJake Slack                ServletResponse res = response;
49603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (res instanceof ServletResponseHttpWrapper)
49703928aee4356845252ac6b662d5c72c29903813eJake Slack                    res = ((ServletResponseHttpWrapper)res).getResponse();
49803928aee4356845252ac6b662d5c72c29903813eJake Slack
49903928aee4356845252ac6b662d5c72c29903813eJake Slack                // Do the filter/handling thang
50003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (chain!=null)
50103928aee4356845252ac6b662d5c72c29903813eJake Slack                    chain.doFilter(req, res);
50203928aee4356845252ac6b662d5c72c29903813eJake Slack                else
50303928aee4356845252ac6b662d5c72c29903813eJake Slack                    servlet_holder.handle(baseRequest,req,res);
50403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
50503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
50603928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(EofException e)
50703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
50803928aee4356845252ac6b662d5c72c29903813eJake Slack            throw e;
50903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
51003928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(RuntimeIOException e)
51103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
51203928aee4356845252ac6b662d5c72c29903813eJake Slack            throw e;
51303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
51403928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(ContinuationThrowable e)
51503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
51603928aee4356845252ac6b662d5c72c29903813eJake Slack            throw e;
51703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
51803928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(Exception e)
51903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
52003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
52103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
52203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (e instanceof IOException)
52303928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw (IOException)e;
52403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (e instanceof RuntimeException)
52503928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw (RuntimeException)e;
52603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (e instanceof ServletException)
52703928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw (ServletException)e;
52803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
52903928aee4356845252ac6b662d5c72c29903813eJake Slack
53003928aee4356845252ac6b662d5c72c29903813eJake Slack            // unwrap cause
53103928aee4356845252ac6b662d5c72c29903813eJake Slack            th=e;
53203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (th instanceof UnavailableException)
53303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
53403928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug(th);
53503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
53603928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (th instanceof ServletException)
53703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
53803928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn(th);
53903928aee4356845252ac6b662d5c72c29903813eJake Slack                Throwable cause=((ServletException)th).getRootCause();
54003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (cause!=null)
54103928aee4356845252ac6b662d5c72c29903813eJake Slack                    th=cause;
54203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
54303928aee4356845252ac6b662d5c72c29903813eJake Slack
54403928aee4356845252ac6b662d5c72c29903813eJake Slack            // handle or log exception
54503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (th instanceof HttpException)
54603928aee4356845252ac6b662d5c72c29903813eJake Slack                throw (HttpException)th;
54703928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (th instanceof RuntimeIOException)
54803928aee4356845252ac6b662d5c72c29903813eJake Slack                throw (RuntimeIOException)th;
54903928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (th instanceof EofException)
55003928aee4356845252ac6b662d5c72c29903813eJake Slack                throw (EofException)th;
55103928aee4356845252ac6b662d5c72c29903813eJake Slack
55203928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (LOG.isDebugEnabled())
55303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
55403928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn(request.getRequestURI(), th);
55503928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug(request.toString());
55603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
55703928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (th instanceof IOException || th instanceof UnavailableException)
55803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
55903928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug(request.getRequestURI(),th);
56003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
56103928aee4356845252ac6b662d5c72c29903813eJake Slack            else
56203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
56303928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn(request.getRequestURI(),th);
56403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
56503928aee4356845252ac6b662d5c72c29903813eJake Slack
56603928aee4356845252ac6b662d5c72c29903813eJake Slack            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,th.getClass());
56703928aee4356845252ac6b662d5c72c29903813eJake Slack            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,th);
56803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!response.isCommitted())
56903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
57003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (th instanceof UnavailableException)
57103928aee4356845252ac6b662d5c72c29903813eJake Slack                {
57203928aee4356845252ac6b662d5c72c29903813eJake Slack                    UnavailableException ue = (UnavailableException)th;
57303928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (ue.isPermanent())
57403928aee4356845252ac6b662d5c72c29903813eJake Slack                        response.sendError(HttpServletResponse.SC_NOT_FOUND);
57503928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
57603928aee4356845252ac6b662d5c72c29903813eJake Slack                        response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
57703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
57803928aee4356845252ac6b662d5c72c29903813eJake Slack                else
57903928aee4356845252ac6b662d5c72c29903813eJake Slack                    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
58003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
58103928aee4356845252ac6b662d5c72c29903813eJake Slack            else
58203928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("Response already committed for handling "+th);
58303928aee4356845252ac6b662d5c72c29903813eJake Slack
58403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
58503928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(Error e)
58603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
58703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
58803928aee4356845252ac6b662d5c72c29903813eJake Slack                throw e;
58903928aee4356845252ac6b662d5c72c29903813eJake Slack            th=e;
59003928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn("Error for "+request.getRequestURI(),e);
59103928aee4356845252ac6b662d5c72c29903813eJake Slack            if(LOG.isDebugEnabled())LOG.debug(request.toString());
59203928aee4356845252ac6b662d5c72c29903813eJake Slack
59303928aee4356845252ac6b662d5c72c29903813eJake Slack            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,e.getClass());
59403928aee4356845252ac6b662d5c72c29903813eJake Slack            request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,e);
59503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!response.isCommitted())
59603928aee4356845252ac6b662d5c72c29903813eJake Slack                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
59703928aee4356845252ac6b662d5c72c29903813eJake Slack            else
59803928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("Response already committed for handling ",e);
59903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
60003928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
60103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
60203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (servlet_holder!=null)
60303928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setHandled(true);
60403928aee4356845252ac6b662d5c72c29903813eJake Slack
60503928aee4356845252ac6b662d5c72c29903813eJake Slack            // Complete async requests
60603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (th!=null && request.isAsyncStarted())
60703928aee4356845252ac6b662d5c72c29903813eJake Slack                ((AsyncContinuation)request.getAsyncContext()).errorComplete();
60803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
60903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
61003928aee4356845252ac6b662d5c72c29903813eJake Slack
61103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
61203928aee4356845252ac6b662d5c72c29903813eJake Slack    protected FilterChain getFilterChain(Request baseRequest, String pathInContext, ServletHolder servletHolder)
61303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
61403928aee4356845252ac6b662d5c72c29903813eJake Slack        String key=pathInContext==null?servletHolder.getName():pathInContext;
61503928aee4356845252ac6b662d5c72c29903813eJake Slack        int dispatch = FilterMapping.dispatch(baseRequest.getDispatcherType());
61603928aee4356845252ac6b662d5c72c29903813eJake Slack
61703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_filterChainsCached && _chainCache!=null)
61803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
61903928aee4356845252ac6b662d5c72c29903813eJake Slack            FilterChain chain = (FilterChain)_chainCache[dispatch].get(key);
62003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (chain!=null)
62103928aee4356845252ac6b662d5c72c29903813eJake Slack                return chain;
62203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
62303928aee4356845252ac6b662d5c72c29903813eJake Slack
62403928aee4356845252ac6b662d5c72c29903813eJake Slack        // Build list of filters
62503928aee4356845252ac6b662d5c72c29903813eJake Slack        Object filters= null;
62603928aee4356845252ac6b662d5c72c29903813eJake Slack        // Path filters
62703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (pathInContext!=null && _filterPathMappings!=null)
62803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
62903928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i= 0; i < _filterPathMappings.size(); i++)
63003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
63103928aee4356845252ac6b662d5c72c29903813eJake Slack                FilterMapping mapping = (FilterMapping)_filterPathMappings.get(i);
63203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (mapping.appliesTo(pathInContext, dispatch))
63303928aee4356845252ac6b662d5c72c29903813eJake Slack                    filters= LazyList.add(filters, mapping.getFilterHolder());
63403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
63503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
63603928aee4356845252ac6b662d5c72c29903813eJake Slack
63703928aee4356845252ac6b662d5c72c29903813eJake Slack        // Servlet name filters
63803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (servletHolder != null && _filterNameMappings!=null && _filterNameMappings.size() > 0)
63903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
64003928aee4356845252ac6b662d5c72c29903813eJake Slack            // Servlet name filters
64103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_filterNameMappings.size() > 0)
64203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
64303928aee4356845252ac6b662d5c72c29903813eJake Slack                Object o= _filterNameMappings.get(servletHolder.getName());
64403928aee4356845252ac6b662d5c72c29903813eJake Slack                for (int i=0; i<LazyList.size(o);i++)
64503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
64603928aee4356845252ac6b662d5c72c29903813eJake Slack                    FilterMapping mapping = (FilterMapping)LazyList.get(o,i);
64703928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (mapping.appliesTo(dispatch))
64803928aee4356845252ac6b662d5c72c29903813eJake Slack                        filters=LazyList.add(filters,mapping.getFilterHolder());
64903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
65003928aee4356845252ac6b662d5c72c29903813eJake Slack
65103928aee4356845252ac6b662d5c72c29903813eJake Slack                o= _filterNameMappings.get("*");
65203928aee4356845252ac6b662d5c72c29903813eJake Slack                for (int i=0; i<LazyList.size(o);i++)
65303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
65403928aee4356845252ac6b662d5c72c29903813eJake Slack                    FilterMapping mapping = (FilterMapping)LazyList.get(o,i);
65503928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (mapping.appliesTo(dispatch))
65603928aee4356845252ac6b662d5c72c29903813eJake Slack                        filters=LazyList.add(filters,mapping.getFilterHolder());
65703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
65803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
65903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
66003928aee4356845252ac6b662d5c72c29903813eJake Slack
66103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (filters==null)
66203928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
66303928aee4356845252ac6b662d5c72c29903813eJake Slack
66403928aee4356845252ac6b662d5c72c29903813eJake Slack
66503928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterChain chain = null;
66603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_filterChainsCached)
66703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
66803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LazyList.size(filters) > 0)
66903928aee4356845252ac6b662d5c72c29903813eJake Slack                chain= new CachedChain(filters, servletHolder);
67003928aee4356845252ac6b662d5c72c29903813eJake Slack
67103928aee4356845252ac6b662d5c72c29903813eJake Slack            final Map<String,FilterChain> cache=_chainCache[dispatch];
67203928aee4356845252ac6b662d5c72c29903813eJake Slack            final Queue<String> lru=_chainLRU[dispatch];
67303928aee4356845252ac6b662d5c72c29903813eJake Slack
67403928aee4356845252ac6b662d5c72c29903813eJake Slack        	// Do we have too many cached chains?
67503928aee4356845252ac6b662d5c72c29903813eJake Slack        	while (_maxFilterChainsCacheSize>0 && cache.size()>=_maxFilterChainsCacheSize)
67603928aee4356845252ac6b662d5c72c29903813eJake Slack        	{
67703928aee4356845252ac6b662d5c72c29903813eJake Slack        	    // The LRU list is not atomic with the cache map, so be prepared to invalidate if
67803928aee4356845252ac6b662d5c72c29903813eJake Slack        	    // a key is not found to delete.
67903928aee4356845252ac6b662d5c72c29903813eJake Slack        	    // Delete by LRU (where U==created)
68003928aee4356845252ac6b662d5c72c29903813eJake Slack        	    String k=lru.poll();
68103928aee4356845252ac6b662d5c72c29903813eJake Slack        	    if (k==null)
68203928aee4356845252ac6b662d5c72c29903813eJake Slack        	    {
68303928aee4356845252ac6b662d5c72c29903813eJake Slack        	        cache.clear();
68403928aee4356845252ac6b662d5c72c29903813eJake Slack        	        break;
68503928aee4356845252ac6b662d5c72c29903813eJake Slack        	    }
68603928aee4356845252ac6b662d5c72c29903813eJake Slack        	    cache.remove(k);
68703928aee4356845252ac6b662d5c72c29903813eJake Slack        	}
68803928aee4356845252ac6b662d5c72c29903813eJake Slack
68903928aee4356845252ac6b662d5c72c29903813eJake Slack        	cache.put(key,chain);
69003928aee4356845252ac6b662d5c72c29903813eJake Slack        	lru.add(key);
69103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
69203928aee4356845252ac6b662d5c72c29903813eJake Slack        else if (LazyList.size(filters) > 0)
69303928aee4356845252ac6b662d5c72c29903813eJake Slack            chain = new Chain(baseRequest,filters, servletHolder);
69403928aee4356845252ac6b662d5c72c29903813eJake Slack
69503928aee4356845252ac6b662d5c72c29903813eJake Slack        return chain;
69603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
69703928aee4356845252ac6b662d5c72c29903813eJake Slack
69803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
69903928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void invalidateChainsCache()
70003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
70103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_chainLRU[FilterMapping.REQUEST]!=null)
70203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
70303928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainLRU[FilterMapping.REQUEST].clear();
70403928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainLRU[FilterMapping.FORWARD].clear();
70503928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainLRU[FilterMapping.INCLUDE].clear();
70603928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainLRU[FilterMapping.ERROR].clear();
70703928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainLRU[FilterMapping.ASYNC].clear();
70803928aee4356845252ac6b662d5c72c29903813eJake Slack
70903928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainCache[FilterMapping.REQUEST].clear();
71003928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainCache[FilterMapping.FORWARD].clear();
71103928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainCache[FilterMapping.INCLUDE].clear();
71203928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainCache[FilterMapping.ERROR].clear();
71303928aee4356845252ac6b662d5c72c29903813eJake Slack            _chainCache[FilterMapping.ASYNC].clear();
71403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
71503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
71603928aee4356845252ac6b662d5c72c29903813eJake Slack
71703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
71803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
71903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return true if the handler is started and there are no unavailable servlets
72003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
72103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isAvailable()
72203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
72303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!isStarted())
72403928aee4356845252ac6b662d5c72c29903813eJake Slack            return false;
72503928aee4356845252ac6b662d5c72c29903813eJake Slack        ServletHolder[] holders = getServlets();
72603928aee4356845252ac6b662d5c72c29903813eJake Slack        for (int i=0;i<holders.length;i++)
72703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
72803928aee4356845252ac6b662d5c72c29903813eJake Slack            ServletHolder holder = holders[i];
72903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (holder!=null && !holder.isAvailable())
73003928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
73103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
73203928aee4356845252ac6b662d5c72c29903813eJake Slack        return true;
73303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
73403928aee4356845252ac6b662d5c72c29903813eJake Slack
73503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
73603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
73703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param start True if this handler will start with unavailable servlets
73803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
73903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setStartWithUnavailable(boolean start)
74003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
74103928aee4356845252ac6b662d5c72c29903813eJake Slack        _startWithUnavailable=start;
74203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
74303928aee4356845252ac6b662d5c72c29903813eJake Slack
74403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
74503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
74603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return True if this handler will start with unavailable servlets
74703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
74803928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isStartWithUnavailable()
74903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
75003928aee4356845252ac6b662d5c72c29903813eJake Slack        return _startWithUnavailable;
75103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
75203928aee4356845252ac6b662d5c72c29903813eJake Slack
75303928aee4356845252ac6b662d5c72c29903813eJake Slack
75403928aee4356845252ac6b662d5c72c29903813eJake Slack
75503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
75603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Initialize filters and load-on-startup servlets.
75703928aee4356845252ac6b662d5c72c29903813eJake Slack     * Called automatically from start if autoInitializeServlet is true.
75803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
75903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void initialize()
76003928aee4356845252ac6b662d5c72c29903813eJake Slack        throws Exception
76103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
76203928aee4356845252ac6b662d5c72c29903813eJake Slack        MultiException mx = new MultiException();
76303928aee4356845252ac6b662d5c72c29903813eJake Slack
76403928aee4356845252ac6b662d5c72c29903813eJake Slack        // Start filters
76503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_filters!=null)
76603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
76703928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=0;i<_filters.length; i++)
76803928aee4356845252ac6b662d5c72c29903813eJake Slack                _filters[i].start();
76903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
77003928aee4356845252ac6b662d5c72c29903813eJake Slack
77103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_servlets!=null)
77203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
77303928aee4356845252ac6b662d5c72c29903813eJake Slack            // Sort and Initialize servlets
77403928aee4356845252ac6b662d5c72c29903813eJake Slack            ServletHolder[] servlets = (ServletHolder[])_servlets.clone();
77503928aee4356845252ac6b662d5c72c29903813eJake Slack            Arrays.sort(servlets);
77603928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=0; i<servlets.length; i++)
77703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
77803928aee4356845252ac6b662d5c72c29903813eJake Slack                try
77903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
78003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (servlets[i].getClassName()==null && servlets[i].getForcedPath()!=null)
78103928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
78203928aee4356845252ac6b662d5c72c29903813eJake Slack                        ServletHolder forced_holder = (ServletHolder)_servletPathMap.match(servlets[i].getForcedPath());
78303928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (forced_holder==null || forced_holder.getClassName()==null)
78403928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
78503928aee4356845252ac6b662d5c72c29903813eJake Slack                            mx.add(new IllegalStateException("No forced path servlet for "+servlets[i].getForcedPath()));
78603928aee4356845252ac6b662d5c72c29903813eJake Slack                            continue;
78703928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
78803928aee4356845252ac6b662d5c72c29903813eJake Slack                        servlets[i].setClassName(forced_holder.getClassName());
78903928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
79003928aee4356845252ac6b662d5c72c29903813eJake Slack
79103928aee4356845252ac6b662d5c72c29903813eJake Slack                    servlets[i].start();
79203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
79303928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(Throwable e)
79403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
79503928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.debug(Log.EXCEPTION,e);
79603928aee4356845252ac6b662d5c72c29903813eJake Slack                    mx.add(e);
79703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
79803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
79903928aee4356845252ac6b662d5c72c29903813eJake Slack            mx.ifExceptionThrow();
80003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
80103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
80203928aee4356845252ac6b662d5c72c29903813eJake Slack
80303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
80403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
80503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the filterChainsCached.
80603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
80703928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isFilterChainsCached()
80803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
80903928aee4356845252ac6b662d5c72c29903813eJake Slack        return _filterChainsCached;
81003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
81103928aee4356845252ac6b662d5c72c29903813eJake Slack
81203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
81303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
81403928aee4356845252ac6b662d5c72c29903813eJake Slack     * see also newServletHolder(Class)
81503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
81603928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletHolder newServletHolder(Holder.Source source)
81703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
81803928aee4356845252ac6b662d5c72c29903813eJake Slack        return new ServletHolder(source);
81903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
82003928aee4356845252ac6b662d5c72c29903813eJake Slack
82103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
82203928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a servlet Holder.
82303928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletHolder newServletHolder(Class<? extends Servlet> servlet)
82403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
82503928aee4356845252ac6b662d5c72c29903813eJake Slack        return new ServletHolder(servlet);
82603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
82703928aee4356845252ac6b662d5c72c29903813eJake Slack
82803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
82903928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a servlet.
83003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The servlet holder.
83103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
83203928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletHolder addServletWithMapping (String className,String pathSpec)
83303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
83403928aee4356845252ac6b662d5c72c29903813eJake Slack        ServletHolder holder = newServletHolder(Holder.Source.EMBEDDED);
83503928aee4356845252ac6b662d5c72c29903813eJake Slack        holder.setClassName(className);
83603928aee4356845252ac6b662d5c72c29903813eJake Slack        addServletWithMapping(holder,pathSpec);
83703928aee4356845252ac6b662d5c72c29903813eJake Slack        return holder;
83803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
83903928aee4356845252ac6b662d5c72c29903813eJake Slack
84003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
84103928aee4356845252ac6b662d5c72c29903813eJake Slack    /** conveniance method to add a servlet.
84203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The servlet holder.
84303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
84403928aee4356845252ac6b662d5c72c29903813eJake Slack    public ServletHolder addServletWithMapping (Class<? extends Servlet> servlet,String pathSpec)
84503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
84603928aee4356845252ac6b662d5c72c29903813eJake Slack        ServletHolder holder = newServletHolder(Holder.Source.EMBEDDED);
84703928aee4356845252ac6b662d5c72c29903813eJake Slack        holder.setHeldClass(servlet);
84803928aee4356845252ac6b662d5c72c29903813eJake Slack        //DUPLICATES adding servlet from addServletWithMapping(holder, pathSpec)?
84903928aee4356845252ac6b662d5c72c29903813eJake Slack        //setServlets((ServletHolder[])LazyList.addToArray(getServlets(), holder, ServletHolder.class));
85003928aee4356845252ac6b662d5c72c29903813eJake Slack        addServletWithMapping(holder,pathSpec);
85103928aee4356845252ac6b662d5c72c29903813eJake Slack
85203928aee4356845252ac6b662d5c72c29903813eJake Slack        return holder;
85303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
85403928aee4356845252ac6b662d5c72c29903813eJake Slack
85503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
85603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** conveniance method to add a servlet.
85703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param servlet servlet holder to add
85803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pathSpec servlet mappings for the servletHolder
85903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
86003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addServletWithMapping (ServletHolder servlet,String pathSpec)
86103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
86203928aee4356845252ac6b662d5c72c29903813eJake Slack        ServletHolder[] holders=getServlets();
86303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (holders!=null)
86403928aee4356845252ac6b662d5c72c29903813eJake Slack            holders = holders.clone();
86503928aee4356845252ac6b662d5c72c29903813eJake Slack
86603928aee4356845252ac6b662d5c72c29903813eJake Slack        try
86703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
86803928aee4356845252ac6b662d5c72c29903813eJake Slack            setServlets((ServletHolder[])LazyList.addToArray(holders, servlet, ServletHolder.class));
86903928aee4356845252ac6b662d5c72c29903813eJake Slack
87003928aee4356845252ac6b662d5c72c29903813eJake Slack            ServletMapping mapping = new ServletMapping();
87103928aee4356845252ac6b662d5c72c29903813eJake Slack            mapping.setServletName(servlet.getName());
87203928aee4356845252ac6b662d5c72c29903813eJake Slack            mapping.setPathSpec(pathSpec);
87303928aee4356845252ac6b662d5c72c29903813eJake Slack            setServletMappings((ServletMapping[])LazyList.addToArray(getServletMappings(), mapping, ServletMapping.class));
87403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
87503928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (Exception e)
87603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
87703928aee4356845252ac6b662d5c72c29903813eJake Slack            setServlets(holders);
87803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (e instanceof RuntimeException)
87903928aee4356845252ac6b662d5c72c29903813eJake Slack                throw (RuntimeException)e;
88003928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new RuntimeException(e);
88103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
88203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
88303928aee4356845252ac6b662d5c72c29903813eJake Slack
88403928aee4356845252ac6b662d5c72c29903813eJake Slack
88503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
88603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**Convenience method to add a pre-constructed ServletHolder.
88703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param holder
88803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
88903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addServlet(ServletHolder holder)
89003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
89103928aee4356845252ac6b662d5c72c29903813eJake Slack        setServlets((ServletHolder[])LazyList.addToArray(getServlets(), holder, ServletHolder.class));
89203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
89303928aee4356845252ac6b662d5c72c29903813eJake Slack
89403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
89503928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a pre-constructed ServletMapping.
89603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param mapping
89703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
89803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addServletMapping (ServletMapping mapping)
89903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
90003928aee4356845252ac6b662d5c72c29903813eJake Slack        setServletMappings((ServletMapping[])LazyList.addToArray(getServletMappings(), mapping, ServletMapping.class));
90103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
90203928aee4356845252ac6b662d5c72c29903813eJake Slack
90303928aee4356845252ac6b662d5c72c29903813eJake Slack    public Set<String>  setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement) {
90403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_contextHandler != null) {
90503928aee4356845252ac6b662d5c72c29903813eJake Slack            return _contextHandler.setServletSecurity(registration, servletSecurityElement);
90603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
90703928aee4356845252ac6b662d5c72c29903813eJake Slack        return Collections.emptySet();
90803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
90903928aee4356845252ac6b662d5c72c29903813eJake Slack
91003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
91103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
91203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see #newFilterHolder(Class)
91303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
91403928aee4356845252ac6b662d5c72c29903813eJake Slack    public FilterHolder newFilterHolder(Holder.Source source)
91503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
91603928aee4356845252ac6b662d5c72c29903813eJake Slack        return new FilterHolder(source);
91703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
91803928aee4356845252ac6b662d5c72c29903813eJake Slack
91903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
92003928aee4356845252ac6b662d5c72c29903813eJake Slack    public FilterHolder getFilter(String name)
92103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
92203928aee4356845252ac6b662d5c72c29903813eJake Slack        return (FilterHolder)_filterNameMap.get(name);
92303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
92403928aee4356845252ac6b662d5c72c29903813eJake Slack
92503928aee4356845252ac6b662d5c72c29903813eJake Slack
92603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
92703928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a filter.
92803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param filter  class of filter to create
92903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pathSpec filter mappings for filter
93003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param dispatches see {@link FilterMapping#setDispatches(int)}
93103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The filter holder.
93203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
93303928aee4356845252ac6b662d5c72c29903813eJake Slack    public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,EnumSet<DispatcherType> dispatches)
93403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
93503928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
93603928aee4356845252ac6b662d5c72c29903813eJake Slack        holder.setHeldClass(filter);
93703928aee4356845252ac6b662d5c72c29903813eJake Slack        addFilterWithMapping(holder,pathSpec,dispatches);
93803928aee4356845252ac6b662d5c72c29903813eJake Slack
93903928aee4356845252ac6b662d5c72c29903813eJake Slack        return holder;
94003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
94103928aee4356845252ac6b662d5c72c29903813eJake Slack
94203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
94303928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a filter.
94403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param className of filter
94503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pathSpec filter mappings for filter
94603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param dispatches see {@link FilterMapping#setDispatches(int)}
94703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The filter holder.
94803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
94903928aee4356845252ac6b662d5c72c29903813eJake Slack    public FilterHolder addFilterWithMapping (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
95003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
95103928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
95203928aee4356845252ac6b662d5c72c29903813eJake Slack        holder.setClassName(className);
95303928aee4356845252ac6b662d5c72c29903813eJake Slack
95403928aee4356845252ac6b662d5c72c29903813eJake Slack        addFilterWithMapping(holder,pathSpec,dispatches);
95503928aee4356845252ac6b662d5c72c29903813eJake Slack        return holder;
95603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
95703928aee4356845252ac6b662d5c72c29903813eJake Slack
95803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
95903928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a filter.
96003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param holder filter holder to add
96103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pathSpec filter mappings for filter
96203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param dispatches see {@link FilterMapping#setDispatches(int)}
96303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
96403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addFilterWithMapping (FilterHolder holder,String pathSpec,EnumSet<DispatcherType> dispatches)
96503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
96603928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterHolder[] holders = getFilters();
96703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (holders!=null)
96803928aee4356845252ac6b662d5c72c29903813eJake Slack            holders = (FilterHolder[])holders.clone();
96903928aee4356845252ac6b662d5c72c29903813eJake Slack
97003928aee4356845252ac6b662d5c72c29903813eJake Slack        try
97103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
97203928aee4356845252ac6b662d5c72c29903813eJake Slack            setFilters((FilterHolder[])LazyList.addToArray(holders, holder, FilterHolder.class));
97303928aee4356845252ac6b662d5c72c29903813eJake Slack
97403928aee4356845252ac6b662d5c72c29903813eJake Slack            FilterMapping mapping = new FilterMapping();
97503928aee4356845252ac6b662d5c72c29903813eJake Slack            mapping.setFilterName(holder.getName());
97603928aee4356845252ac6b662d5c72c29903813eJake Slack            mapping.setPathSpec(pathSpec);
97703928aee4356845252ac6b662d5c72c29903813eJake Slack            mapping.setDispatcherTypes(dispatches);
97803928aee4356845252ac6b662d5c72c29903813eJake Slack            //setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), mapping, FilterMapping.class));
97903928aee4356845252ac6b662d5c72c29903813eJake Slack            addFilterMapping(mapping);
98003928aee4356845252ac6b662d5c72c29903813eJake Slack
98103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
98203928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (RuntimeException e)
98303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
98403928aee4356845252ac6b662d5c72c29903813eJake Slack            setFilters(holders);
98503928aee4356845252ac6b662d5c72c29903813eJake Slack            throw e;
98603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
98703928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (Error e)
98803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
98903928aee4356845252ac6b662d5c72c29903813eJake Slack            setFilters(holders);
99003928aee4356845252ac6b662d5c72c29903813eJake Slack            throw e;
99103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
99203928aee4356845252ac6b662d5c72c29903813eJake Slack
99303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
99403928aee4356845252ac6b662d5c72c29903813eJake Slack
99503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
99603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a filter.
99703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param filter  class of filter to create
99803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pathSpec filter mappings for filter
99903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param dispatches see {@link FilterMapping#setDispatches(int)}
100003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The filter holder.
100103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
100203928aee4356845252ac6b662d5c72c29903813eJake Slack    public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,int dispatches)
100303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
100403928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
100503928aee4356845252ac6b662d5c72c29903813eJake Slack        holder.setHeldClass(filter);
100603928aee4356845252ac6b662d5c72c29903813eJake Slack        addFilterWithMapping(holder,pathSpec,dispatches);
100703928aee4356845252ac6b662d5c72c29903813eJake Slack
100803928aee4356845252ac6b662d5c72c29903813eJake Slack        return holder;
100903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
101003928aee4356845252ac6b662d5c72c29903813eJake Slack
101103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
101203928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a filter.
101303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param className of filter
101403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pathSpec filter mappings for filter
101503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param dispatches see {@link FilterMapping#setDispatches(int)}
101603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The filter holder.
101703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
101803928aee4356845252ac6b662d5c72c29903813eJake Slack    public FilterHolder addFilterWithMapping (String className,String pathSpec,int dispatches)
101903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
102003928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
102103928aee4356845252ac6b662d5c72c29903813eJake Slack        holder.setClassName(className);
102203928aee4356845252ac6b662d5c72c29903813eJake Slack
102303928aee4356845252ac6b662d5c72c29903813eJake Slack        addFilterWithMapping(holder,pathSpec,dispatches);
102403928aee4356845252ac6b662d5c72c29903813eJake Slack        return holder;
102503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
102603928aee4356845252ac6b662d5c72c29903813eJake Slack
102703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
102803928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a filter.
102903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param holder filter holder to add
103003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pathSpec filter mappings for filter
103103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param dispatches see {@link FilterMapping#setDispatches(int)}
103203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
103303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addFilterWithMapping (FilterHolder holder,String pathSpec,int dispatches)
103403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
103503928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterHolder[] holders = getFilters();
103603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (holders!=null)
103703928aee4356845252ac6b662d5c72c29903813eJake Slack            holders = (FilterHolder[])holders.clone();
103803928aee4356845252ac6b662d5c72c29903813eJake Slack
103903928aee4356845252ac6b662d5c72c29903813eJake Slack        try
104003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
104103928aee4356845252ac6b662d5c72c29903813eJake Slack            setFilters((FilterHolder[])LazyList.addToArray(holders, holder, FilterHolder.class));
104203928aee4356845252ac6b662d5c72c29903813eJake Slack
104303928aee4356845252ac6b662d5c72c29903813eJake Slack            FilterMapping mapping = new FilterMapping();
104403928aee4356845252ac6b662d5c72c29903813eJake Slack            mapping.setFilterName(holder.getName());
104503928aee4356845252ac6b662d5c72c29903813eJake Slack            mapping.setPathSpec(pathSpec);
104603928aee4356845252ac6b662d5c72c29903813eJake Slack            mapping.setDispatches(dispatches);
104703928aee4356845252ac6b662d5c72c29903813eJake Slack            //setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), mapping, FilterMapping.class));
104803928aee4356845252ac6b662d5c72c29903813eJake Slack            addFilterMapping(mapping);
104903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
105003928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (RuntimeException e)
105103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
105203928aee4356845252ac6b662d5c72c29903813eJake Slack            setFilters(holders);
105303928aee4356845252ac6b662d5c72c29903813eJake Slack            throw e;
105403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
105503928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (Error e)
105603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
105703928aee4356845252ac6b662d5c72c29903813eJake Slack            setFilters(holders);
105803928aee4356845252ac6b662d5c72c29903813eJake Slack            throw e;
105903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
106003928aee4356845252ac6b662d5c72c29903813eJake Slack
106103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
106203928aee4356845252ac6b662d5c72c29903813eJake Slack
106303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
106403928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a filter with a mapping
106503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param className
106603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pathSpec
106703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param dispatches
106803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return the filter holder created
106903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @deprecated use {@link #addFilterWithMapping(Class, String, EnumSet<DispatcherType>)} instead
107003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
107103928aee4356845252ac6b662d5c72c29903813eJake Slack    public FilterHolder addFilter (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
107203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
107303928aee4356845252ac6b662d5c72c29903813eJake Slack        return addFilterWithMapping(className, pathSpec, dispatches);
107403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
107503928aee4356845252ac6b662d5c72c29903813eJake Slack
107603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
107703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
107803928aee4356845252ac6b662d5c72c29903813eJake Slack     * convenience method to add a filter and mapping
107903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param filter
108003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param filterMapping
108103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
108203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addFilter (FilterHolder filter, FilterMapping filterMapping)
108303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
108403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (filter != null)
108503928aee4356845252ac6b662d5c72c29903813eJake Slack            setFilters((FilterHolder[])LazyList.addToArray(getFilters(), filter, FilterHolder.class));
108603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (filterMapping != null)
108703928aee4356845252ac6b662d5c72c29903813eJake Slack            //setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), filterMapping, FilterMapping.class));
108803928aee4356845252ac6b662d5c72c29903813eJake Slack            addFilterMapping(filterMapping);
108903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
109003928aee4356845252ac6b662d5c72c29903813eJake Slack
109103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
109203928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a preconstructed FilterHolder
109303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param filter
109403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
109503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addFilter (FilterHolder filter)
109603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
109703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (filter != null)
109803928aee4356845252ac6b662d5c72c29903813eJake Slack            setFilters((FilterHolder[])LazyList.addToArray(getFilters(), filter, FilterHolder.class));
109903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
110003928aee4356845252ac6b662d5c72c29903813eJake Slack
110103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
110203928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a preconstructed FilterMapping
110303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param mapping
110403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
110503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addFilterMapping (FilterMapping mapping)
110603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
110703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (mapping != null)
110803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
110903928aee4356845252ac6b662d5c72c29903813eJake Slack            Source source = (mapping.getFilterHolder()==null?null:mapping.getFilterHolder().getSource());
111003928aee4356845252ac6b662d5c72c29903813eJake Slack            FilterMapping[] mappings =getFilterMappings();
111103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (mappings==null || mappings.length==0)
111203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
111303928aee4356845252ac6b662d5c72c29903813eJake Slack                setFilterMappings(insertFilterMapping(mapping,0,false));
111403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (source != null && source == Source.JAVAX_API)
111503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _matchAfterIndex = 0;
111603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
111703928aee4356845252ac6b662d5c72c29903813eJake Slack            else
111803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
111903928aee4356845252ac6b662d5c72c29903813eJake Slack                //there are existing entries. If this is a programmatic filtermapping, it is added at the end of the list.
112003928aee4356845252ac6b662d5c72c29903813eJake Slack                //If this is a normal filtermapping, it is inserted after all the other filtermappings (matchBefores and normals),
112103928aee4356845252ac6b662d5c72c29903813eJake Slack                //but before the first matchAfter filtermapping.
112203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (source != null && Source.JAVAX_API == source)
112303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
112403928aee4356845252ac6b662d5c72c29903813eJake Slack                    setFilterMappings(insertFilterMapping(mapping,mappings.length-1, false));
112503928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_matchAfterIndex < 0)
112603928aee4356845252ac6b662d5c72c29903813eJake Slack                        _matchAfterIndex = getFilterMappings().length-1;
112703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
112803928aee4356845252ac6b662d5c72c29903813eJake Slack                else
112903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
113003928aee4356845252ac6b662d5c72c29903813eJake Slack                    //insert non-programmatic filter mappings before any matchAfters, if any
113103928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_matchAfterIndex < 0)
113203928aee4356845252ac6b662d5c72c29903813eJake Slack                        setFilterMappings(insertFilterMapping(mapping,mappings.length-1, false));
113303928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
113403928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
113503928aee4356845252ac6b662d5c72c29903813eJake Slack                        FilterMapping[] new_mappings = insertFilterMapping(mapping, _matchAfterIndex, true);
113603928aee4356845252ac6b662d5c72c29903813eJake Slack                        ++_matchAfterIndex;
113703928aee4356845252ac6b662d5c72c29903813eJake Slack                        setFilterMappings(new_mappings);
113803928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
113903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
114003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
114103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
114203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
114303928aee4356845252ac6b662d5c72c29903813eJake Slack
114403928aee4356845252ac6b662d5c72c29903813eJake Slack
114503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
114603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Convenience method to add a preconstructed FilterMapping
114703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param mapping
114803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
114903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void prependFilterMapping (FilterMapping mapping)
115003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
115103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (mapping != null)
115203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
115303928aee4356845252ac6b662d5c72c29903813eJake Slack            Source source = mapping.getFilterHolder().getSource();
115403928aee4356845252ac6b662d5c72c29903813eJake Slack
115503928aee4356845252ac6b662d5c72c29903813eJake Slack            FilterMapping[] mappings = getFilterMappings();
115603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (mappings==null || mappings.length==0)
115703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
115803928aee4356845252ac6b662d5c72c29903813eJake Slack                setFilterMappings(insertFilterMapping(mapping, 0, false));
115903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (source != null && Source.JAVAX_API == source)
116003928aee4356845252ac6b662d5c72c29903813eJake Slack                    _matchBeforeIndex = 0;
116103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
116203928aee4356845252ac6b662d5c72c29903813eJake Slack            else
116303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
116403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (source != null && Source.JAVAX_API == source)
116503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
116603928aee4356845252ac6b662d5c72c29903813eJake Slack                    //programmatically defined filter mappings are prepended to mapping list in the order
116703928aee4356845252ac6b662d5c72c29903813eJake Slack                    //in which they were defined. In other words, insert this mapping at the tail of the
116803928aee4356845252ac6b662d5c72c29903813eJake Slack                    //programmatically prepended filter mappings, BEFORE the first web.xml defined filter mapping.
116903928aee4356845252ac6b662d5c72c29903813eJake Slack
117003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_matchBeforeIndex < 0)
117103928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
117203928aee4356845252ac6b662d5c72c29903813eJake Slack                        //no programmatically defined prepended filter mappings yet, prepend this one
117303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _matchBeforeIndex = 0;
117403928aee4356845252ac6b662d5c72c29903813eJake Slack                        FilterMapping[] new_mappings = insertFilterMapping(mapping, 0, true);
117503928aee4356845252ac6b662d5c72c29903813eJake Slack                        setFilterMappings(new_mappings);
117603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
117703928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
117803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
117903928aee4356845252ac6b662d5c72c29903813eJake Slack                        FilterMapping[] new_mappings = insertFilterMapping(mapping,_matchBeforeIndex, false);
118003928aee4356845252ac6b662d5c72c29903813eJake Slack                        ++_matchBeforeIndex;
118103928aee4356845252ac6b662d5c72c29903813eJake Slack                        setFilterMappings(new_mappings);
118203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
118303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
118403928aee4356845252ac6b662d5c72c29903813eJake Slack                else
118503928aee4356845252ac6b662d5c72c29903813eJake Slack                {
118603928aee4356845252ac6b662d5c72c29903813eJake Slack                    //non programmatically defined, just prepend to list
118703928aee4356845252ac6b662d5c72c29903813eJake Slack                    FilterMapping[] new_mappings = insertFilterMapping(mapping, 0, true);
118803928aee4356845252ac6b662d5c72c29903813eJake Slack                    setFilterMappings(new_mappings);
118903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
119003928aee4356845252ac6b662d5c72c29903813eJake Slack
119103928aee4356845252ac6b662d5c72c29903813eJake Slack                //adjust matchAfterIndex ptr to take account of the mapping we just prepended
119203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_matchAfterIndex >= 0)
119303928aee4356845252ac6b662d5c72c29903813eJake Slack                    ++_matchAfterIndex;
119403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
119503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
119603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
119703928aee4356845252ac6b662d5c72c29903813eJake Slack
119803928aee4356845252ac6b662d5c72c29903813eJake Slack
119903928aee4356845252ac6b662d5c72c29903813eJake Slack
120003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
120103928aee4356845252ac6b662d5c72c29903813eJake Slack     * Insert a filtermapping in the list
120203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param mapping the FilterMapping to add
120303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pos the position in the existing arry at which to add it
120403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param before if true, insert before  pos, if false insert after it
120503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return
120603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
120703928aee4356845252ac6b662d5c72c29903813eJake Slack    protected FilterMapping[] insertFilterMapping (FilterMapping mapping, int pos, boolean before)
120803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
120903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (pos < 0)
121003928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalArgumentException("FilterMapping insertion pos < 0");
121103928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterMapping[] mappings = getFilterMappings();
121203928aee4356845252ac6b662d5c72c29903813eJake Slack
121303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (mappings==null || mappings.length==0)
121403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
121503928aee4356845252ac6b662d5c72c29903813eJake Slack            return new FilterMapping[] {mapping};
121603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
121703928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterMapping[] new_mappings = new FilterMapping[mappings.length+1];
121803928aee4356845252ac6b662d5c72c29903813eJake Slack
121903928aee4356845252ac6b662d5c72c29903813eJake Slack
122003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (before)
122103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
122203928aee4356845252ac6b662d5c72c29903813eJake Slack            //copy existing filter mappings up to but not including the pos
122303928aee4356845252ac6b662d5c72c29903813eJake Slack            System.arraycopy(mappings,0,new_mappings,0,pos);
122403928aee4356845252ac6b662d5c72c29903813eJake Slack
122503928aee4356845252ac6b662d5c72c29903813eJake Slack            //add in the new mapping
122603928aee4356845252ac6b662d5c72c29903813eJake Slack            new_mappings[pos] = mapping;
122703928aee4356845252ac6b662d5c72c29903813eJake Slack
122803928aee4356845252ac6b662d5c72c29903813eJake Slack            //copy the old pos mapping and any remaining existing mappings
122903928aee4356845252ac6b662d5c72c29903813eJake Slack            System.arraycopy(mappings,pos,new_mappings,pos+1, mappings.length-pos);
123003928aee4356845252ac6b662d5c72c29903813eJake Slack
123103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
123203928aee4356845252ac6b662d5c72c29903813eJake Slack        else
123303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
123403928aee4356845252ac6b662d5c72c29903813eJake Slack            //copy existing filter mappings up to and including the pos
123503928aee4356845252ac6b662d5c72c29903813eJake Slack            System.arraycopy(mappings,0,new_mappings,0,pos+1);
123603928aee4356845252ac6b662d5c72c29903813eJake Slack            //add in the new mapping after the pos
123703928aee4356845252ac6b662d5c72c29903813eJake Slack            new_mappings[pos+1] = mapping;
123803928aee4356845252ac6b662d5c72c29903813eJake Slack
123903928aee4356845252ac6b662d5c72c29903813eJake Slack            //copy the remaining existing mappings
124003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (mappings.length > pos+1)
124103928aee4356845252ac6b662d5c72c29903813eJake Slack                System.arraycopy(mappings,pos+1,new_mappings,pos+2, mappings.length-(pos+1));
124203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
124303928aee4356845252ac6b662d5c72c29903813eJake Slack        return new_mappings;
124403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
124503928aee4356845252ac6b662d5c72c29903813eJake Slack
124603928aee4356845252ac6b662d5c72c29903813eJake Slack
124703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
124803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected synchronized void updateNameMappings()
124903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
125003928aee4356845252ac6b662d5c72c29903813eJake Slack        // update filter name map
125103928aee4356845252ac6b662d5c72c29903813eJake Slack        _filterNameMap.clear();
125203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_filters!=null)
125303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
125403928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=0;i<_filters.length;i++)
125503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
125603928aee4356845252ac6b662d5c72c29903813eJake Slack                _filterNameMap.put(_filters[i].getName(),_filters[i]);
125703928aee4356845252ac6b662d5c72c29903813eJake Slack                _filters[i].setServletHandler(this);
125803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
125903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
126003928aee4356845252ac6b662d5c72c29903813eJake Slack
126103928aee4356845252ac6b662d5c72c29903813eJake Slack        // Map servlet names to holders
126203928aee4356845252ac6b662d5c72c29903813eJake Slack        _servletNameMap.clear();
126303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_servlets!=null)
126403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
126503928aee4356845252ac6b662d5c72c29903813eJake Slack            // update the maps
126603928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=0;i<_servlets.length;i++)
126703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
126803928aee4356845252ac6b662d5c72c29903813eJake Slack                _servletNameMap.put(_servlets[i].getName(),_servlets[i]);
126903928aee4356845252ac6b662d5c72c29903813eJake Slack                _servlets[i].setServletHandler(this);
127003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
127103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
127203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
127303928aee4356845252ac6b662d5c72c29903813eJake Slack
127403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
127503928aee4356845252ac6b662d5c72c29903813eJake Slack    protected synchronized void updateMappings()
127603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
127703928aee4356845252ac6b662d5c72c29903813eJake Slack        // update filter mappings
127803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_filterMappings==null)
127903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
128003928aee4356845252ac6b662d5c72c29903813eJake Slack            _filterPathMappings=null;
128103928aee4356845252ac6b662d5c72c29903813eJake Slack            _filterNameMappings=null;
128203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
128303928aee4356845252ac6b662d5c72c29903813eJake Slack        else
128403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
128503928aee4356845252ac6b662d5c72c29903813eJake Slack            _filterPathMappings=new ArrayList();
128603928aee4356845252ac6b662d5c72c29903813eJake Slack            _filterNameMappings=new MultiMap();
128703928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=0;i<_filterMappings.length;i++)
128803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
128903928aee4356845252ac6b662d5c72c29903813eJake Slack                FilterHolder filter_holder = (FilterHolder)_filterNameMap.get(_filterMappings[i].getFilterName());
129003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (filter_holder==null)
129103928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException("No filter named "+_filterMappings[i].getFilterName());
129203928aee4356845252ac6b662d5c72c29903813eJake Slack                _filterMappings[i].setFilterHolder(filter_holder);
129303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_filterMappings[i].getPathSpecs()!=null)
129403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _filterPathMappings.add(_filterMappings[i]);
129503928aee4356845252ac6b662d5c72c29903813eJake Slack
129603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_filterMappings[i].getServletNames()!=null)
129703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
129803928aee4356845252ac6b662d5c72c29903813eJake Slack                    String[] names=_filterMappings[i].getServletNames();
129903928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int j=0;j<names.length;j++)
130003928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
130103928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (names[j]!=null)
130203928aee4356845252ac6b662d5c72c29903813eJake Slack                            _filterNameMappings.add(names[j], _filterMappings[i]);
130303928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
130403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
130503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
130603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
130703928aee4356845252ac6b662d5c72c29903813eJake Slack
130803928aee4356845252ac6b662d5c72c29903813eJake Slack        // Map servlet paths to holders
130903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_servletMappings==null || _servletNameMap==null)
131003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
131103928aee4356845252ac6b662d5c72c29903813eJake Slack            _servletPathMap=null;
131203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
131303928aee4356845252ac6b662d5c72c29903813eJake Slack        else
131403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
131503928aee4356845252ac6b662d5c72c29903813eJake Slack            PathMap pm = new PathMap();
131603928aee4356845252ac6b662d5c72c29903813eJake Slack
131703928aee4356845252ac6b662d5c72c29903813eJake Slack            // update the maps
131803928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=0;i<_servletMappings.length;i++)
131903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
132003928aee4356845252ac6b662d5c72c29903813eJake Slack                ServletHolder servlet_holder = (ServletHolder)_servletNameMap.get(_servletMappings[i].getServletName());
132103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (servlet_holder==null)
132203928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException("No such servlet: "+_servletMappings[i].getServletName());
132303928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (servlet_holder.isEnabled() && _servletMappings[i].getPathSpecs()!=null)
132403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
132503928aee4356845252ac6b662d5c72c29903813eJake Slack                    String[] pathSpecs = _servletMappings[i].getPathSpecs();
132603928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int j=0;j<pathSpecs.length;j++)
132703928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (pathSpecs[j]!=null)
132803928aee4356845252ac6b662d5c72c29903813eJake Slack                            pm.put(pathSpecs[j],servlet_holder);
132903928aee4356845252ac6b662d5c72c29903813eJake Slack                }
133003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
133103928aee4356845252ac6b662d5c72c29903813eJake Slack
133203928aee4356845252ac6b662d5c72c29903813eJake Slack            _servletPathMap=pm;
133303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
133403928aee4356845252ac6b662d5c72c29903813eJake Slack
133503928aee4356845252ac6b662d5c72c29903813eJake Slack        // flush filter chain cache
133603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_chainCache!=null)
133703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
133803928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=_chainCache.length;i-->0;)
133903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
134003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_chainCache[i]!=null)
134103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _chainCache[i].clear();
134203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
134303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
134403928aee4356845252ac6b662d5c72c29903813eJake Slack
134503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (LOG.isDebugEnabled())
134603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
134703928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("filterNameMap="+_filterNameMap);
134803928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("pathFilters="+_filterPathMappings);
134903928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("servletFilterMap="+_filterNameMappings);
135003928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("servletPathMap="+_servletPathMap);
135103928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("servletNameMap="+_servletNameMap);
135203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
135303928aee4356845252ac6b662d5c72c29903813eJake Slack
135403928aee4356845252ac6b662d5c72c29903813eJake Slack        try
135503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
135603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_contextHandler!=null && _contextHandler.isStarted() || _contextHandler==null && isStarted())
135703928aee4356845252ac6b662d5c72c29903813eJake Slack                initialize();
135803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
135903928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (Exception e)
136003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
136103928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new RuntimeException(e);
136203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
136303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
136403928aee4356845252ac6b662d5c72c29903813eJake Slack
136503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
136603928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void notFound(HttpServletRequest request,
136703928aee4356845252ac6b662d5c72c29903813eJake Slack                  HttpServletResponse response)
136803928aee4356845252ac6b662d5c72c29903813eJake Slack        throws IOException
136903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
137003928aee4356845252ac6b662d5c72c29903813eJake Slack        if(LOG.isDebugEnabled())
137103928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("Not Found "+request.getRequestURI());
137203928aee4356845252ac6b662d5c72c29903813eJake Slack        //Override to send an error back, eg with: response.sendError(HttpServletResponse.SC_NOT_FOUND);
137303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
137403928aee4356845252ac6b662d5c72c29903813eJake Slack
137503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
137603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
137703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param filterChainsCached The filterChainsCached to set.
137803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
137903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setFilterChainsCached(boolean filterChainsCached)
138003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
138103928aee4356845252ac6b662d5c72c29903813eJake Slack        _filterChainsCached = filterChainsCached;
138203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
138303928aee4356845252ac6b662d5c72c29903813eJake Slack
138403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
138503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
138603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param filterMappings The filterMappings to set.
138703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
138803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setFilterMappings(FilterMapping[] filterMappings)
138903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
139003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (getServer()!=null)
139103928aee4356845252ac6b662d5c72c29903813eJake Slack            getServer().getContainer().update(this,_filterMappings,filterMappings,"filterMapping",true);
139203928aee4356845252ac6b662d5c72c29903813eJake Slack        _filterMappings = filterMappings;
139303928aee4356845252ac6b662d5c72c29903813eJake Slack        updateMappings();
139403928aee4356845252ac6b662d5c72c29903813eJake Slack        invalidateChainsCache();
139503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
139603928aee4356845252ac6b662d5c72c29903813eJake Slack
139703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
139803928aee4356845252ac6b662d5c72c29903813eJake Slack    public synchronized void setFilters(FilterHolder[] holders)
139903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
140003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (getServer()!=null)
140103928aee4356845252ac6b662d5c72c29903813eJake Slack            getServer().getContainer().update(this,_filters,holders,"filter",true);
140203928aee4356845252ac6b662d5c72c29903813eJake Slack        _filters=holders;
140303928aee4356845252ac6b662d5c72c29903813eJake Slack        updateNameMappings();
140403928aee4356845252ac6b662d5c72c29903813eJake Slack        invalidateChainsCache();
140503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
140603928aee4356845252ac6b662d5c72c29903813eJake Slack
140703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
140803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
140903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param servletMappings The servletMappings to set.
141003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
141103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setServletMappings(ServletMapping[] servletMappings)
141203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
141303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (getServer()!=null)
141403928aee4356845252ac6b662d5c72c29903813eJake Slack            getServer().getContainer().update(this,_servletMappings,servletMappings,"servletMapping",true);
141503928aee4356845252ac6b662d5c72c29903813eJake Slack        _servletMappings = servletMappings;
141603928aee4356845252ac6b662d5c72c29903813eJake Slack        updateMappings();
141703928aee4356845252ac6b662d5c72c29903813eJake Slack        invalidateChainsCache();
141803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
141903928aee4356845252ac6b662d5c72c29903813eJake Slack
142003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
142103928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Set Servlets.
142203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param holders Array of servletsto define
142303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
142403928aee4356845252ac6b662d5c72c29903813eJake Slack    public synchronized void setServlets(ServletHolder[] holders)
142503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
142603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (getServer()!=null)
142703928aee4356845252ac6b662d5c72c29903813eJake Slack            getServer().getContainer().update(this,_servlets,holders,"servlet",true);
142803928aee4356845252ac6b662d5c72c29903813eJake Slack        _servlets=holders;
142903928aee4356845252ac6b662d5c72c29903813eJake Slack        updateNameMappings();
143003928aee4356845252ac6b662d5c72c29903813eJake Slack        invalidateChainsCache();
143103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
143203928aee4356845252ac6b662d5c72c29903813eJake Slack
143303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
143403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
143503928aee4356845252ac6b662d5c72c29903813eJake Slack    private class CachedChain implements FilterChain
143603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
143703928aee4356845252ac6b662d5c72c29903813eJake Slack        FilterHolder _filterHolder;
143803928aee4356845252ac6b662d5c72c29903813eJake Slack        CachedChain _next;
143903928aee4356845252ac6b662d5c72c29903813eJake Slack        ServletHolder _servletHolder;
144003928aee4356845252ac6b662d5c72c29903813eJake Slack
144103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
144203928aee4356845252ac6b662d5c72c29903813eJake Slack        CachedChain(Object filters, ServletHolder servletHolder)
144303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
144403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LazyList.size(filters)>0)
144503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
144603928aee4356845252ac6b662d5c72c29903813eJake Slack                _filterHolder=(FilterHolder)LazyList.get(filters, 0);
144703928aee4356845252ac6b662d5c72c29903813eJake Slack                filters=LazyList.remove(filters,0);
144803928aee4356845252ac6b662d5c72c29903813eJake Slack                _next=new CachedChain(filters,servletHolder);
144903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
145003928aee4356845252ac6b662d5c72c29903813eJake Slack            else
145103928aee4356845252ac6b662d5c72c29903813eJake Slack                _servletHolder=servletHolder;
145203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
145303928aee4356845252ac6b662d5c72c29903813eJake Slack
145403928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
145503928aee4356845252ac6b662d5c72c29903813eJake Slack        public void doFilter(ServletRequest request, ServletResponse response)
145603928aee4356845252ac6b662d5c72c29903813eJake Slack            throws IOException, ServletException
145703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
145803928aee4356845252ac6b662d5c72c29903813eJake Slack            final Request baseRequest=(request instanceof Request)?((Request)request):AbstractHttpConnection.getCurrentConnection().getRequest();
145903928aee4356845252ac6b662d5c72c29903813eJake Slack
146003928aee4356845252ac6b662d5c72c29903813eJake Slack            // pass to next filter
146103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_filterHolder!=null)
146203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
146303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (LOG.isDebugEnabled())
146403928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.debug("call filter " + _filterHolder);
146503928aee4356845252ac6b662d5c72c29903813eJake Slack                Filter filter= _filterHolder.getFilter();
146603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_filterHolder.isAsyncSupported())
146703928aee4356845252ac6b662d5c72c29903813eJake Slack                    filter.doFilter(request, response, _next);
146803928aee4356845252ac6b662d5c72c29903813eJake Slack                else
146903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
147003928aee4356845252ac6b662d5c72c29903813eJake Slack                    final boolean suspendable=baseRequest.isAsyncSupported();
147103928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (suspendable)
147203928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
147303928aee4356845252ac6b662d5c72c29903813eJake Slack                        try
147403928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
147503928aee4356845252ac6b662d5c72c29903813eJake Slack                            baseRequest.setAsyncSupported(false);
147603928aee4356845252ac6b662d5c72c29903813eJake Slack                            filter.doFilter(request, response, _next);
147703928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
147803928aee4356845252ac6b662d5c72c29903813eJake Slack                        finally
147903928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
148003928aee4356845252ac6b662d5c72c29903813eJake Slack                            baseRequest.setAsyncSupported(true);
148103928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
148203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
148303928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
148403928aee4356845252ac6b662d5c72c29903813eJake Slack                        filter.doFilter(request, response, _next);
148503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
148603928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
148703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
148803928aee4356845252ac6b662d5c72c29903813eJake Slack
148903928aee4356845252ac6b662d5c72c29903813eJake Slack            // Call servlet
149003928aee4356845252ac6b662d5c72c29903813eJake Slack
149103928aee4356845252ac6b662d5c72c29903813eJake Slack            HttpServletRequest srequest = (HttpServletRequest)request;
149203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_servletHolder != null)
149303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
149403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (LOG.isDebugEnabled())
149503928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.debug("call servlet " + _servletHolder);
149603928aee4356845252ac6b662d5c72c29903813eJake Slack                _servletHolder.handle(baseRequest,request, response);
149703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
149803928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (getHandler()==null)
149903928aee4356845252ac6b662d5c72c29903813eJake Slack                notFound(srequest, (HttpServletResponse)response);
150003928aee4356845252ac6b662d5c72c29903813eJake Slack            else
150103928aee4356845252ac6b662d5c72c29903813eJake Slack                nextHandle(URIUtil.addPaths(srequest.getServletPath(),srequest.getPathInfo()),
150203928aee4356845252ac6b662d5c72c29903813eJake Slack                           baseRequest,srequest,(HttpServletResponse)response);
150303928aee4356845252ac6b662d5c72c29903813eJake Slack
150403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
150503928aee4356845252ac6b662d5c72c29903813eJake Slack
150603928aee4356845252ac6b662d5c72c29903813eJake Slack        public String toString()
150703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
150803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_filterHolder!=null)
150903928aee4356845252ac6b662d5c72c29903813eJake Slack                return _filterHolder+"->"+_next.toString();
151003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_servletHolder!=null)
151103928aee4356845252ac6b662d5c72c29903813eJake Slack                return _servletHolder.toString();
151203928aee4356845252ac6b662d5c72c29903813eJake Slack            return "null";
151303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
151403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
151503928aee4356845252ac6b662d5c72c29903813eJake Slack
151603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
151703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
151803928aee4356845252ac6b662d5c72c29903813eJake Slack    private class Chain implements FilterChain
151903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
152003928aee4356845252ac6b662d5c72c29903813eJake Slack        final Request _baseRequest;
152103928aee4356845252ac6b662d5c72c29903813eJake Slack        final Object _chain;
152203928aee4356845252ac6b662d5c72c29903813eJake Slack        final ServletHolder _servletHolder;
152303928aee4356845252ac6b662d5c72c29903813eJake Slack        int _filter= 0;
152403928aee4356845252ac6b662d5c72c29903813eJake Slack
152503928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
152603928aee4356845252ac6b662d5c72c29903813eJake Slack        Chain(Request baseRequest, Object filters, ServletHolder servletHolder)
152703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
152803928aee4356845252ac6b662d5c72c29903813eJake Slack            _baseRequest=baseRequest;
152903928aee4356845252ac6b662d5c72c29903813eJake Slack            _chain= filters;
153003928aee4356845252ac6b662d5c72c29903813eJake Slack            _servletHolder= servletHolder;
153103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
153203928aee4356845252ac6b662d5c72c29903813eJake Slack
153303928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
153403928aee4356845252ac6b662d5c72c29903813eJake Slack        public void doFilter(ServletRequest request, ServletResponse response)
153503928aee4356845252ac6b662d5c72c29903813eJake Slack            throws IOException, ServletException
153603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
153703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
153803928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("doFilter " + _filter);
153903928aee4356845252ac6b662d5c72c29903813eJake Slack
154003928aee4356845252ac6b662d5c72c29903813eJake Slack            // pass to next filter
154103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_filter < LazyList.size(_chain))
154203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
154303928aee4356845252ac6b662d5c72c29903813eJake Slack                FilterHolder holder= (FilterHolder)LazyList.get(_chain, _filter++);
154403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (LOG.isDebugEnabled())
154503928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.debug("call filter " + holder);
154603928aee4356845252ac6b662d5c72c29903813eJake Slack                Filter filter= holder.getFilter();
154703928aee4356845252ac6b662d5c72c29903813eJake Slack
154803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (holder.isAsyncSupported() || !_baseRequest.isAsyncSupported())
154903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
155003928aee4356845252ac6b662d5c72c29903813eJake Slack                    filter.doFilter(request, response, this);
155103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
155203928aee4356845252ac6b662d5c72c29903813eJake Slack                else
155303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
155403928aee4356845252ac6b662d5c72c29903813eJake Slack                    try
155503928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
155603928aee4356845252ac6b662d5c72c29903813eJake Slack                        _baseRequest.setAsyncSupported(false);
155703928aee4356845252ac6b662d5c72c29903813eJake Slack                        filter.doFilter(request, response, this);
155803928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
155903928aee4356845252ac6b662d5c72c29903813eJake Slack                    finally
156003928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
156103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _baseRequest.setAsyncSupported(true);
156203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
156303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
156403928aee4356845252ac6b662d5c72c29903813eJake Slack
156503928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
156603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
156703928aee4356845252ac6b662d5c72c29903813eJake Slack
156803928aee4356845252ac6b662d5c72c29903813eJake Slack            // Call servlet
156903928aee4356845252ac6b662d5c72c29903813eJake Slack            HttpServletRequest srequest = (HttpServletRequest)request;
157003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_servletHolder != null)
157103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
157203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (LOG.isDebugEnabled())
157303928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.debug("call servlet " + _servletHolder);
157403928aee4356845252ac6b662d5c72c29903813eJake Slack                _servletHolder.handle(_baseRequest,request, response);
157503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
157603928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (getHandler()==null)
157703928aee4356845252ac6b662d5c72c29903813eJake Slack                notFound(srequest, (HttpServletResponse)response);
157803928aee4356845252ac6b662d5c72c29903813eJake Slack            else
157903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
158003928aee4356845252ac6b662d5c72c29903813eJake Slack                Request baseRequest=(request instanceof Request)?((Request)request):AbstractHttpConnection.getCurrentConnection().getRequest();
158103928aee4356845252ac6b662d5c72c29903813eJake Slack                nextHandle(URIUtil.addPaths(srequest.getServletPath(),srequest.getPathInfo()),
158203928aee4356845252ac6b662d5c72c29903813eJake Slack                           baseRequest,srequest,(HttpServletResponse)response);
158303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
158403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
158503928aee4356845252ac6b662d5c72c29903813eJake Slack
158603928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
158703928aee4356845252ac6b662d5c72c29903813eJake Slack        public String toString()
158803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
158903928aee4356845252ac6b662d5c72c29903813eJake Slack            StringBuilder b = new StringBuilder();
159003928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i=0; i<LazyList.size(_chain);i++)
159103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
159203928aee4356845252ac6b662d5c72c29903813eJake Slack                Object o=LazyList.get(_chain, i);
159303928aee4356845252ac6b662d5c72c29903813eJake Slack                b.append(o.toString());
159403928aee4356845252ac6b662d5c72c29903813eJake Slack                b.append("->");
159503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
159603928aee4356845252ac6b662d5c72c29903813eJake Slack            b.append(_servletHolder);
159703928aee4356845252ac6b662d5c72c29903813eJake Slack            return b.toString();
159803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
159903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
160003928aee4356845252ac6b662d5c72c29903813eJake Slack
160103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
160203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
160303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The maximum entries in a filter chain cache.
160403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
160503928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getMaxFilterChainsCacheSize()
160603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
160703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _maxFilterChainsCacheSize;
160803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
160903928aee4356845252ac6b662d5c72c29903813eJake Slack
161003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
161103928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Set the maximum filter chain cache size.
161203928aee4356845252ac6b662d5c72c29903813eJake Slack     * Filter chains are cached if {@link #isFilterChainsCached()} is true. If the max cache size
161303928aee4356845252ac6b662d5c72c29903813eJake Slack     * is greater than zero, then the cache is flushed whenever it grows to be this size.
161403928aee4356845252ac6b662d5c72c29903813eJake Slack     *
161503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param maxFilterChainsCacheSize  the maximum number of entries in a filter chain cache.
161603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
161703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setMaxFilterChainsCacheSize(int maxFilterChainsCacheSize)
161803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
161903928aee4356845252ac6b662d5c72c29903813eJake Slack        _maxFilterChainsCacheSize = maxFilterChainsCacheSize;
162003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
162103928aee4356845252ac6b662d5c72c29903813eJake Slack
162203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
162303928aee4356845252ac6b662d5c72c29903813eJake Slack    void destroyServlet(Servlet servlet)
162403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
162503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_contextHandler!=null)
162603928aee4356845252ac6b662d5c72c29903813eJake Slack            _contextHandler.destroyServlet(servlet);
162703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
162803928aee4356845252ac6b662d5c72c29903813eJake Slack
162903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
163003928aee4356845252ac6b662d5c72c29903813eJake Slack    void destroyFilter(Filter filter)
163103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
163203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_contextHandler!=null)
163303928aee4356845252ac6b662d5c72c29903813eJake Slack            _contextHandler.destroyFilter(filter);
163403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
163503928aee4356845252ac6b662d5c72c29903813eJake Slack
163603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
163703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
163803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void dump(Appendable out,String indent) throws IOException
163903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
164003928aee4356845252ac6b662d5c72c29903813eJake Slack        super.dumpThis(out);
164103928aee4356845252ac6b662d5c72c29903813eJake Slack        dump(out,indent,
164203928aee4356845252ac6b662d5c72c29903813eJake Slack                TypeUtil.asList(getHandlers()),
164303928aee4356845252ac6b662d5c72c29903813eJake Slack                getBeans(),
164403928aee4356845252ac6b662d5c72c29903813eJake Slack                TypeUtil.asList(getFilterMappings()),
164503928aee4356845252ac6b662d5c72c29903813eJake Slack                TypeUtil.asList(getFilters()),
164603928aee4356845252ac6b662d5c72c29903813eJake Slack                TypeUtil.asList(getServletMappings()),
164703928aee4356845252ac6b662d5c72c29903813eJake Slack                TypeUtil.asList(getServlets()));
164803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
164903928aee4356845252ac6b662d5c72c29903813eJake Slack}
1650