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.server.handler;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.File;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.InputStream;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.MalformedURLException;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.URL;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.URLClassLoader;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.security.AccessController;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.ArrayList;
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Arrays;
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Collections;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Enumeration;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.EventListener;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashMap;
3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashSet;
3503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Iterator;
3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List;
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Locale;
3803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Map;
3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Set;
4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.concurrent.CopyOnWriteArrayList;
4103928aee4356845252ac6b662d5c72c29903813eJake Slack
4203928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.DispatcherType;
4303928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.RequestDispatcher;
4403928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.Servlet;
4503928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletContext;
4603928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletContextAttributeEvent;
4703928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletContextAttributeListener;
4803928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletContextEvent;
4903928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletContextListener;
5003928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletException;
5103928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletRegistration;
5203928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletRequestAttributeListener;
5303928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletRequestEvent;
5403928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletRequestListener;
5503928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.SessionCookieConfig;
5603928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.SessionTrackingMode;
5703928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.Filter;
5803928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.FilterRegistration;
5903928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.FilterRegistration.Dynamic;
6003928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.descriptor.JspConfigDescriptor;
6103928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletRequest;
6203928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletResponse;
6303928aee4356845252ac6b662d5c72c29903813eJake Slack
6403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.HttpException;
6503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.MimeTypes;
6603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Buffer;
6703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.AbstractHttpConnection;
6803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Dispatcher;
6903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Handler;
7003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.HandlerContainer;
7103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Request;
7203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Server;
7303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.Attributes;
7403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.AttributesMap;
7503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.LazyList;
7603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.Loader;
7703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.StringUtil;
7803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.TypeUtil;
7903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.URIUtil;
8003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.component.AggregateLifeCycle;
8103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.component.Dumpable;
8203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
8303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
8403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.resource.Resource;
8503928aee4356845252ac6b662d5c72c29903813eJake Slack
8603928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
8703928aee4356845252ac6b662d5c72c29903813eJake Slack/**
8803928aee4356845252ac6b662d5c72c29903813eJake Slack * ContextHandler.
8903928aee4356845252ac6b662d5c72c29903813eJake Slack *
9003928aee4356845252ac6b662d5c72c29903813eJake Slack * This handler wraps a call to handle by setting the context and servlet path, plus setting the context classloader.
9103928aee4356845252ac6b662d5c72c29903813eJake Slack *
9203928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
9303928aee4356845252ac6b662d5c72c29903813eJake Slack * If the context init parameter "org.eclipse.jetty.server.context.ManagedAttributes" is set to a comma separated list of names, then they are treated as
9403928aee4356845252ac6b662d5c72c29903813eJake Slack * context attribute names, which if set as attributes are passed to the servers Container so that they may be managed with JMX.
9503928aee4356845252ac6b662d5c72c29903813eJake Slack * <p>
9603928aee4356845252ac6b662d5c72c29903813eJake Slack * The maximum size of a form that can be processed by this context is controlled by the system properties org.eclipse.jetty.server.Request.maxFormKeys
9703928aee4356845252ac6b662d5c72c29903813eJake Slack * and org.eclipse.jetty.server.Request.maxFormContentSize.  These can also be configured with {@link #setMaxFormContentSize(int)} and {@link #setMaxFormKeys(int)}
9803928aee4356845252ac6b662d5c72c29903813eJake Slack *
9903928aee4356845252ac6b662d5c72c29903813eJake Slack * @org.apache.xbean.XBean description="Creates a basic HTTP context"
10003928aee4356845252ac6b662d5c72c29903813eJake Slack */
10103928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class ContextHandler extends ScopedHandler implements Attributes, Server.Graceful
10203928aee4356845252ac6b662d5c72c29903813eJake Slack{
10303928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(ContextHandler.class);
10403928aee4356845252ac6b662d5c72c29903813eJake Slack
10503928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final ThreadLocal<Context> __context = new ThreadLocal<Context>();
10603928aee4356845252ac6b662d5c72c29903813eJake Slack
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
10803928aee4356845252ac6b662d5c72c29903813eJake Slack     * If a context attribute with this name is set, it is interpreted as a comma separated list of attribute name. Any other context attributes that are set
10903928aee4356845252ac6b662d5c72c29903813eJake Slack     * with a name from this list will result in a call to {@link #setManagedAttribute(String, Object)}, which typically initiates the creation of a JMX MBean
11003928aee4356845252ac6b662d5c72c29903813eJake Slack     * for the attribute value.
11103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final String MANAGED_ATTRIBUTES = "org.eclipse.jetty.server.context.ManagedAttributes";
11303928aee4356845252ac6b662d5c72c29903813eJake Slack
11403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
11603928aee4356845252ac6b662d5c72c29903813eJake Slack     * Get the current ServletContext implementation.
11703928aee4356845252ac6b662d5c72c29903813eJake Slack     *
11803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return ServletContext implementation
11903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
12003928aee4356845252ac6b662d5c72c29903813eJake Slack    public static Context getCurrentContext()
12103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12203928aee4356845252ac6b662d5c72c29903813eJake Slack        return __context.get();
12303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12403928aee4356845252ac6b662d5c72c29903813eJake Slack
12503928aee4356845252ac6b662d5c72c29903813eJake Slack    protected Context _scontext;
12603928aee4356845252ac6b662d5c72c29903813eJake Slack
12703928aee4356845252ac6b662d5c72c29903813eJake Slack    private final AttributesMap _attributes;
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    private final AttributesMap _contextAttributes;
12903928aee4356845252ac6b662d5c72c29903813eJake Slack    private final Map<String, String> _initParams;
13003928aee4356845252ac6b662d5c72c29903813eJake Slack    private ClassLoader _classLoader;
13103928aee4356845252ac6b662d5c72c29903813eJake Slack    private String _contextPath = "/";
13203928aee4356845252ac6b662d5c72c29903813eJake Slack    private String _displayName;
13303928aee4356845252ac6b662d5c72c29903813eJake Slack    private Resource _baseResource;
13403928aee4356845252ac6b662d5c72c29903813eJake Slack    private MimeTypes _mimeTypes;
13503928aee4356845252ac6b662d5c72c29903813eJake Slack    private Map<String, String> _localeEncodingMap;
13603928aee4356845252ac6b662d5c72c29903813eJake Slack    private String[] _welcomeFiles;
13703928aee4356845252ac6b662d5c72c29903813eJake Slack    private ErrorHandler _errorHandler;
13803928aee4356845252ac6b662d5c72c29903813eJake Slack    private String[] _vhosts;
13903928aee4356845252ac6b662d5c72c29903813eJake Slack    private Set<String> _connectors;
14003928aee4356845252ac6b662d5c72c29903813eJake Slack    private EventListener[] _eventListeners;
14103928aee4356845252ac6b662d5c72c29903813eJake Slack    private Logger _logger;
14203928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _allowNullPathInfo;
14303928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _maxFormKeys = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormKeys",-1).intValue();
14403928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _maxFormContentSize = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormContentSize",-1).intValue();
14503928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _compactPath = false;
14603928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _aliasesAllowed = false;
14703928aee4356845252ac6b662d5c72c29903813eJake Slack
14803928aee4356845252ac6b662d5c72c29903813eJake Slack    private Object _contextListeners;
14903928aee4356845252ac6b662d5c72c29903813eJake Slack    private Object _contextAttributeListeners;
15003928aee4356845252ac6b662d5c72c29903813eJake Slack    private Object _requestListeners;
15103928aee4356845252ac6b662d5c72c29903813eJake Slack    private Object _requestAttributeListeners;
15203928aee4356845252ac6b662d5c72c29903813eJake Slack    private Object _durableListeners;
15303928aee4356845252ac6b662d5c72c29903813eJake Slack    private Map<String, Object> _managedAttributes;
15403928aee4356845252ac6b662d5c72c29903813eJake Slack    private String[] _protectedTargets;
15503928aee4356845252ac6b662d5c72c29903813eJake Slack    private final CopyOnWriteArrayList<AliasCheck> _aliasChecks = new CopyOnWriteArrayList<ContextHandler.AliasCheck>();
15603928aee4356845252ac6b662d5c72c29903813eJake Slack
15703928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _shutdown = false;
15803928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _available = true;
15903928aee4356845252ac6b662d5c72c29903813eJake Slack    private volatile int _availability; // 0=STOPPED, 1=AVAILABLE, 2=SHUTDOWN, 3=UNAVAILABLE
16003928aee4356845252ac6b662d5c72c29903813eJake Slack
16103928aee4356845252ac6b662d5c72c29903813eJake Slack    private final static int __STOPPED = 0, __AVAILABLE = 1, __SHUTDOWN = 2, __UNAVAILABLE = 3;
16203928aee4356845252ac6b662d5c72c29903813eJake Slack
16303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
16403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
16503928aee4356845252ac6b662d5c72c29903813eJake Slack     *
16603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
16703928aee4356845252ac6b662d5c72c29903813eJake Slack    public ContextHandler()
16803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16903928aee4356845252ac6b662d5c72c29903813eJake Slack        super();
17003928aee4356845252ac6b662d5c72c29903813eJake Slack        _scontext = new Context();
17103928aee4356845252ac6b662d5c72c29903813eJake Slack        _attributes = new AttributesMap();
17203928aee4356845252ac6b662d5c72c29903813eJake Slack        _contextAttributes = new AttributesMap();
17303928aee4356845252ac6b662d5c72c29903813eJake Slack        _initParams = new HashMap<String, String>();
17403928aee4356845252ac6b662d5c72c29903813eJake Slack        addAliasCheck(new ApproveNonExistentDirectoryAliases());
17503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17603928aee4356845252ac6b662d5c72c29903813eJake Slack
17703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
17803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
17903928aee4356845252ac6b662d5c72c29903813eJake Slack     *
18003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
18103928aee4356845252ac6b662d5c72c29903813eJake Slack    protected ContextHandler(Context context)
18203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
18303928aee4356845252ac6b662d5c72c29903813eJake Slack        super();
18403928aee4356845252ac6b662d5c72c29903813eJake Slack        _scontext = context;
18503928aee4356845252ac6b662d5c72c29903813eJake Slack        _attributes = new AttributesMap();
18603928aee4356845252ac6b662d5c72c29903813eJake Slack        _contextAttributes = new AttributesMap();
18703928aee4356845252ac6b662d5c72c29903813eJake Slack        _initParams = new HashMap<String, String>();
18803928aee4356845252ac6b662d5c72c29903813eJake Slack        addAliasCheck(new ApproveNonExistentDirectoryAliases());
18903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
19003928aee4356845252ac6b662d5c72c29903813eJake Slack
19103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
19203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
19303928aee4356845252ac6b662d5c72c29903813eJake Slack     *
19403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
19503928aee4356845252ac6b662d5c72c29903813eJake Slack    public ContextHandler(String contextPath)
19603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
19703928aee4356845252ac6b662d5c72c29903813eJake Slack        this();
19803928aee4356845252ac6b662d5c72c29903813eJake Slack        setContextPath(contextPath);
19903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
20003928aee4356845252ac6b662d5c72c29903813eJake Slack
20103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
20203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
20303928aee4356845252ac6b662d5c72c29903813eJake Slack     *
20403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
20503928aee4356845252ac6b662d5c72c29903813eJake Slack    public ContextHandler(HandlerContainer parent, String contextPath)
20603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20703928aee4356845252ac6b662d5c72c29903813eJake Slack        this();
20803928aee4356845252ac6b662d5c72c29903813eJake Slack        setContextPath(contextPath);
20903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (parent instanceof HandlerWrapper)
21003928aee4356845252ac6b662d5c72c29903813eJake Slack            ((HandlerWrapper)parent).setHandler(this);
21103928aee4356845252ac6b662d5c72c29903813eJake Slack        else if (parent instanceof HandlerCollection)
21203928aee4356845252ac6b662d5c72c29903813eJake Slack            ((HandlerCollection)parent).addHandler(this);
21303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
21403928aee4356845252ac6b662d5c72c29903813eJake Slack
21503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
21603928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
21703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void dump(Appendable out, String indent) throws IOException
21803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
21903928aee4356845252ac6b662d5c72c29903813eJake Slack        dumpThis(out);
22003928aee4356845252ac6b662d5c72c29903813eJake Slack        dump(out,indent,Collections.singletonList(new CLDump(getClassLoader())),TypeUtil.asList(getHandlers()),getBeans(),_initParams.entrySet(),
22103928aee4356845252ac6b662d5c72c29903813eJake Slack                _attributes.getAttributeEntrySet(),_contextAttributes.getAttributeEntrySet());
22203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
22303928aee4356845252ac6b662d5c72c29903813eJake Slack
22403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
22503928aee4356845252ac6b662d5c72c29903813eJake Slack    public Context getServletContext()
22603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
22703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _scontext;
22803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
22903928aee4356845252ac6b662d5c72c29903813eJake Slack
23003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
23103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
23203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return the allowNullPathInfo true if /context is not redirected to /context/
23303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
23403928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean getAllowNullPathInfo()
23503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
23603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _allowNullPathInfo;
23703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
23803928aee4356845252ac6b662d5c72c29903813eJake Slack
23903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
24003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
24103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param allowNullPathInfo
24203928aee4356845252ac6b662d5c72c29903813eJake Slack     *            true if /context is not redirected to /context/
24303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
24403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setAllowNullPathInfo(boolean allowNullPathInfo)
24503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
24603928aee4356845252ac6b662d5c72c29903813eJake Slack        _allowNullPathInfo = allowNullPathInfo;
24703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
24803928aee4356845252ac6b662d5c72c29903813eJake Slack
24903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
25003928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
25103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setServer(Server server)
25203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
25303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_errorHandler != null)
25403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
25503928aee4356845252ac6b662d5c72c29903813eJake Slack            Server old_server = getServer();
25603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (old_server != null && old_server != server)
25703928aee4356845252ac6b662d5c72c29903813eJake Slack                old_server.getContainer().update(this,_errorHandler,null,"error",true);
25803928aee4356845252ac6b662d5c72c29903813eJake Slack            super.setServer(server);
25903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (server != null && server != old_server)
26003928aee4356845252ac6b662d5c72c29903813eJake Slack                server.getContainer().update(this,null,_errorHandler,"error",true);
26103928aee4356845252ac6b662d5c72c29903813eJake Slack            _errorHandler.setServer(server);
26203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
26303928aee4356845252ac6b662d5c72c29903813eJake Slack        else
26403928aee4356845252ac6b662d5c72c29903813eJake Slack            super.setServer(server);
26503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
26603928aee4356845252ac6b662d5c72c29903813eJake Slack
26703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
26803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
26903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Set the virtual hosts for the context. Only requests that have a matching host header or fully qualified URL will be passed to that context with a
27003928aee4356845252ac6b662d5c72c29903813eJake Slack     * virtual host name. A context with no virtual host names or a null virtual host name is available to all requests that are not served by a context with a
27103928aee4356845252ac6b662d5c72c29903813eJake Slack     * matching virtual host name.
27203928aee4356845252ac6b662d5c72c29903813eJake Slack     *
27303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param vhosts
27403928aee4356845252ac6b662d5c72c29903813eJake Slack     *            Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be
27503928aee4356845252ac6b662d5c72c29903813eJake Slack     *            String representation of IP addresses. Host names may start with '*.' to wildcard one level of names.
27603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
27703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setVirtualHosts(String[] vhosts)
27803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
27903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (vhosts == null)
28003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
28103928aee4356845252ac6b662d5c72c29903813eJake Slack            _vhosts = vhosts;
28203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
28303928aee4356845252ac6b662d5c72c29903813eJake Slack        else
28403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
28503928aee4356845252ac6b662d5c72c29903813eJake Slack            _vhosts = new String[vhosts.length];
28603928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i = 0; i < vhosts.length; i++)
28703928aee4356845252ac6b662d5c72c29903813eJake Slack                _vhosts[i] = normalizeHostname(vhosts[i]);
28803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
28903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
29003928aee4356845252ac6b662d5c72c29903813eJake Slack
29103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
29203928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Either set virtual hosts or add to an existing set of virtual hosts.
29303928aee4356845252ac6b662d5c72c29903813eJake Slack     *
29403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param virtualHosts
29503928aee4356845252ac6b662d5c72c29903813eJake Slack     *            Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be
29603928aee4356845252ac6b662d5c72c29903813eJake Slack     *            String representation of IP addresses. Host names may start with '*.' to wildcard one level of names.
29703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
29803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addVirtualHosts(String[] virtualHosts)
29903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
30003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (virtualHosts == null)  // since this is add, we don't null the old ones
30103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
30203928aee4356845252ac6b662d5c72c29903813eJake Slack            return;
30303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
30403928aee4356845252ac6b662d5c72c29903813eJake Slack        else
30503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
30603928aee4356845252ac6b662d5c72c29903813eJake Slack            List<String> currentVirtualHosts = null;
30703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_vhosts != null)
30803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
30903928aee4356845252ac6b662d5c72c29903813eJake Slack                currentVirtualHosts = new ArrayList<String>(Arrays.asList(_vhosts));
31003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
31103928aee4356845252ac6b662d5c72c29903813eJake Slack            else
31203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
31303928aee4356845252ac6b662d5c72c29903813eJake Slack                currentVirtualHosts = new ArrayList<String>();
31403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
31503928aee4356845252ac6b662d5c72c29903813eJake Slack
31603928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i = 0; i < virtualHosts.length; i++)
31703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
31803928aee4356845252ac6b662d5c72c29903813eJake Slack                String normVhost = normalizeHostname(virtualHosts[i]);
31903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!currentVirtualHosts.contains(normVhost))
32003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
32103928aee4356845252ac6b662d5c72c29903813eJake Slack                    currentVirtualHosts.add(normVhost);
32203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
32303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
32403928aee4356845252ac6b662d5c72c29903813eJake Slack            _vhosts = currentVirtualHosts.toArray(new String[0]);
32503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
32603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
32703928aee4356845252ac6b662d5c72c29903813eJake Slack
32803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
32903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
33003928aee4356845252ac6b662d5c72c29903813eJake Slack     * Removes an array of virtual host entries, if this removes all entries the _vhosts will be set to null
33103928aee4356845252ac6b662d5c72c29903813eJake Slack     *
33203928aee4356845252ac6b662d5c72c29903813eJake Slack     *  @param virtualHosts
33303928aee4356845252ac6b662d5c72c29903813eJake Slack     *            Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be
33403928aee4356845252ac6b662d5c72c29903813eJake Slack     *            String representation of IP addresses. Host names may start with '*.' to wildcard one level of names.
33503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
33603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void removeVirtualHosts(String[] virtualHosts)
33703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
33803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (virtualHosts == null)
33903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
34003928aee4356845252ac6b662d5c72c29903813eJake Slack            return; // do nothing
34103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
34203928aee4356845252ac6b662d5c72c29903813eJake Slack        else if ( _vhosts == null || _vhosts.length == 0)
34303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
34403928aee4356845252ac6b662d5c72c29903813eJake Slack            return; // do nothing
34503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
34603928aee4356845252ac6b662d5c72c29903813eJake Slack        else
34703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
34803928aee4356845252ac6b662d5c72c29903813eJake Slack            List<String> existingVirtualHosts = new ArrayList<String>(Arrays.asList(_vhosts));
34903928aee4356845252ac6b662d5c72c29903813eJake Slack
35003928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i = 0; i < virtualHosts.length; i++)
35103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
35203928aee4356845252ac6b662d5c72c29903813eJake Slack                String toRemoveVirtualHost = normalizeHostname(virtualHosts[i]);
35303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (existingVirtualHosts.contains(toRemoveVirtualHost))
35403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
35503928aee4356845252ac6b662d5c72c29903813eJake Slack                    existingVirtualHosts.remove(toRemoveVirtualHost);
35603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
35703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
35803928aee4356845252ac6b662d5c72c29903813eJake Slack
35903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (existingVirtualHosts.isEmpty())
36003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
36103928aee4356845252ac6b662d5c72c29903813eJake Slack                _vhosts = null; // if we ended up removing them all, just null out _vhosts
36203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
36303928aee4356845252ac6b662d5c72c29903813eJake Slack            else
36403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
36503928aee4356845252ac6b662d5c72c29903813eJake Slack                _vhosts = existingVirtualHosts.toArray(new String[0]);
36603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
36703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
36803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36903928aee4356845252ac6b662d5c72c29903813eJake Slack
37003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
37103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
37203928aee4356845252ac6b662d5c72c29903813eJake Slack     * Get the virtual hosts for the context. Only requests that have a matching host header or fully qualified URL will be passed to that context with a
37303928aee4356845252ac6b662d5c72c29903813eJake Slack     * virtual host name. A context with no virtual host names or a null virtual host name is available to all requests that are not served by a context with a
37403928aee4356845252ac6b662d5c72c29903813eJake Slack     * matching virtual host name.
37503928aee4356845252ac6b662d5c72c29903813eJake Slack     *
37603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Array of virtual hosts that this context responds to. A null host name or empty array means any hostname is acceptable. Host names may be String
37703928aee4356845252ac6b662d5c72c29903813eJake Slack     *         representation of IP addresses. Host names may start with '*.' to wildcard one level of names.
37803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
37903928aee4356845252ac6b662d5c72c29903813eJake Slack    public String[] getVirtualHosts()
38003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
38103928aee4356845252ac6b662d5c72c29903813eJake Slack        return _vhosts;
38203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
38303928aee4356845252ac6b662d5c72c29903813eJake Slack
38403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
38503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
38603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return an array of connector names that this context will accept a request from.
38703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
38803928aee4356845252ac6b662d5c72c29903813eJake Slack    public String[] getConnectorNames()
38903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
39003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_connectors == null || _connectors.size() == 0)
39103928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
39203928aee4356845252ac6b662d5c72c29903813eJake Slack
39303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _connectors.toArray(new String[_connectors.size()]);
39403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
39503928aee4356845252ac6b662d5c72c29903813eJake Slack
39603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
39703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
39803928aee4356845252ac6b662d5c72c29903813eJake Slack     * Set the names of accepted connectors.
39903928aee4356845252ac6b662d5c72c29903813eJake Slack     *
40003928aee4356845252ac6b662d5c72c29903813eJake Slack     * Names are either "host:port" or a specific configured name for a connector.
40103928aee4356845252ac6b662d5c72c29903813eJake Slack     *
40203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param connectors
40303928aee4356845252ac6b662d5c72c29903813eJake Slack     *            If non null, an array of connector names that this context will accept a request from.
40403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
40503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setConnectorNames(String[] connectors)
40603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
40703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (connectors == null || connectors.length == 0)
40803928aee4356845252ac6b662d5c72c29903813eJake Slack            _connectors = null;
40903928aee4356845252ac6b662d5c72c29903813eJake Slack        else
41003928aee4356845252ac6b662d5c72c29903813eJake Slack            _connectors = new HashSet<String>(Arrays.asList(connectors));
41103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
41203928aee4356845252ac6b662d5c72c29903813eJake Slack
41303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
41403928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
41503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletContext#getAttribute(java.lang.String)
41603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
41703928aee4356845252ac6b662d5c72c29903813eJake Slack    public Object getAttribute(String name)
41803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
41903928aee4356845252ac6b662d5c72c29903813eJake Slack        return _attributes.getAttribute(name);
42003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
42103928aee4356845252ac6b662d5c72c29903813eJake Slack
42203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
42303928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
42403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletContext#getAttributeNames()
42503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
42603928aee4356845252ac6b662d5c72c29903813eJake Slack    @SuppressWarnings("unchecked")
42703928aee4356845252ac6b662d5c72c29903813eJake Slack    public Enumeration getAttributeNames()
42803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
42903928aee4356845252ac6b662d5c72c29903813eJake Slack        return AttributesMap.getAttributeNamesCopy(_attributes);
43003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
43103928aee4356845252ac6b662d5c72c29903813eJake Slack
43203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
43303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
43403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the attributes.
43503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
43603928aee4356845252ac6b662d5c72c29903813eJake Slack    public Attributes getAttributes()
43703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
43803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _attributes;
43903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
44003928aee4356845252ac6b662d5c72c29903813eJake Slack
44103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
44203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
44303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the classLoader.
44403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
44503928aee4356845252ac6b662d5c72c29903813eJake Slack    public ClassLoader getClassLoader()
44603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
44703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _classLoader;
44803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
44903928aee4356845252ac6b662d5c72c29903813eJake Slack
45003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
45103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
45203928aee4356845252ac6b662d5c72c29903813eJake Slack     * Make best effort to extract a file classpath from the context classloader
45303928aee4356845252ac6b662d5c72c29903813eJake Slack     *
45403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the classLoader.
45503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
45603928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getClassPath()
45703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
45803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_classLoader == null || !(_classLoader instanceof URLClassLoader))
45903928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
46003928aee4356845252ac6b662d5c72c29903813eJake Slack        URLClassLoader loader = (URLClassLoader)_classLoader;
46103928aee4356845252ac6b662d5c72c29903813eJake Slack        URL[] urls = loader.getURLs();
46203928aee4356845252ac6b662d5c72c29903813eJake Slack        StringBuilder classpath = new StringBuilder();
46303928aee4356845252ac6b662d5c72c29903813eJake Slack        for (int i = 0; i < urls.length; i++)
46403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
46503928aee4356845252ac6b662d5c72c29903813eJake Slack            try
46603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
46703928aee4356845252ac6b662d5c72c29903813eJake Slack                Resource resource = newResource(urls[i]);
46803928aee4356845252ac6b662d5c72c29903813eJake Slack                File file = resource.getFile();
46903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (file != null && file.exists())
47003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
47103928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (classpath.length() > 0)
47203928aee4356845252ac6b662d5c72c29903813eJake Slack                        classpath.append(File.pathSeparatorChar);
47303928aee4356845252ac6b662d5c72c29903813eJake Slack                    classpath.append(file.getAbsolutePath());
47403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
47503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
47603928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IOException e)
47703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
47803928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug(e);
47903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
48003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
48103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (classpath.length() == 0)
48203928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
48303928aee4356845252ac6b662d5c72c29903813eJake Slack        return classpath.toString();
48403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
48503928aee4356845252ac6b662d5c72c29903813eJake Slack
48603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
48703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
48803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the _contextPath.
48903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
49003928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getContextPath()
49103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
49203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _contextPath;
49303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
49403928aee4356845252ac6b662d5c72c29903813eJake Slack
49503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
49603928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
49703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletContext#getInitParameter(java.lang.String)
49803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
49903928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getInitParameter(String name)
50003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
50103928aee4356845252ac6b662d5c72c29903813eJake Slack        return _initParams.get(name);
50203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
50303928aee4356845252ac6b662d5c72c29903813eJake Slack
50403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
50503928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
50603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
50703928aee4356845252ac6b662d5c72c29903813eJake Slack    public String setInitParameter(String name, String value)
50803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
50903928aee4356845252ac6b662d5c72c29903813eJake Slack        return _initParams.put(name,value);
51003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
51103928aee4356845252ac6b662d5c72c29903813eJake Slack
51203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
51303928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
51403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletContext#getInitParameterNames()
51503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
51603928aee4356845252ac6b662d5c72c29903813eJake Slack    @SuppressWarnings("rawtypes")
51703928aee4356845252ac6b662d5c72c29903813eJake Slack    public Enumeration getInitParameterNames()
51803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
51903928aee4356845252ac6b662d5c72c29903813eJake Slack        return Collections.enumeration(_initParams.keySet());
52003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
52103928aee4356845252ac6b662d5c72c29903813eJake Slack
52203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
52303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
52403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the initParams.
52503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
52603928aee4356845252ac6b662d5c72c29903813eJake Slack    public Map<String, String> getInitParams()
52703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
52803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _initParams;
52903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
53003928aee4356845252ac6b662d5c72c29903813eJake Slack
53103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
53203928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
53303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletContext#getServletContextName()
53403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
53503928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getDisplayName()
53603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
53703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _displayName;
53803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
53903928aee4356845252ac6b662d5c72c29903813eJake Slack
54003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
54103928aee4356845252ac6b662d5c72c29903813eJake Slack    public EventListener[] getEventListeners()
54203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
54303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _eventListeners;
54403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
54503928aee4356845252ac6b662d5c72c29903813eJake Slack
54603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
54703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
54803928aee4356845252ac6b662d5c72c29903813eJake Slack     * Set the context event listeners.
54903928aee4356845252ac6b662d5c72c29903813eJake Slack     *
55003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param eventListeners
55103928aee4356845252ac6b662d5c72c29903813eJake Slack     *            the event listeners
55203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see ServletContextListener
55303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see ServletContextAttributeListener
55403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see ServletRequestListener
55503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see ServletRequestAttributeListener
55603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
55703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setEventListeners(EventListener[] eventListeners)
55803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
55903928aee4356845252ac6b662d5c72c29903813eJake Slack        _contextListeners = null;
56003928aee4356845252ac6b662d5c72c29903813eJake Slack        _contextAttributeListeners = null;
56103928aee4356845252ac6b662d5c72c29903813eJake Slack        _requestListeners = null;
56203928aee4356845252ac6b662d5c72c29903813eJake Slack        _requestAttributeListeners = null;
56303928aee4356845252ac6b662d5c72c29903813eJake Slack
56403928aee4356845252ac6b662d5c72c29903813eJake Slack        _eventListeners = eventListeners;
56503928aee4356845252ac6b662d5c72c29903813eJake Slack
56603928aee4356845252ac6b662d5c72c29903813eJake Slack        for (int i = 0; eventListeners != null && i < eventListeners.length; i++)
56703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
56803928aee4356845252ac6b662d5c72c29903813eJake Slack            EventListener listener = _eventListeners[i];
56903928aee4356845252ac6b662d5c72c29903813eJake Slack
57003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (listener instanceof ServletContextListener)
57103928aee4356845252ac6b662d5c72c29903813eJake Slack                _contextListeners = LazyList.add(_contextListeners,listener);
57203928aee4356845252ac6b662d5c72c29903813eJake Slack
57303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (listener instanceof ServletContextAttributeListener)
57403928aee4356845252ac6b662d5c72c29903813eJake Slack                _contextAttributeListeners = LazyList.add(_contextAttributeListeners,listener);
57503928aee4356845252ac6b662d5c72c29903813eJake Slack
57603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (listener instanceof ServletRequestListener)
57703928aee4356845252ac6b662d5c72c29903813eJake Slack                _requestListeners = LazyList.add(_requestListeners,listener);
57803928aee4356845252ac6b662d5c72c29903813eJake Slack
57903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (listener instanceof ServletRequestAttributeListener)
58003928aee4356845252ac6b662d5c72c29903813eJake Slack                _requestAttributeListeners = LazyList.add(_requestAttributeListeners,listener);
58103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
58203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
58303928aee4356845252ac6b662d5c72c29903813eJake Slack
58403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
58503928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
58603928aee4356845252ac6b662d5c72c29903813eJake Slack     * Add a context event listeners.
58703928aee4356845252ac6b662d5c72c29903813eJake Slack     *
58803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see ServletContextListener
58903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see ServletContextAttributeListener
59003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see ServletRequestListener
59103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see ServletRequestAttributeListener
59203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
59303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addEventListener(EventListener listener)
59403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
59503928aee4356845252ac6b662d5c72c29903813eJake Slack        //Only listeners added before the context starts last through a stop/start cycle
59603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!(isStarted() || isStarting()))
59703928aee4356845252ac6b662d5c72c29903813eJake Slack            _durableListeners = LazyList.add(_durableListeners, listener);
59803928aee4356845252ac6b662d5c72c29903813eJake Slack
59903928aee4356845252ac6b662d5c72c29903813eJake Slack        setEventListeners((EventListener[])LazyList.addToArray(getEventListeners(),listener,EventListener.class));
60003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
60103928aee4356845252ac6b662d5c72c29903813eJake Slack
60203928aee4356845252ac6b662d5c72c29903813eJake Slack
60303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
60403928aee4356845252ac6b662d5c72c29903813eJake Slack     * Apply any necessary restrictions on a programmatically added
60503928aee4356845252ac6b662d5c72c29903813eJake Slack     * listener.
60603928aee4356845252ac6b662d5c72c29903813eJake Slack     *
60703928aee4356845252ac6b662d5c72c29903813eJake Slack     * Superclasses should implement.
60803928aee4356845252ac6b662d5c72c29903813eJake Slack     *
60903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param listener
61003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
61103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void restrictEventListener (EventListener listener)
61203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
61303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
61403928aee4356845252ac6b662d5c72c29903813eJake Slack
61503928aee4356845252ac6b662d5c72c29903813eJake Slack
61603928aee4356845252ac6b662d5c72c29903813eJake Slack
61703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
61803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
61903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return true if this context is accepting new requests
62003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
62103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isShutdown()
62203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
62303928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
62403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
62503928aee4356845252ac6b662d5c72c29903813eJake Slack            return !_shutdown;
62603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
62703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
62803928aee4356845252ac6b662d5c72c29903813eJake Slack
62903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
63003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
63103928aee4356845252ac6b662d5c72c29903813eJake Slack     * Set shutdown status. This field allows for graceful shutdown of a context. A started context may be put into non accepting state so that existing
63203928aee4356845252ac6b662d5c72c29903813eJake Slack     * requests can complete, but no new requests are accepted.
63303928aee4356845252ac6b662d5c72c29903813eJake Slack     *
63403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param shutdown
63503928aee4356845252ac6b662d5c72c29903813eJake Slack     *            true if this context is (not?) accepting new requests
63603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
63703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setShutdown(boolean shutdown)
63803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
63903928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
64003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
64103928aee4356845252ac6b662d5c72c29903813eJake Slack            _shutdown = shutdown;
64203928aee4356845252ac6b662d5c72c29903813eJake Slack            _availability = isRunning()?(_shutdown?__SHUTDOWN:_available?__AVAILABLE:__UNAVAILABLE):__STOPPED;
64303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
64403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
64503928aee4356845252ac6b662d5c72c29903813eJake Slack
64603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
64703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
64803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return false if this context is unavailable (sends 503)
64903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
65003928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isAvailable()
65103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
65203928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
65303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
65403928aee4356845252ac6b662d5c72c29903813eJake Slack            return _available;
65503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
65603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
65703928aee4356845252ac6b662d5c72c29903813eJake Slack
65803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
65903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
66003928aee4356845252ac6b662d5c72c29903813eJake Slack     * Set Available status.
66103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
66203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setAvailable(boolean available)
66303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
66403928aee4356845252ac6b662d5c72c29903813eJake Slack        synchronized (this)
66503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
66603928aee4356845252ac6b662d5c72c29903813eJake Slack            _available = available;
66703928aee4356845252ac6b662d5c72c29903813eJake Slack            _availability = isRunning()?(_shutdown?__SHUTDOWN:_available?__AVAILABLE:__UNAVAILABLE):__STOPPED;
66803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
66903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
67003928aee4356845252ac6b662d5c72c29903813eJake Slack
67103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
67203928aee4356845252ac6b662d5c72c29903813eJake Slack    public Logger getLogger()
67303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
67403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _logger;
67503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
67603928aee4356845252ac6b662d5c72c29903813eJake Slack
67703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
67803928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setLogger(Logger logger)
67903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
68003928aee4356845252ac6b662d5c72c29903813eJake Slack        _logger = logger;
68103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
68203928aee4356845252ac6b662d5c72c29903813eJake Slack
68303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
68403928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
68503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.thread.AbstractLifeCycle#doStart()
68603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
68703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
68803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doStart() throws Exception
68903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
69003928aee4356845252ac6b662d5c72c29903813eJake Slack        _availability = __STOPPED;
69103928aee4356845252ac6b662d5c72c29903813eJake Slack
69203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_contextPath == null)
69303928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("Null contextPath");
69403928aee4356845252ac6b662d5c72c29903813eJake Slack
69503928aee4356845252ac6b662d5c72c29903813eJake Slack        _logger = Log.getLogger(getDisplayName() == null?getContextPath():getDisplayName());
69603928aee4356845252ac6b662d5c72c29903813eJake Slack        ClassLoader old_classloader = null;
69703928aee4356845252ac6b662d5c72c29903813eJake Slack        Thread current_thread = null;
69803928aee4356845252ac6b662d5c72c29903813eJake Slack        Context old_context = null;
69903928aee4356845252ac6b662d5c72c29903813eJake Slack
70003928aee4356845252ac6b662d5c72c29903813eJake Slack        try
70103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
70203928aee4356845252ac6b662d5c72c29903813eJake Slack            // Set the classloader
70303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_classLoader != null)
70403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
70503928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread = Thread.currentThread();
70603928aee4356845252ac6b662d5c72c29903813eJake Slack                old_classloader = current_thread.getContextClassLoader();
70703928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread.setContextClassLoader(_classLoader);
70803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
70903928aee4356845252ac6b662d5c72c29903813eJake Slack
71003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_mimeTypes == null)
71103928aee4356845252ac6b662d5c72c29903813eJake Slack                _mimeTypes = new MimeTypes();
71203928aee4356845252ac6b662d5c72c29903813eJake Slack
71303928aee4356845252ac6b662d5c72c29903813eJake Slack            old_context = __context.get();
71403928aee4356845252ac6b662d5c72c29903813eJake Slack            __context.set(_scontext);
71503928aee4356845252ac6b662d5c72c29903813eJake Slack
71603928aee4356845252ac6b662d5c72c29903813eJake Slack            // defers the calling of super.doStart()
71703928aee4356845252ac6b662d5c72c29903813eJake Slack            startContext();
71803928aee4356845252ac6b662d5c72c29903813eJake Slack
71903928aee4356845252ac6b662d5c72c29903813eJake Slack            synchronized(this)
72003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
72103928aee4356845252ac6b662d5c72c29903813eJake Slack                _availability = _shutdown?__SHUTDOWN:_available?__AVAILABLE:__UNAVAILABLE;
72203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
72303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
72403928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
72503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
72603928aee4356845252ac6b662d5c72c29903813eJake Slack            __context.set(old_context);
72703928aee4356845252ac6b662d5c72c29903813eJake Slack
72803928aee4356845252ac6b662d5c72c29903813eJake Slack            // reset the classloader
72903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_classLoader != null)
73003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
73103928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread.setContextClassLoader(old_classloader);
73203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
73303928aee4356845252ac6b662d5c72c29903813eJake Slack
73403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
73503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
73603928aee4356845252ac6b662d5c72c29903813eJake Slack
73703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
73803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
73903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Extensible startContext. this method is called from {@link ContextHandler#doStart()} instead of a call to super.doStart(). This allows derived classes to
74003928aee4356845252ac6b662d5c72c29903813eJake Slack     * insert additional handling (Eg configuration) before the call to super.doStart by this method will start contained handlers.
74103928aee4356845252ac6b662d5c72c29903813eJake Slack     *
74203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.server.handler.ContextHandler.Context
74303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
74403928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void startContext() throws Exception
74503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
74603928aee4356845252ac6b662d5c72c29903813eJake Slack        String managedAttributes = _initParams.get(MANAGED_ATTRIBUTES);
74703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (managedAttributes != null)
74803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
74903928aee4356845252ac6b662d5c72c29903813eJake Slack            _managedAttributes = new HashMap<String, Object>();
75003928aee4356845252ac6b662d5c72c29903813eJake Slack            String[] attributes = managedAttributes.split(",");
75103928aee4356845252ac6b662d5c72c29903813eJake Slack            for (String attribute : attributes)
75203928aee4356845252ac6b662d5c72c29903813eJake Slack                _managedAttributes.put(attribute,null);
75303928aee4356845252ac6b662d5c72c29903813eJake Slack
75403928aee4356845252ac6b662d5c72c29903813eJake Slack            Enumeration e = _scontext.getAttributeNames();
75503928aee4356845252ac6b662d5c72c29903813eJake Slack            while (e.hasMoreElements())
75603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
75703928aee4356845252ac6b662d5c72c29903813eJake Slack                String name = (String)e.nextElement();
75803928aee4356845252ac6b662d5c72c29903813eJake Slack                Object value = _scontext.getAttribute(name);
75903928aee4356845252ac6b662d5c72c29903813eJake Slack                checkManagedAttribute(name,value);
76003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
76103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
76203928aee4356845252ac6b662d5c72c29903813eJake Slack
76303928aee4356845252ac6b662d5c72c29903813eJake Slack        super.doStart();
76403928aee4356845252ac6b662d5c72c29903813eJake Slack
76503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_errorHandler != null)
76603928aee4356845252ac6b662d5c72c29903813eJake Slack            _errorHandler.start();
76703928aee4356845252ac6b662d5c72c29903813eJake Slack
76803928aee4356845252ac6b662d5c72c29903813eJake Slack        // Context listeners
76903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_contextListeners != null)
77003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
77103928aee4356845252ac6b662d5c72c29903813eJake Slack            ServletContextEvent event = new ServletContextEvent(_scontext);
77203928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i = 0; i < LazyList.size(_contextListeners); i++)
77303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
77403928aee4356845252ac6b662d5c72c29903813eJake Slack                callContextInitialized(((ServletContextListener)LazyList.get(_contextListeners, i)), event);
77503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
77603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
77703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
77803928aee4356845252ac6b662d5c72c29903813eJake Slack
77903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
78003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void callContextInitialized (ServletContextListener l, ServletContextEvent e)
78103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
78203928aee4356845252ac6b662d5c72c29903813eJake Slack        l.contextInitialized(e);
78303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
78403928aee4356845252ac6b662d5c72c29903813eJake Slack
78503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
78603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void callContextDestroyed (ServletContextListener l, ServletContextEvent e)
78703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
78803928aee4356845252ac6b662d5c72c29903813eJake Slack        l.contextDestroyed(e);
78903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
79003928aee4356845252ac6b662d5c72c29903813eJake Slack
79103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
79203928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
79303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.thread.AbstractLifeCycle#doStop()
79403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
79503928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
79603928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doStop() throws Exception
79703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
79803928aee4356845252ac6b662d5c72c29903813eJake Slack        _availability = __STOPPED;
79903928aee4356845252ac6b662d5c72c29903813eJake Slack
80003928aee4356845252ac6b662d5c72c29903813eJake Slack        ClassLoader old_classloader = null;
80103928aee4356845252ac6b662d5c72c29903813eJake Slack        Thread current_thread = null;
80203928aee4356845252ac6b662d5c72c29903813eJake Slack
80303928aee4356845252ac6b662d5c72c29903813eJake Slack        Context old_context = __context.get();
80403928aee4356845252ac6b662d5c72c29903813eJake Slack        __context.set(_scontext);
80503928aee4356845252ac6b662d5c72c29903813eJake Slack        try
80603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
80703928aee4356845252ac6b662d5c72c29903813eJake Slack            // Set the classloader
80803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_classLoader != null)
80903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
81003928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread = Thread.currentThread();
81103928aee4356845252ac6b662d5c72c29903813eJake Slack                old_classloader = current_thread.getContextClassLoader();
81203928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread.setContextClassLoader(_classLoader);
81303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
81403928aee4356845252ac6b662d5c72c29903813eJake Slack
81503928aee4356845252ac6b662d5c72c29903813eJake Slack            super.doStop();
81603928aee4356845252ac6b662d5c72c29903813eJake Slack
81703928aee4356845252ac6b662d5c72c29903813eJake Slack            // Context listeners
81803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_contextListeners != null)
81903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
82003928aee4356845252ac6b662d5c72c29903813eJake Slack                ServletContextEvent event = new ServletContextEvent(_scontext);
82103928aee4356845252ac6b662d5c72c29903813eJake Slack                for (int i = LazyList.size(_contextListeners); i-- > 0;)
82203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
82303928aee4356845252ac6b662d5c72c29903813eJake Slack                    ((ServletContextListener)LazyList.get(_contextListeners,i)).contextDestroyed(event);
82403928aee4356845252ac6b662d5c72c29903813eJake Slack                }
82503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
82603928aee4356845252ac6b662d5c72c29903813eJake Slack
82703928aee4356845252ac6b662d5c72c29903813eJake Slack            //remove all non-durable listeners
82803928aee4356845252ac6b662d5c72c29903813eJake Slack            setEventListeners((EventListener[])LazyList.toArray(_durableListeners, EventListener.class));
82903928aee4356845252ac6b662d5c72c29903813eJake Slack            _durableListeners = null;
83003928aee4356845252ac6b662d5c72c29903813eJake Slack
83103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_errorHandler != null)
83203928aee4356845252ac6b662d5c72c29903813eJake Slack                _errorHandler.stop();
83303928aee4356845252ac6b662d5c72c29903813eJake Slack
83403928aee4356845252ac6b662d5c72c29903813eJake Slack            Enumeration e = _scontext.getAttributeNames();
83503928aee4356845252ac6b662d5c72c29903813eJake Slack            while (e.hasMoreElements())
83603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
83703928aee4356845252ac6b662d5c72c29903813eJake Slack                String name = (String)e.nextElement();
83803928aee4356845252ac6b662d5c72c29903813eJake Slack                checkManagedAttribute(name,null);
83903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
84003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
84103928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
84203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
84303928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.info("stopped {}",this);
84403928aee4356845252ac6b662d5c72c29903813eJake Slack            __context.set(old_context);
84503928aee4356845252ac6b662d5c72c29903813eJake Slack            // reset the classloader
84603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_classLoader != null)
84703928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread.setContextClassLoader(old_classloader);
84803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
84903928aee4356845252ac6b662d5c72c29903813eJake Slack
85003928aee4356845252ac6b662d5c72c29903813eJake Slack        _contextAttributes.clearAttributes();
85103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
85203928aee4356845252ac6b662d5c72c29903813eJake Slack
85303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
85403928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
85503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
85603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
85703928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException, ServletException
85803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
85903928aee4356845252ac6b662d5c72c29903813eJake Slack        DispatcherType dispatch = baseRequest.getDispatcherType();
86003928aee4356845252ac6b662d5c72c29903813eJake Slack
86103928aee4356845252ac6b662d5c72c29903813eJake Slack        switch (_availability)
86203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
86303928aee4356845252ac6b662d5c72c29903813eJake Slack            case __STOPPED:
86403928aee4356845252ac6b662d5c72c29903813eJake Slack            case __SHUTDOWN:
86503928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
86603928aee4356845252ac6b662d5c72c29903813eJake Slack            case __UNAVAILABLE:
86703928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setHandled(true);
86803928aee4356845252ac6b662d5c72c29903813eJake Slack                response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
86903928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
87003928aee4356845252ac6b662d5c72c29903813eJake Slack            default:
87103928aee4356845252ac6b662d5c72c29903813eJake Slack                if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
87203928aee4356845252ac6b662d5c72c29903813eJake Slack                    return false;
87303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
87403928aee4356845252ac6b662d5c72c29903813eJake Slack
87503928aee4356845252ac6b662d5c72c29903813eJake Slack        // Check the vhosts
87603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_vhosts != null && _vhosts.length > 0)
87703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
87803928aee4356845252ac6b662d5c72c29903813eJake Slack            String vhost = normalizeHostname(baseRequest.getServerName());
87903928aee4356845252ac6b662d5c72c29903813eJake Slack
88003928aee4356845252ac6b662d5c72c29903813eJake Slack            boolean match = false;
88103928aee4356845252ac6b662d5c72c29903813eJake Slack
88203928aee4356845252ac6b662d5c72c29903813eJake Slack            // TODO non-linear lookup
88303928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int i = 0; !match && i < _vhosts.length; i++)
88403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
88503928aee4356845252ac6b662d5c72c29903813eJake Slack                String contextVhost = _vhosts[i];
88603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (contextVhost == null)
88703928aee4356845252ac6b662d5c72c29903813eJake Slack                    continue;
88803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (contextVhost.startsWith("*."))
88903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
89003928aee4356845252ac6b662d5c72c29903813eJake Slack                    // wildcard only at the beginning, and only for one additional subdomain level
89103928aee4356845252ac6b662d5c72c29903813eJake Slack                    match = contextVhost.regionMatches(true,2,vhost,vhost.indexOf(".") + 1,contextVhost.length() - 2);
89203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
89303928aee4356845252ac6b662d5c72c29903813eJake Slack                else
89403928aee4356845252ac6b662d5c72c29903813eJake Slack                    match = contextVhost.equalsIgnoreCase(vhost);
89503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
89603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!match)
89703928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
89803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
89903928aee4356845252ac6b662d5c72c29903813eJake Slack
90003928aee4356845252ac6b662d5c72c29903813eJake Slack        // Check the connector
90103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_connectors != null && _connectors.size() > 0)
90203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
90303928aee4356845252ac6b662d5c72c29903813eJake Slack            String connector = AbstractHttpConnection.getCurrentConnection().getConnector().getName();
90403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (connector == null || !_connectors.contains(connector))
90503928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
90603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
90703928aee4356845252ac6b662d5c72c29903813eJake Slack
90803928aee4356845252ac6b662d5c72c29903813eJake Slack        // Are we not the root context?
90903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_contextPath.length() > 1)
91003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
91103928aee4356845252ac6b662d5c72c29903813eJake Slack            // reject requests that are not for us
91203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!target.startsWith(_contextPath))
91303928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
91403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (target.length() > _contextPath.length() && target.charAt(_contextPath.length()) != '/')
91503928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
91603928aee4356845252ac6b662d5c72c29903813eJake Slack
91703928aee4356845252ac6b662d5c72c29903813eJake Slack            // redirect null path infos
91803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!_allowNullPathInfo && _contextPath.length() == target.length())
91903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
92003928aee4356845252ac6b662d5c72c29903813eJake Slack                // context request must end with /
92103928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setHandled(true);
92203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (baseRequest.getQueryString() != null)
92303928aee4356845252ac6b662d5c72c29903813eJake Slack                    response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString());
92403928aee4356845252ac6b662d5c72c29903813eJake Slack                else
92503928aee4356845252ac6b662d5c72c29903813eJake Slack                    response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
92603928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
92703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
92803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
92903928aee4356845252ac6b662d5c72c29903813eJake Slack
93003928aee4356845252ac6b662d5c72c29903813eJake Slack        return true;
93103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
93203928aee4356845252ac6b662d5c72c29903813eJake Slack
93303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
93403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
93503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.server.handler.ScopedHandler#doScope(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest,
93603928aee4356845252ac6b662d5c72c29903813eJake Slack     *      javax.servlet.http.HttpServletResponse)
93703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
93803928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
93903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
94003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
94103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (LOG.isDebugEnabled())
94203928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug("scope {}|{}|{} @ {}",baseRequest.getContextPath(),baseRequest.getServletPath(),baseRequest.getPathInfo(),this);
94303928aee4356845252ac6b662d5c72c29903813eJake Slack
94403928aee4356845252ac6b662d5c72c29903813eJake Slack        Context old_context = null;
94503928aee4356845252ac6b662d5c72c29903813eJake Slack        String old_context_path = null;
94603928aee4356845252ac6b662d5c72c29903813eJake Slack        String old_servlet_path = null;
94703928aee4356845252ac6b662d5c72c29903813eJake Slack        String old_path_info = null;
94803928aee4356845252ac6b662d5c72c29903813eJake Slack        ClassLoader old_classloader = null;
94903928aee4356845252ac6b662d5c72c29903813eJake Slack        Thread current_thread = null;
95003928aee4356845252ac6b662d5c72c29903813eJake Slack        String pathInfo = target;
95103928aee4356845252ac6b662d5c72c29903813eJake Slack
95203928aee4356845252ac6b662d5c72c29903813eJake Slack        DispatcherType dispatch = baseRequest.getDispatcherType();
95303928aee4356845252ac6b662d5c72c29903813eJake Slack
95403928aee4356845252ac6b662d5c72c29903813eJake Slack        old_context = baseRequest.getContext();
95503928aee4356845252ac6b662d5c72c29903813eJake Slack
95603928aee4356845252ac6b662d5c72c29903813eJake Slack        // Are we already in this context?
95703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (old_context != _scontext)
95803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
95903928aee4356845252ac6b662d5c72c29903813eJake Slack            // check the target.
96003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (DispatcherType.REQUEST.equals(dispatch) || DispatcherType.ASYNC.equals(dispatch) || (DispatcherType.ERROR.equals(dispatch) && baseRequest.getAsyncContinuation().isExpired()))
96103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
96203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_compactPath)
96303928aee4356845252ac6b662d5c72c29903813eJake Slack                    target = URIUtil.compactPath(target);
96403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!checkContext(target,baseRequest,response))
96503928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
96603928aee4356845252ac6b662d5c72c29903813eJake Slack
96703928aee4356845252ac6b662d5c72c29903813eJake Slack                if (target.length() > _contextPath.length())
96803928aee4356845252ac6b662d5c72c29903813eJake Slack                {
96903928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_contextPath.length() > 1)
97003928aee4356845252ac6b662d5c72c29903813eJake Slack                        target = target.substring(_contextPath.length());
97103928aee4356845252ac6b662d5c72c29903813eJake Slack                    pathInfo = target;
97203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
97303928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (_contextPath.length() == 1)
97403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
97503928aee4356845252ac6b662d5c72c29903813eJake Slack                    target = URIUtil.SLASH;
97603928aee4356845252ac6b662d5c72c29903813eJake Slack                    pathInfo = URIUtil.SLASH;
97703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
97803928aee4356845252ac6b662d5c72c29903813eJake Slack                else
97903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
98003928aee4356845252ac6b662d5c72c29903813eJake Slack                    target = URIUtil.SLASH;
98103928aee4356845252ac6b662d5c72c29903813eJake Slack                    pathInfo = null;
98203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
98303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
98403928aee4356845252ac6b662d5c72c29903813eJake Slack
98503928aee4356845252ac6b662d5c72c29903813eJake Slack            // Set the classloader
98603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_classLoader != null)
98703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
98803928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread = Thread.currentThread();
98903928aee4356845252ac6b662d5c72c29903813eJake Slack                old_classloader = current_thread.getContextClassLoader();
99003928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread.setContextClassLoader(_classLoader);
99103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
99203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
99303928aee4356845252ac6b662d5c72c29903813eJake Slack
99403928aee4356845252ac6b662d5c72c29903813eJake Slack        try
99503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
99603928aee4356845252ac6b662d5c72c29903813eJake Slack            old_context_path = baseRequest.getContextPath();
99703928aee4356845252ac6b662d5c72c29903813eJake Slack            old_servlet_path = baseRequest.getServletPath();
99803928aee4356845252ac6b662d5c72c29903813eJake Slack            old_path_info = baseRequest.getPathInfo();
99903928aee4356845252ac6b662d5c72c29903813eJake Slack
100003928aee4356845252ac6b662d5c72c29903813eJake Slack            // Update the paths
100103928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setContext(_scontext);
100203928aee4356845252ac6b662d5c72c29903813eJake Slack            __context.set(_scontext);
100303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!DispatcherType.INCLUDE.equals(dispatch) && target.startsWith("/"))
100403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
100503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_contextPath.length() == 1)
100603928aee4356845252ac6b662d5c72c29903813eJake Slack                    baseRequest.setContextPath("");
100703928aee4356845252ac6b662d5c72c29903813eJake Slack                else
100803928aee4356845252ac6b662d5c72c29903813eJake Slack                    baseRequest.setContextPath(_contextPath);
100903928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setServletPath(null);
101003928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setPathInfo(pathInfo);
101103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
101203928aee4356845252ac6b662d5c72c29903813eJake Slack
101303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
101403928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("context={}|{}|{} @ {}",baseRequest.getContextPath(),baseRequest.getServletPath(), baseRequest.getPathInfo(),this);
101503928aee4356845252ac6b662d5c72c29903813eJake Slack
101603928aee4356845252ac6b662d5c72c29903813eJake Slack            // start manual inline of nextScope(target,baseRequest,request,response);
101703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (never())
101803928aee4356845252ac6b662d5c72c29903813eJake Slack                nextScope(target,baseRequest,request,response);
101903928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (_nextScope != null)
102003928aee4356845252ac6b662d5c72c29903813eJake Slack                _nextScope.doScope(target,baseRequest,request,response);
102103928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (_outerScope != null)
102203928aee4356845252ac6b662d5c72c29903813eJake Slack                _outerScope.doHandle(target,baseRequest,request,response);
102303928aee4356845252ac6b662d5c72c29903813eJake Slack            else
102403928aee4356845252ac6b662d5c72c29903813eJake Slack                doHandle(target,baseRequest,request,response);
102503928aee4356845252ac6b662d5c72c29903813eJake Slack            // end manual inline (pathentic attempt to reduce stack depth)
102603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
102703928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
102803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
102903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (old_context != _scontext)
103003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
103103928aee4356845252ac6b662d5c72c29903813eJake Slack                // reset the classloader
103203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_classLoader != null)
103303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
103403928aee4356845252ac6b662d5c72c29903813eJake Slack                    current_thread.setContextClassLoader(old_classloader);
103503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
103603928aee4356845252ac6b662d5c72c29903813eJake Slack
103703928aee4356845252ac6b662d5c72c29903813eJake Slack                // reset the context and servlet path.
103803928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setContext(old_context);
103903928aee4356845252ac6b662d5c72c29903813eJake Slack                __context.set(old_context);
104003928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setContextPath(old_context_path);
104103928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setServletPath(old_servlet_path);
104203928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setPathInfo(old_path_info);
104303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
104403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
104503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
104603928aee4356845252ac6b662d5c72c29903813eJake Slack
104703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
104803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
104903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.server.handler.ScopedHandler#doHandle(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest,
105003928aee4356845252ac6b662d5c72c29903813eJake Slack     *      javax.servlet.http.HttpServletResponse)
105103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
105203928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
105303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
105403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
105503928aee4356845252ac6b662d5c72c29903813eJake Slack        final DispatcherType dispatch = baseRequest.getDispatcherType();
105603928aee4356845252ac6b662d5c72c29903813eJake Slack        final boolean new_context = baseRequest.takeNewContext();
105703928aee4356845252ac6b662d5c72c29903813eJake Slack        try
105803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
105903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (new_context)
106003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
106103928aee4356845252ac6b662d5c72c29903813eJake Slack                // Handle the REALLY SILLY request events!
106203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_requestAttributeListeners != null)
106303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
106403928aee4356845252ac6b662d5c72c29903813eJake Slack                    final int s = LazyList.size(_requestAttributeListeners);
106503928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int i = 0; i < s; i++)
106603928aee4356845252ac6b662d5c72c29903813eJake Slack                        baseRequest.addEventListener(((EventListener)LazyList.get(_requestAttributeListeners,i)));
106703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
106803928aee4356845252ac6b662d5c72c29903813eJake Slack
106903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_requestListeners != null)
107003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
107103928aee4356845252ac6b662d5c72c29903813eJake Slack                    final int s = LazyList.size(_requestListeners);
107203928aee4356845252ac6b662d5c72c29903813eJake Slack                    final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request);
107303928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int i = 0; i < s; i++)
107403928aee4356845252ac6b662d5c72c29903813eJake Slack                        ((ServletRequestListener)LazyList.get(_requestListeners,i)).requestInitialized(sre);
107503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
107603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
107703928aee4356845252ac6b662d5c72c29903813eJake Slack
107803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (DispatcherType.REQUEST.equals(dispatch) && isProtectedTarget(target))
107903928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new HttpException(HttpServletResponse.SC_NOT_FOUND);
108003928aee4356845252ac6b662d5c72c29903813eJake Slack
108103928aee4356845252ac6b662d5c72c29903813eJake Slack            // start manual inline of nextHandle(target,baseRequest,request,response);
108203928aee4356845252ac6b662d5c72c29903813eJake Slack            // noinspection ConstantIfStatement
108303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (never())
108403928aee4356845252ac6b662d5c72c29903813eJake Slack                nextHandle(target,baseRequest,request,response);
108503928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (_nextScope != null && _nextScope == _handler)
108603928aee4356845252ac6b662d5c72c29903813eJake Slack                _nextScope.doHandle(target,baseRequest,request,response);
108703928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (_handler != null)
108803928aee4356845252ac6b662d5c72c29903813eJake Slack                _handler.handle(target,baseRequest,request,response);
108903928aee4356845252ac6b662d5c72c29903813eJake Slack            // end manual inline
109003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
109103928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (HttpException e)
109203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
109303928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug(e);
109403928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setHandled(true);
109503928aee4356845252ac6b662d5c72c29903813eJake Slack            response.sendError(e.getStatus(),e.getReason());
109603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
109703928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
109803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
109903928aee4356845252ac6b662d5c72c29903813eJake Slack            // Handle more REALLY SILLY request events!
110003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (new_context)
110103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
110203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_requestListeners != null)
110303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
110403928aee4356845252ac6b662d5c72c29903813eJake Slack                    final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request);
110503928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int i = LazyList.size(_requestListeners); i-- > 0;)
110603928aee4356845252ac6b662d5c72c29903813eJake Slack                        ((ServletRequestListener)LazyList.get(_requestListeners,i)).requestDestroyed(sre);
110703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
110803928aee4356845252ac6b662d5c72c29903813eJake Slack
110903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_requestAttributeListeners != null)
111003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
111103928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int i = LazyList.size(_requestAttributeListeners); i-- > 0;)
111203928aee4356845252ac6b662d5c72c29903813eJake Slack                        baseRequest.removeEventListener(((EventListener)LazyList.get(_requestAttributeListeners,i)));
111303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
111403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
111503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
111603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
111703928aee4356845252ac6b662d5c72c29903813eJake Slack
111803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
111903928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
112003928aee4356845252ac6b662d5c72c29903813eJake Slack     * Handle a runnable in this context
112103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
112203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void handle(Runnable runnable)
112303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
112403928aee4356845252ac6b662d5c72c29903813eJake Slack        ClassLoader old_classloader = null;
112503928aee4356845252ac6b662d5c72c29903813eJake Slack        Thread current_thread = null;
112603928aee4356845252ac6b662d5c72c29903813eJake Slack        Context old_context = null;
112703928aee4356845252ac6b662d5c72c29903813eJake Slack        try
112803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
112903928aee4356845252ac6b662d5c72c29903813eJake Slack            old_context = __context.get();
113003928aee4356845252ac6b662d5c72c29903813eJake Slack            __context.set(_scontext);
113103928aee4356845252ac6b662d5c72c29903813eJake Slack
113203928aee4356845252ac6b662d5c72c29903813eJake Slack            // Set the classloader
113303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_classLoader != null)
113403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
113503928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread = Thread.currentThread();
113603928aee4356845252ac6b662d5c72c29903813eJake Slack                old_classloader = current_thread.getContextClassLoader();
113703928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread.setContextClassLoader(_classLoader);
113803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
113903928aee4356845252ac6b662d5c72c29903813eJake Slack
114003928aee4356845252ac6b662d5c72c29903813eJake Slack            runnable.run();
114103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
114203928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
114303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
114403928aee4356845252ac6b662d5c72c29903813eJake Slack            __context.set(old_context);
114503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (old_classloader != null)
114603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
114703928aee4356845252ac6b662d5c72c29903813eJake Slack                current_thread.setContextClassLoader(old_classloader);
114803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
114903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
115003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
115103928aee4356845252ac6b662d5c72c29903813eJake Slack
115203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
115303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
115403928aee4356845252ac6b662d5c72c29903813eJake Slack     * Check the target. Called by {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)} when a target within a context is determined. If
115503928aee4356845252ac6b662d5c72c29903813eJake Slack     * the target is protected, 404 is returned.
115603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
115703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
115803928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isProtectedTarget(String target)
115903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
116003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (target == null || _protectedTargets == null)
116103928aee4356845252ac6b662d5c72c29903813eJake Slack            return false;
116203928aee4356845252ac6b662d5c72c29903813eJake Slack
116303928aee4356845252ac6b662d5c72c29903813eJake Slack        while (target.startsWith("//"))
116403928aee4356845252ac6b662d5c72c29903813eJake Slack            target=URIUtil.compactPath(target);
116503928aee4356845252ac6b662d5c72c29903813eJake Slack
116603928aee4356845252ac6b662d5c72c29903813eJake Slack        boolean isProtected = false;
116703928aee4356845252ac6b662d5c72c29903813eJake Slack        int i=0;
116803928aee4356845252ac6b662d5c72c29903813eJake Slack        while (!isProtected && i<_protectedTargets.length)
116903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
117003928aee4356845252ac6b662d5c72c29903813eJake Slack            isProtected = StringUtil.startsWithIgnoreCase(target, _protectedTargets[i++]);
117103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
117203928aee4356845252ac6b662d5c72c29903813eJake Slack        return isProtected;
117303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
117403928aee4356845252ac6b662d5c72c29903813eJake Slack
117503928aee4356845252ac6b662d5c72c29903813eJake Slack
117603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setProtectedTargets (String[] targets)
117703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
117803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (targets == null)
117903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
118003928aee4356845252ac6b662d5c72c29903813eJake Slack            _protectedTargets = null;
118103928aee4356845252ac6b662d5c72c29903813eJake Slack            return;
118203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
118303928aee4356845252ac6b662d5c72c29903813eJake Slack
118403928aee4356845252ac6b662d5c72c29903813eJake Slack        _protectedTargets = new String[targets.length];
118503928aee4356845252ac6b662d5c72c29903813eJake Slack        System.arraycopy(targets, 0, _protectedTargets, 0, targets.length);
118603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
118703928aee4356845252ac6b662d5c72c29903813eJake Slack
118803928aee4356845252ac6b662d5c72c29903813eJake Slack    public String[] getProtectedTargets ()
118903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
119003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_protectedTargets == null)
119103928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
119203928aee4356845252ac6b662d5c72c29903813eJake Slack
119303928aee4356845252ac6b662d5c72c29903813eJake Slack        String[] tmp = new String[_protectedTargets.length];
119403928aee4356845252ac6b662d5c72c29903813eJake Slack        System.arraycopy(_protectedTargets, 0, tmp, 0, _protectedTargets.length);
119503928aee4356845252ac6b662d5c72c29903813eJake Slack        return tmp;
119603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
119703928aee4356845252ac6b662d5c72c29903813eJake Slack
119803928aee4356845252ac6b662d5c72c29903813eJake Slack
119903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
120003928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
120103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
120203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
120303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void removeAttribute(String name)
120403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
120503928aee4356845252ac6b662d5c72c29903813eJake Slack        checkManagedAttribute(name,null);
120603928aee4356845252ac6b662d5c72c29903813eJake Slack        _attributes.removeAttribute(name);
120703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
120803928aee4356845252ac6b662d5c72c29903813eJake Slack
120903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
121003928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
121103928aee4356845252ac6b662d5c72c29903813eJake Slack     * Set a context attribute. Attributes set via this API cannot be overriden by the ServletContext.setAttribute API. Their lifecycle spans the stop/start of
121203928aee4356845252ac6b662d5c72c29903813eJake Slack     * a context. No attribute listener events are triggered by this API.
121303928aee4356845252ac6b662d5c72c29903813eJake Slack     *
121403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object)
121503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
121603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setAttribute(String name, Object value)
121703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
121803928aee4356845252ac6b662d5c72c29903813eJake Slack        checkManagedAttribute(name,value);
121903928aee4356845252ac6b662d5c72c29903813eJake Slack        _attributes.setAttribute(name,value);
122003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
122103928aee4356845252ac6b662d5c72c29903813eJake Slack
122203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
122303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
122403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param attributes
122503928aee4356845252ac6b662d5c72c29903813eJake Slack     *            The attributes to set.
122603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
122703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setAttributes(Attributes attributes)
122803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
122903928aee4356845252ac6b662d5c72c29903813eJake Slack        _attributes.clearAttributes();
123003928aee4356845252ac6b662d5c72c29903813eJake Slack        _attributes.addAll(attributes);
123103928aee4356845252ac6b662d5c72c29903813eJake Slack        Enumeration e = _attributes.getAttributeNames();
123203928aee4356845252ac6b662d5c72c29903813eJake Slack        while (e.hasMoreElements())
123303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
123403928aee4356845252ac6b662d5c72c29903813eJake Slack            String name = (String)e.nextElement();
123503928aee4356845252ac6b662d5c72c29903813eJake Slack            checkManagedAttribute(name,attributes.getAttribute(name));
123603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
123703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
123803928aee4356845252ac6b662d5c72c29903813eJake Slack
123903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
124003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void clearAttributes()
124103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
124203928aee4356845252ac6b662d5c72c29903813eJake Slack        Enumeration e = _attributes.getAttributeNames();
124303928aee4356845252ac6b662d5c72c29903813eJake Slack        while (e.hasMoreElements())
124403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
124503928aee4356845252ac6b662d5c72c29903813eJake Slack            String name = (String)e.nextElement();
124603928aee4356845252ac6b662d5c72c29903813eJake Slack            checkManagedAttribute(name,null);
124703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
124803928aee4356845252ac6b662d5c72c29903813eJake Slack        _attributes.clearAttributes();
124903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
125003928aee4356845252ac6b662d5c72c29903813eJake Slack
125103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
125203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void checkManagedAttribute(String name, Object value)
125303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
125403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_managedAttributes != null && _managedAttributes.containsKey(name))
125503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
125603928aee4356845252ac6b662d5c72c29903813eJake Slack            setManagedAttribute(name,value);
125703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
125803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
125903928aee4356845252ac6b662d5c72c29903813eJake Slack
126003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
126103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setManagedAttribute(String name, Object value)
126203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
126303928aee4356845252ac6b662d5c72c29903813eJake Slack        Object old = _managedAttributes.put(name,value);
126403928aee4356845252ac6b662d5c72c29903813eJake Slack        getServer().getContainer().update(this,old,value,name,true);
126503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
126603928aee4356845252ac6b662d5c72c29903813eJake Slack
126703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
126803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
126903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param classLoader
127003928aee4356845252ac6b662d5c72c29903813eJake Slack     *            The classLoader to set.
127103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
127203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setClassLoader(ClassLoader classLoader)
127303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
127403928aee4356845252ac6b662d5c72c29903813eJake Slack        _classLoader = classLoader;
127503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
127603928aee4356845252ac6b662d5c72c29903813eJake Slack
127703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
127803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
127903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param contextPath
128003928aee4356845252ac6b662d5c72c29903813eJake Slack     *            The _contextPath to set.
128103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
128203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setContextPath(String contextPath)
128303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
128403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (contextPath != null && contextPath.length() > 1 && contextPath.endsWith("/"))
128503928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalArgumentException("ends with /");
128603928aee4356845252ac6b662d5c72c29903813eJake Slack        _contextPath = contextPath;
128703928aee4356845252ac6b662d5c72c29903813eJake Slack
128803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (getServer() != null && (getServer().isStarting() || getServer().isStarted()))
128903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
129003928aee4356845252ac6b662d5c72c29903813eJake Slack            Handler[] contextCollections = getServer().getChildHandlersByClass(ContextHandlerCollection.class);
129103928aee4356845252ac6b662d5c72c29903813eJake Slack            for (int h = 0; contextCollections != null && h < contextCollections.length; h++)
129203928aee4356845252ac6b662d5c72c29903813eJake Slack                ((ContextHandlerCollection)contextCollections[h]).mapContexts();
129303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
129403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
129503928aee4356845252ac6b662d5c72c29903813eJake Slack
129603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
129703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
129803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param servletContextName
129903928aee4356845252ac6b662d5c72c29903813eJake Slack     *            The servletContextName to set.
130003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
130103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setDisplayName(String servletContextName)
130203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
130303928aee4356845252ac6b662d5c72c29903813eJake Slack        _displayName = servletContextName;
130403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
130503928aee4356845252ac6b662d5c72c29903813eJake Slack
130603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
130703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
130803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the resourceBase.
130903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
131003928aee4356845252ac6b662d5c72c29903813eJake Slack    public Resource getBaseResource()
131103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
131203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_baseResource == null)
131303928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
131403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _baseResource;
131503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
131603928aee4356845252ac6b662d5c72c29903813eJake Slack
131703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
131803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
131903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the base resource as a string.
132003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
132103928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getResourceBase()
132203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
132303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_baseResource == null)
132403928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
132503928aee4356845252ac6b662d5c72c29903813eJake Slack        return _baseResource.toString();
132603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
132703928aee4356845252ac6b662d5c72c29903813eJake Slack
132803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
132903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
133003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param base
133103928aee4356845252ac6b662d5c72c29903813eJake Slack     *            The resourceBase to set.
133203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
133303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setBaseResource(Resource base)
133403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
133503928aee4356845252ac6b662d5c72c29903813eJake Slack        _baseResource = base;
133603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
133703928aee4356845252ac6b662d5c72c29903813eJake Slack
133803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
133903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
134003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param resourceBase
134103928aee4356845252ac6b662d5c72c29903813eJake Slack     *            The base resource as a string.
134203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
134303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setResourceBase(String resourceBase)
134403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
134503928aee4356845252ac6b662d5c72c29903813eJake Slack        try
134603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
134703928aee4356845252ac6b662d5c72c29903813eJake Slack            setBaseResource(newResource(resourceBase));
134803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
134903928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (Exception e)
135003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
135103928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(e.toString());
135203928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug(e);
135303928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalArgumentException(resourceBase);
135403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
135503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
135603928aee4356845252ac6b662d5c72c29903813eJake Slack
135703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
135803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
135903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return True if aliases are allowed
136003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
136103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isAliases()
136203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
136303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _aliasesAllowed;
136403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
136503928aee4356845252ac6b662d5c72c29903813eJake Slack
136603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
136703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
136803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param aliases
136903928aee4356845252ac6b662d5c72c29903813eJake Slack     *            aliases are allowed
137003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
137103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setAliases(boolean aliases)
137203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
137303928aee4356845252ac6b662d5c72c29903813eJake Slack        _aliasesAllowed = aliases;
137403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
137503928aee4356845252ac6b662d5c72c29903813eJake Slack
137603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
137703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
137803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the mimeTypes.
137903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
138003928aee4356845252ac6b662d5c72c29903813eJake Slack    public MimeTypes getMimeTypes()
138103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
138203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_mimeTypes == null)
138303928aee4356845252ac6b662d5c72c29903813eJake Slack            _mimeTypes = new MimeTypes();
138403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _mimeTypes;
138503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
138603928aee4356845252ac6b662d5c72c29903813eJake Slack
138703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
138803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
138903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param mimeTypes
139003928aee4356845252ac6b662d5c72c29903813eJake Slack     *            The mimeTypes to set.
139103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
139203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setMimeTypes(MimeTypes mimeTypes)
139303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
139403928aee4356845252ac6b662d5c72c29903813eJake Slack        _mimeTypes = mimeTypes;
139503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
139603928aee4356845252ac6b662d5c72c29903813eJake Slack
139703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
139803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
139903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
140003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setWelcomeFiles(String[] files)
140103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
140203928aee4356845252ac6b662d5c72c29903813eJake Slack        _welcomeFiles = files;
140303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
140403928aee4356845252ac6b662d5c72c29903813eJake Slack
140503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
140603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
140703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The names of the files which the server should consider to be welcome files in this context.
140803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see <a href="http://jcp.org/aboutJava/communityprocess/final/jsr154/index.html">The Servlet Specification</a>
140903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see #setWelcomeFiles
141003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
141103928aee4356845252ac6b662d5c72c29903813eJake Slack    public String[] getWelcomeFiles()
141203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
141303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _welcomeFiles;
141403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
141503928aee4356845252ac6b662d5c72c29903813eJake Slack
141603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
141703928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
141803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the errorHandler.
141903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
142003928aee4356845252ac6b662d5c72c29903813eJake Slack    public ErrorHandler getErrorHandler()
142103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
142203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _errorHandler;
142303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
142403928aee4356845252ac6b662d5c72c29903813eJake Slack
142503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
142603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
142703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param errorHandler
142803928aee4356845252ac6b662d5c72c29903813eJake Slack     *            The errorHandler to set.
142903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
143003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setErrorHandler(ErrorHandler errorHandler)
143103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
143203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (errorHandler != null)
143303928aee4356845252ac6b662d5c72c29903813eJake Slack            errorHandler.setServer(getServer());
143403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (getServer() != null)
143503928aee4356845252ac6b662d5c72c29903813eJake Slack            getServer().getContainer().update(this,_errorHandler,errorHandler,"errorHandler",true);
143603928aee4356845252ac6b662d5c72c29903813eJake Slack        _errorHandler = errorHandler;
143703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
143803928aee4356845252ac6b662d5c72c29903813eJake Slack
143903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
144003928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getMaxFormContentSize()
144103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
144203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _maxFormContentSize;
144303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
144403928aee4356845252ac6b662d5c72c29903813eJake Slack
144503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
144603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
144703928aee4356845252ac6b662d5c72c29903813eJake Slack     * Set the maximum size of a form post, to protect against DOS attacks from large forms.
144803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param maxSize
144903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
145003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setMaxFormContentSize(int maxSize)
145103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
145203928aee4356845252ac6b662d5c72c29903813eJake Slack        _maxFormContentSize = maxSize;
145303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
145403928aee4356845252ac6b662d5c72c29903813eJake Slack
145503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
145603928aee4356845252ac6b662d5c72c29903813eJake Slack    public int getMaxFormKeys()
145703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
145803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _maxFormKeys;
145903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
146003928aee4356845252ac6b662d5c72c29903813eJake Slack
146103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
146203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
146303928aee4356845252ac6b662d5c72c29903813eJake Slack     * Set the maximum number of form Keys to protect against DOS attack from crafted hash keys.
146403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param max
146503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
146603928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setMaxFormKeys(int max)
146703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
146803928aee4356845252ac6b662d5c72c29903813eJake Slack        _maxFormKeys = max;
146903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
147003928aee4356845252ac6b662d5c72c29903813eJake Slack
147103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
147203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
147303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return True if URLs are compacted to replace multiple '/'s with a single '/'
147403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
147503928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isCompactPath()
147603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
147703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _compactPath;
147803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
147903928aee4356845252ac6b662d5c72c29903813eJake Slack
148003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
148103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
148203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param compactPath
148303928aee4356845252ac6b662d5c72c29903813eJake Slack     *            True if URLs are compacted to replace multiple '/'s with a single '/'
148403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
148503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setCompactPath(boolean compactPath)
148603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
148703928aee4356845252ac6b662d5c72c29903813eJake Slack        _compactPath = compactPath;
148803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
148903928aee4356845252ac6b662d5c72c29903813eJake Slack
149003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
149103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
149203928aee4356845252ac6b662d5c72c29903813eJake Slack    public String toString()
149303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
149403928aee4356845252ac6b662d5c72c29903813eJake Slack        String[] vhosts = getVirtualHosts();
149503928aee4356845252ac6b662d5c72c29903813eJake Slack
149603928aee4356845252ac6b662d5c72c29903813eJake Slack        StringBuilder b = new StringBuilder();
149703928aee4356845252ac6b662d5c72c29903813eJake Slack
149803928aee4356845252ac6b662d5c72c29903813eJake Slack        Package pkg = getClass().getPackage();
149903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (pkg != null)
150003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
150103928aee4356845252ac6b662d5c72c29903813eJake Slack            String p = pkg.getName();
150203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (p != null && p.length() > 0)
150303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
150403928aee4356845252ac6b662d5c72c29903813eJake Slack                String[] ss = p.split("\\.");
150503928aee4356845252ac6b662d5c72c29903813eJake Slack                for (String s : ss)
150603928aee4356845252ac6b662d5c72c29903813eJake Slack                    b.append(s.charAt(0)).append('.');
150703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
150803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
150903928aee4356845252ac6b662d5c72c29903813eJake Slack        b.append(getClass().getSimpleName());
151003928aee4356845252ac6b662d5c72c29903813eJake Slack        b.append('{').append(getContextPath()).append(',').append(getBaseResource());
151103928aee4356845252ac6b662d5c72c29903813eJake Slack
151203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (vhosts != null && vhosts.length > 0)
151303928aee4356845252ac6b662d5c72c29903813eJake Slack            b.append(',').append(vhosts[0]);
151403928aee4356845252ac6b662d5c72c29903813eJake Slack        b.append('}');
151503928aee4356845252ac6b662d5c72c29903813eJake Slack
151603928aee4356845252ac6b662d5c72c29903813eJake Slack        return b.toString();
151703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
151803928aee4356845252ac6b662d5c72c29903813eJake Slack
151903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
152003928aee4356845252ac6b662d5c72c29903813eJake Slack    public synchronized Class<?> loadClass(String className) throws ClassNotFoundException
152103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
152203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (className == null)
152303928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
152403928aee4356845252ac6b662d5c72c29903813eJake Slack
152503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_classLoader == null)
152603928aee4356845252ac6b662d5c72c29903813eJake Slack            return Loader.loadClass(this.getClass(),className);
152703928aee4356845252ac6b662d5c72c29903813eJake Slack
152803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _classLoader.loadClass(className);
152903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
153003928aee4356845252ac6b662d5c72c29903813eJake Slack
153103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
153203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addLocaleEncoding(String locale, String encoding)
153303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
153403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_localeEncodingMap == null)
153503928aee4356845252ac6b662d5c72c29903813eJake Slack            _localeEncodingMap = new HashMap<String, String>();
153603928aee4356845252ac6b662d5c72c29903813eJake Slack        _localeEncodingMap.put(locale,encoding);
153703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
153803928aee4356845252ac6b662d5c72c29903813eJake Slack
153903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
154003928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getLocaleEncoding(String locale)
154103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
154203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_localeEncodingMap == null)
154303928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
154403928aee4356845252ac6b662d5c72c29903813eJake Slack        String encoding = _localeEncodingMap.get(locale);
154503928aee4356845252ac6b662d5c72c29903813eJake Slack        return encoding;
154603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
154703928aee4356845252ac6b662d5c72c29903813eJake Slack
154803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
154903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
155003928aee4356845252ac6b662d5c72c29903813eJake Slack     * Get the character encoding for a locale. The full locale name is first looked up in the map of encodings. If no encoding is found, then the locale
155103928aee4356845252ac6b662d5c72c29903813eJake Slack     * language is looked up.
155203928aee4356845252ac6b662d5c72c29903813eJake Slack     *
155303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param locale
155403928aee4356845252ac6b662d5c72c29903813eJake Slack     *            a <code>Locale</code> value
155503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return a <code>String</code> representing the character encoding for the locale or null if none found.
155603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
155703928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getLocaleEncoding(Locale locale)
155803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
155903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_localeEncodingMap == null)
156003928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
156103928aee4356845252ac6b662d5c72c29903813eJake Slack        String encoding = _localeEncodingMap.get(locale.toString());
156203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (encoding == null)
156303928aee4356845252ac6b662d5c72c29903813eJake Slack            encoding = _localeEncodingMap.get(locale.getLanguage());
156403928aee4356845252ac6b662d5c72c29903813eJake Slack        return encoding;
156503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
156603928aee4356845252ac6b662d5c72c29903813eJake Slack
156703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
156803928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
156903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
157003928aee4356845252ac6b662d5c72c29903813eJake Slack    public Resource getResource(String path) throws MalformedURLException
157103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
157203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (path == null || !path.startsWith(URIUtil.SLASH))
157303928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new MalformedURLException(path);
157403928aee4356845252ac6b662d5c72c29903813eJake Slack
157503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_baseResource == null)
157603928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
157703928aee4356845252ac6b662d5c72c29903813eJake Slack
157803928aee4356845252ac6b662d5c72c29903813eJake Slack        try
157903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
158003928aee4356845252ac6b662d5c72c29903813eJake Slack            path = URIUtil.canonicalPath(path);
158103928aee4356845252ac6b662d5c72c29903813eJake Slack            Resource resource = _baseResource.addPath(path);
158203928aee4356845252ac6b662d5c72c29903813eJake Slack
158303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (checkAlias(path,resource))
158403928aee4356845252ac6b662d5c72c29903813eJake Slack                return resource;
158503928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
158603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
158703928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (Exception e)
158803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
158903928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.ignore(e);
159003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
159103928aee4356845252ac6b662d5c72c29903813eJake Slack
159203928aee4356845252ac6b662d5c72c29903813eJake Slack        return null;
159303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
159403928aee4356845252ac6b662d5c72c29903813eJake Slack
159503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
159603928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean checkAlias(String path, Resource resource)
159703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
159803928aee4356845252ac6b662d5c72c29903813eJake Slack        // Is the resource aliased?
159903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!_aliasesAllowed && resource.getAlias() != null)
160003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
160103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (LOG.isDebugEnabled())
160203928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.debug("Aliased resource: " + resource + "~=" + resource.getAlias());
160303928aee4356845252ac6b662d5c72c29903813eJake Slack
160403928aee4356845252ac6b662d5c72c29903813eJake Slack            // alias checks
160503928aee4356845252ac6b662d5c72c29903813eJake Slack            for (Iterator<AliasCheck> i=_aliasChecks.iterator();i.hasNext();)
160603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
160703928aee4356845252ac6b662d5c72c29903813eJake Slack                AliasCheck check = i.next();
160803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (check.check(path,resource))
160903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
161003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (LOG.isDebugEnabled())
161103928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.debug("Aliased resource: " + resource + " approved by " + check);
161203928aee4356845252ac6b662d5c72c29903813eJake Slack                    return true;
161303928aee4356845252ac6b662d5c72c29903813eJake Slack                }
161403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
161503928aee4356845252ac6b662d5c72c29903813eJake Slack            return false;
161603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
161703928aee4356845252ac6b662d5c72c29903813eJake Slack        return true;
161803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
161903928aee4356845252ac6b662d5c72c29903813eJake Slack
162003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
162103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
162203928aee4356845252ac6b662d5c72c29903813eJake Slack     * Convert URL to Resource wrapper for {@link Resource#newResource(URL)} enables extensions to provide alternate resource implementations.
162303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
162403928aee4356845252ac6b662d5c72c29903813eJake Slack    public Resource newResource(URL url) throws IOException
162503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
162603928aee4356845252ac6b662d5c72c29903813eJake Slack        return Resource.newResource(url);
162703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
162803928aee4356845252ac6b662d5c72c29903813eJake Slack
162903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
163003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
163103928aee4356845252ac6b662d5c72c29903813eJake Slack     * Convert a URL or path to a Resource. The default implementation is a wrapper for {@link Resource#newResource(String)}.
163203928aee4356845252ac6b662d5c72c29903813eJake Slack     *
163303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param urlOrPath
163403928aee4356845252ac6b662d5c72c29903813eJake Slack     *            The URL or path to convert
163503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return The Resource for the URL/path
163603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @throws IOException
163703928aee4356845252ac6b662d5c72c29903813eJake Slack     *             The Resource could not be created.
163803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
163903928aee4356845252ac6b662d5c72c29903813eJake Slack    public Resource newResource(String urlOrPath) throws IOException
164003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
164103928aee4356845252ac6b662d5c72c29903813eJake Slack        return Resource.newResource(urlOrPath);
164203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
164303928aee4356845252ac6b662d5c72c29903813eJake Slack
164403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
164503928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
164603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
164703928aee4356845252ac6b662d5c72c29903813eJake Slack    public Set<String> getResourcePaths(String path)
164803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
164903928aee4356845252ac6b662d5c72c29903813eJake Slack        try
165003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
165103928aee4356845252ac6b662d5c72c29903813eJake Slack            path = URIUtil.canonicalPath(path);
165203928aee4356845252ac6b662d5c72c29903813eJake Slack            Resource resource = getResource(path);
165303928aee4356845252ac6b662d5c72c29903813eJake Slack
165403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (resource != null && resource.exists())
165503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
165603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!path.endsWith(URIUtil.SLASH))
165703928aee4356845252ac6b662d5c72c29903813eJake Slack                    path = path + URIUtil.SLASH;
165803928aee4356845252ac6b662d5c72c29903813eJake Slack
165903928aee4356845252ac6b662d5c72c29903813eJake Slack                String[] l = resource.list();
166003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (l != null)
166103928aee4356845252ac6b662d5c72c29903813eJake Slack                {
166203928aee4356845252ac6b662d5c72c29903813eJake Slack                    HashSet<String> set = new HashSet<String>();
166303928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int i = 0; i < l.length; i++)
166403928aee4356845252ac6b662d5c72c29903813eJake Slack                        set.add(path + l[i]);
166503928aee4356845252ac6b662d5c72c29903813eJake Slack                    return set;
166603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
166703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
166803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
166903928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (Exception e)
167003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
167103928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.ignore(e);
167203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
167303928aee4356845252ac6b662d5c72c29903813eJake Slack        return Collections.emptySet();
167403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
167503928aee4356845252ac6b662d5c72c29903813eJake Slack
167603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
167703928aee4356845252ac6b662d5c72c29903813eJake Slack    private String normalizeHostname(String host)
167803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
167903928aee4356845252ac6b662d5c72c29903813eJake Slack        if (host == null)
168003928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
168103928aee4356845252ac6b662d5c72c29903813eJake Slack
168203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (host.endsWith("."))
168303928aee4356845252ac6b662d5c72c29903813eJake Slack            return host.substring(0,host.length() - 1);
168403928aee4356845252ac6b662d5c72c29903813eJake Slack
168503928aee4356845252ac6b662d5c72c29903813eJake Slack        return host;
168603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
168703928aee4356845252ac6b662d5c72c29903813eJake Slack
168803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
168903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
169003928aee4356845252ac6b662d5c72c29903813eJake Slack     * Add an AliasCheck instance to possibly permit aliased resources
169103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param check The alias checker
169203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
169303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void addAliasCheck(AliasCheck check)
169403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
169503928aee4356845252ac6b662d5c72c29903813eJake Slack        _aliasChecks.add(check);
169603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
169703928aee4356845252ac6b662d5c72c29903813eJake Slack
169803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
169903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
170003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Mutable list of Alias checks
170103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
170203928aee4356845252ac6b662d5c72c29903813eJake Slack    public List<AliasCheck> getAliasChecks()
170303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
170403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _aliasChecks;
170503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
170603928aee4356845252ac6b662d5c72c29903813eJake Slack
170703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
170803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
170903928aee4356845252ac6b662d5c72c29903813eJake Slack     * Context.
171003928aee4356845252ac6b662d5c72c29903813eJake Slack     * <p>
171103928aee4356845252ac6b662d5c72c29903813eJake Slack     * A partial implementation of {@link javax.servlet.ServletContext}. A complete implementation is provided by the derived {@link ContextHandler}.
171203928aee4356845252ac6b662d5c72c29903813eJake Slack     * </p>
171303928aee4356845252ac6b662d5c72c29903813eJake Slack     *
171403928aee4356845252ac6b662d5c72c29903813eJake Slack     *
171503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
171603928aee4356845252ac6b662d5c72c29903813eJake Slack    public class Context implements ServletContext
171703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
171803928aee4356845252ac6b662d5c72c29903813eJake Slack        protected int _majorVersion = 3;
171903928aee4356845252ac6b662d5c72c29903813eJake Slack        protected int _minorVersion = 0;
172003928aee4356845252ac6b662d5c72c29903813eJake Slack        protected boolean _enabled = true; //whether or not the dynamic API is enabled for callers
172103928aee4356845252ac6b662d5c72c29903813eJake Slack
172203928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
172303928aee4356845252ac6b662d5c72c29903813eJake Slack        protected Context()
172403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
172503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
172603928aee4356845252ac6b662d5c72c29903813eJake Slack
172703928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
172803928aee4356845252ac6b662d5c72c29903813eJake Slack        public ContextHandler getContextHandler()
172903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
173003928aee4356845252ac6b662d5c72c29903813eJake Slack            // TODO reduce visibility of this method
173103928aee4356845252ac6b662d5c72c29903813eJake Slack            return ContextHandler.this;
173203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
173303928aee4356845252ac6b662d5c72c29903813eJake Slack
173403928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
173503928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
173603928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getContext(java.lang.String)
173703928aee4356845252ac6b662d5c72c29903813eJake Slack         */
173803928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
173903928aee4356845252ac6b662d5c72c29903813eJake Slack        public ServletContext getContext(String uripath)
174003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
174103928aee4356845252ac6b662d5c72c29903813eJake Slack            List<ContextHandler> contexts = new ArrayList<ContextHandler>();
174203928aee4356845252ac6b662d5c72c29903813eJake Slack            Handler[] handlers = getServer().getChildHandlersByClass(ContextHandler.class);
174303928aee4356845252ac6b662d5c72c29903813eJake Slack            String matched_path = null;
174403928aee4356845252ac6b662d5c72c29903813eJake Slack
174503928aee4356845252ac6b662d5c72c29903813eJake Slack            for (Handler handler : handlers)
174603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
174703928aee4356845252ac6b662d5c72c29903813eJake Slack                if (handler == null)
174803928aee4356845252ac6b662d5c72c29903813eJake Slack                    continue;
174903928aee4356845252ac6b662d5c72c29903813eJake Slack                ContextHandler ch = (ContextHandler)handler;
175003928aee4356845252ac6b662d5c72c29903813eJake Slack                String context_path = ch.getContextPath();
175103928aee4356845252ac6b662d5c72c29903813eJake Slack
175203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (uripath.equals(context_path) || (uripath.startsWith(context_path) && uripath.charAt(context_path.length()) == '/')
175303928aee4356845252ac6b662d5c72c29903813eJake Slack                        || "/".equals(context_path))
175403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
175503928aee4356845252ac6b662d5c72c29903813eJake Slack                    // look first for vhost matching context only
175603928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (getVirtualHosts() != null && getVirtualHosts().length > 0)
175703928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
175803928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (ch.getVirtualHosts() != null && ch.getVirtualHosts().length > 0)
175903928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
176003928aee4356845252ac6b662d5c72c29903813eJake Slack                            for (String h1 : getVirtualHosts())
176103928aee4356845252ac6b662d5c72c29903813eJake Slack                                for (String h2 : ch.getVirtualHosts())
176203928aee4356845252ac6b662d5c72c29903813eJake Slack                                    if (h1.equals(h2))
176303928aee4356845252ac6b662d5c72c29903813eJake Slack                                    {
176403928aee4356845252ac6b662d5c72c29903813eJake Slack                                        if (matched_path == null || context_path.length() > matched_path.length())
176503928aee4356845252ac6b662d5c72c29903813eJake Slack                                        {
176603928aee4356845252ac6b662d5c72c29903813eJake Slack                                            contexts.clear();
176703928aee4356845252ac6b662d5c72c29903813eJake Slack                                            matched_path = context_path;
176803928aee4356845252ac6b662d5c72c29903813eJake Slack                                        }
176903928aee4356845252ac6b662d5c72c29903813eJake Slack
177003928aee4356845252ac6b662d5c72c29903813eJake Slack                                        if (matched_path.equals(context_path))
177103928aee4356845252ac6b662d5c72c29903813eJake Slack                                            contexts.add(ch);
177203928aee4356845252ac6b662d5c72c29903813eJake Slack                                    }
177303928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
177403928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
177503928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
177603928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
177703928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (matched_path == null || context_path.length() > matched_path.length())
177803928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
177903928aee4356845252ac6b662d5c72c29903813eJake Slack                            contexts.clear();
178003928aee4356845252ac6b662d5c72c29903813eJake Slack                            matched_path = context_path;
178103928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
178203928aee4356845252ac6b662d5c72c29903813eJake Slack
178303928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (matched_path.equals(context_path))
178403928aee4356845252ac6b662d5c72c29903813eJake Slack                            contexts.add(ch);
178503928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
178603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
178703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
178803928aee4356845252ac6b662d5c72c29903813eJake Slack
178903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (contexts.size() > 0)
179003928aee4356845252ac6b662d5c72c29903813eJake Slack                return contexts.get(0)._scontext;
179103928aee4356845252ac6b662d5c72c29903813eJake Slack
179203928aee4356845252ac6b662d5c72c29903813eJake Slack            // try again ignoring virtual hosts
179303928aee4356845252ac6b662d5c72c29903813eJake Slack            matched_path = null;
179403928aee4356845252ac6b662d5c72c29903813eJake Slack            for (Handler handler : handlers)
179503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
179603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (handler == null)
179703928aee4356845252ac6b662d5c72c29903813eJake Slack                    continue;
179803928aee4356845252ac6b662d5c72c29903813eJake Slack                ContextHandler ch = (ContextHandler)handler;
179903928aee4356845252ac6b662d5c72c29903813eJake Slack                String context_path = ch.getContextPath();
180003928aee4356845252ac6b662d5c72c29903813eJake Slack
180103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (uripath.equals(context_path) || (uripath.startsWith(context_path) && uripath.charAt(context_path.length()) == '/')
180203928aee4356845252ac6b662d5c72c29903813eJake Slack                        || "/".equals(context_path))
180303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
180403928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (matched_path == null || context_path.length() > matched_path.length())
180503928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
180603928aee4356845252ac6b662d5c72c29903813eJake Slack                        contexts.clear();
180703928aee4356845252ac6b662d5c72c29903813eJake Slack                        matched_path = context_path;
180803928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
180903928aee4356845252ac6b662d5c72c29903813eJake Slack
181003928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (matched_path.equals(context_path))
181103928aee4356845252ac6b662d5c72c29903813eJake Slack                        contexts.add(ch);
181203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
181303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
181403928aee4356845252ac6b662d5c72c29903813eJake Slack
181503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (contexts.size() > 0)
181603928aee4356845252ac6b662d5c72c29903813eJake Slack                return contexts.get(0)._scontext;
181703928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
181803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
181903928aee4356845252ac6b662d5c72c29903813eJake Slack
182003928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
182103928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
182203928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getMajorVersion()
182303928aee4356845252ac6b662d5c72c29903813eJake Slack         */
182403928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
182503928aee4356845252ac6b662d5c72c29903813eJake Slack        public int getMajorVersion()
182603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
182703928aee4356845252ac6b662d5c72c29903813eJake Slack            return 3;
182803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
182903928aee4356845252ac6b662d5c72c29903813eJake Slack
183003928aee4356845252ac6b662d5c72c29903813eJake Slack
183103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
183203928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
183303928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getMimeType(java.lang.String)
183403928aee4356845252ac6b662d5c72c29903813eJake Slack         */
183503928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
183603928aee4356845252ac6b662d5c72c29903813eJake Slack        public String getMimeType(String file)
183703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
183803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_mimeTypes == null)
183903928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
184003928aee4356845252ac6b662d5c72c29903813eJake Slack            Buffer mime = _mimeTypes.getMimeByExtension(file);
184103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (mime != null)
184203928aee4356845252ac6b662d5c72c29903813eJake Slack                return mime.toString();
184303928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
184403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
184503928aee4356845252ac6b662d5c72c29903813eJake Slack
184603928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
184703928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
184803928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getMinorVersion()
184903928aee4356845252ac6b662d5c72c29903813eJake Slack         */
185003928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
185103928aee4356845252ac6b662d5c72c29903813eJake Slack        public int getMinorVersion()
185203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
185303928aee4356845252ac6b662d5c72c29903813eJake Slack            return 0;
185403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
185503928aee4356845252ac6b662d5c72c29903813eJake Slack
185603928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
185703928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
185803928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String)
185903928aee4356845252ac6b662d5c72c29903813eJake Slack         */
186003928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
186103928aee4356845252ac6b662d5c72c29903813eJake Slack        public RequestDispatcher getNamedDispatcher(String name)
186203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
186303928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
186403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
186503928aee4356845252ac6b662d5c72c29903813eJake Slack
186603928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
186703928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
186803928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getRequestDispatcher(java.lang.String)
186903928aee4356845252ac6b662d5c72c29903813eJake Slack         */
187003928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
187103928aee4356845252ac6b662d5c72c29903813eJake Slack        public RequestDispatcher getRequestDispatcher(String uriInContext)
187203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
187303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (uriInContext == null)
187403928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
187503928aee4356845252ac6b662d5c72c29903813eJake Slack
187603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!uriInContext.startsWith("/"))
187703928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
187803928aee4356845252ac6b662d5c72c29903813eJake Slack
187903928aee4356845252ac6b662d5c72c29903813eJake Slack            try
188003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
188103928aee4356845252ac6b662d5c72c29903813eJake Slack                String query = null;
188203928aee4356845252ac6b662d5c72c29903813eJake Slack                int q = 0;
188303928aee4356845252ac6b662d5c72c29903813eJake Slack                if ((q = uriInContext.indexOf('?')) > 0)
188403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
188503928aee4356845252ac6b662d5c72c29903813eJake Slack                    query = uriInContext.substring(q + 1);
188603928aee4356845252ac6b662d5c72c29903813eJake Slack                    uriInContext = uriInContext.substring(0,q);
188703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
188803928aee4356845252ac6b662d5c72c29903813eJake Slack
188903928aee4356845252ac6b662d5c72c29903813eJake Slack                String pathInContext = URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
189003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (pathInContext!=null)
189103928aee4356845252ac6b662d5c72c29903813eJake Slack                {
189203928aee4356845252ac6b662d5c72c29903813eJake Slack                    String uri = URIUtil.addPaths(getContextPath(),uriInContext);
189303928aee4356845252ac6b662d5c72c29903813eJake Slack                    ContextHandler context = ContextHandler.this;
189403928aee4356845252ac6b662d5c72c29903813eJake Slack                    return new Dispatcher(context,uri,pathInContext,query);
189503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
189603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
189703928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (Exception e)
189803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
189903928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
190003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
190103928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
190203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
190303928aee4356845252ac6b662d5c72c29903813eJake Slack
190403928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
190503928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
190603928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getRealPath(java.lang.String)
190703928aee4356845252ac6b662d5c72c29903813eJake Slack         */
190803928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
190903928aee4356845252ac6b662d5c72c29903813eJake Slack        public String getRealPath(String path)
191003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
191103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (path == null)
191203928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
191303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (path.length() == 0)
191403928aee4356845252ac6b662d5c72c29903813eJake Slack                path = URIUtil.SLASH;
191503928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (path.charAt(0) != '/')
191603928aee4356845252ac6b662d5c72c29903813eJake Slack                path = URIUtil.SLASH + path;
191703928aee4356845252ac6b662d5c72c29903813eJake Slack
191803928aee4356845252ac6b662d5c72c29903813eJake Slack            try
191903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
192003928aee4356845252ac6b662d5c72c29903813eJake Slack                Resource resource = ContextHandler.this.getResource(path);
192103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (resource != null)
192203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
192303928aee4356845252ac6b662d5c72c29903813eJake Slack                    File file = resource.getFile();
192403928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (file != null)
192503928aee4356845252ac6b662d5c72c29903813eJake Slack                        return file.getCanonicalPath();
192603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
192703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
192803928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (Exception e)
192903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
193003928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
193103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
193203928aee4356845252ac6b662d5c72c29903813eJake Slack
193303928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
193403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
193503928aee4356845252ac6b662d5c72c29903813eJake Slack
193603928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
193703928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
193803928aee4356845252ac6b662d5c72c29903813eJake Slack        public URL getResource(String path) throws MalformedURLException
193903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
194003928aee4356845252ac6b662d5c72c29903813eJake Slack            Resource resource = ContextHandler.this.getResource(path);
194103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (resource != null && resource.exists())
194203928aee4356845252ac6b662d5c72c29903813eJake Slack                return resource.getURL();
194303928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
194403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
194503928aee4356845252ac6b662d5c72c29903813eJake Slack
194603928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
194703928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
194803928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getResourceAsStream(java.lang.String)
194903928aee4356845252ac6b662d5c72c29903813eJake Slack         */
195003928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
195103928aee4356845252ac6b662d5c72c29903813eJake Slack        public InputStream getResourceAsStream(String path)
195203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
195303928aee4356845252ac6b662d5c72c29903813eJake Slack            try
195403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
195503928aee4356845252ac6b662d5c72c29903813eJake Slack                URL url = getResource(path);
195603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (url == null)
195703928aee4356845252ac6b662d5c72c29903813eJake Slack                    return null;
195803928aee4356845252ac6b662d5c72c29903813eJake Slack                Resource r = Resource.newResource(url);
195903928aee4356845252ac6b662d5c72c29903813eJake Slack                return r.getInputStream();
196003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
196103928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (Exception e)
196203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
196303928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
196403928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
196503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
196603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
196703928aee4356845252ac6b662d5c72c29903813eJake Slack
196803928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
196903928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
197003928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getResourcePaths(java.lang.String)
197103928aee4356845252ac6b662d5c72c29903813eJake Slack         */
197203928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
197303928aee4356845252ac6b662d5c72c29903813eJake Slack        public Set getResourcePaths(String path)
197403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
197503928aee4356845252ac6b662d5c72c29903813eJake Slack            return ContextHandler.this.getResourcePaths(path);
197603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
197703928aee4356845252ac6b662d5c72c29903813eJake Slack
197803928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
197903928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
198003928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getServerInfo()
198103928aee4356845252ac6b662d5c72c29903813eJake Slack         */
198203928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
198303928aee4356845252ac6b662d5c72c29903813eJake Slack        public String getServerInfo()
198403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
198503928aee4356845252ac6b662d5c72c29903813eJake Slack            return "jetty/" + Server.getVersion();
198603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
198703928aee4356845252ac6b662d5c72c29903813eJake Slack
198803928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
198903928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
199003928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getServlet(java.lang.String)
199103928aee4356845252ac6b662d5c72c29903813eJake Slack         */
199203928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
199303928aee4356845252ac6b662d5c72c29903813eJake Slack        @Deprecated
199403928aee4356845252ac6b662d5c72c29903813eJake Slack        public Servlet getServlet(String name) throws ServletException
199503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
199603928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
199703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
199803928aee4356845252ac6b662d5c72c29903813eJake Slack
199903928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
200003928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
200103928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getServletNames()
200203928aee4356845252ac6b662d5c72c29903813eJake Slack         */
200303928aee4356845252ac6b662d5c72c29903813eJake Slack        @SuppressWarnings("unchecked")
200403928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
200503928aee4356845252ac6b662d5c72c29903813eJake Slack        @Deprecated
200603928aee4356845252ac6b662d5c72c29903813eJake Slack        public Enumeration getServletNames()
200703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
200803928aee4356845252ac6b662d5c72c29903813eJake Slack            return Collections.enumeration(Collections.EMPTY_LIST);
200903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
201003928aee4356845252ac6b662d5c72c29903813eJake Slack
201103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
201203928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
201303928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getServlets()
201403928aee4356845252ac6b662d5c72c29903813eJake Slack         */
201503928aee4356845252ac6b662d5c72c29903813eJake Slack        @SuppressWarnings("unchecked")
201603928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
201703928aee4356845252ac6b662d5c72c29903813eJake Slack        @Deprecated
201803928aee4356845252ac6b662d5c72c29903813eJake Slack        public Enumeration getServlets()
201903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
202003928aee4356845252ac6b662d5c72c29903813eJake Slack            return Collections.enumeration(Collections.EMPTY_LIST);
202103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
202203928aee4356845252ac6b662d5c72c29903813eJake Slack
202303928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
202403928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
202503928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#log(java.lang.Exception, java.lang.String)
202603928aee4356845252ac6b662d5c72c29903813eJake Slack         */
202703928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
202803928aee4356845252ac6b662d5c72c29903813eJake Slack        public void log(Exception exception, String msg)
202903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
203003928aee4356845252ac6b662d5c72c29903813eJake Slack            _logger.warn(msg,exception);
203103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
203203928aee4356845252ac6b662d5c72c29903813eJake Slack
203303928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
203403928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
203503928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#log(java.lang.String)
203603928aee4356845252ac6b662d5c72c29903813eJake Slack         */
203703928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
203803928aee4356845252ac6b662d5c72c29903813eJake Slack        public void log(String msg)
203903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
204003928aee4356845252ac6b662d5c72c29903813eJake Slack            _logger.info(msg);
204103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
204203928aee4356845252ac6b662d5c72c29903813eJake Slack
204303928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
204403928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
204503928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#log(java.lang.String, java.lang.Throwable)
204603928aee4356845252ac6b662d5c72c29903813eJake Slack         */
204703928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
204803928aee4356845252ac6b662d5c72c29903813eJake Slack        public void log(String message, Throwable throwable)
204903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
205003928aee4356845252ac6b662d5c72c29903813eJake Slack            _logger.warn(message,throwable);
205103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
205203928aee4356845252ac6b662d5c72c29903813eJake Slack
205303928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
205403928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
205503928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getInitParameter(java.lang.String)
205603928aee4356845252ac6b662d5c72c29903813eJake Slack         */
205703928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
205803928aee4356845252ac6b662d5c72c29903813eJake Slack        public String getInitParameter(String name)
205903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
206003928aee4356845252ac6b662d5c72c29903813eJake Slack            return ContextHandler.this.getInitParameter(name);
206103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
206203928aee4356845252ac6b662d5c72c29903813eJake Slack
206303928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
206403928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
206503928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getInitParameterNames()
206603928aee4356845252ac6b662d5c72c29903813eJake Slack         */
206703928aee4356845252ac6b662d5c72c29903813eJake Slack        @SuppressWarnings("unchecked")
206803928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
206903928aee4356845252ac6b662d5c72c29903813eJake Slack        public Enumeration getInitParameterNames()
207003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
207103928aee4356845252ac6b662d5c72c29903813eJake Slack            return ContextHandler.this.getInitParameterNames();
207203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
207303928aee4356845252ac6b662d5c72c29903813eJake Slack
207403928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
207503928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
207603928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getAttribute(java.lang.String)
207703928aee4356845252ac6b662d5c72c29903813eJake Slack         */
207803928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
207903928aee4356845252ac6b662d5c72c29903813eJake Slack        public synchronized Object getAttribute(String name)
208003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
208103928aee4356845252ac6b662d5c72c29903813eJake Slack            Object o = ContextHandler.this.getAttribute(name);
208203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (o == null && _contextAttributes != null)
208303928aee4356845252ac6b662d5c72c29903813eJake Slack                o = _contextAttributes.getAttribute(name);
208403928aee4356845252ac6b662d5c72c29903813eJake Slack            return o;
208503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
208603928aee4356845252ac6b662d5c72c29903813eJake Slack
208703928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
208803928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
208903928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getAttributeNames()
209003928aee4356845252ac6b662d5c72c29903813eJake Slack         */
209103928aee4356845252ac6b662d5c72c29903813eJake Slack        @SuppressWarnings("unchecked")
209203928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
209303928aee4356845252ac6b662d5c72c29903813eJake Slack        public synchronized Enumeration getAttributeNames()
209403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
209503928aee4356845252ac6b662d5c72c29903813eJake Slack            HashSet<String> set = new HashSet<String>();
209603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_contextAttributes != null)
209703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
209803928aee4356845252ac6b662d5c72c29903813eJake Slack                Enumeration<String> e = _contextAttributes.getAttributeNames();
209903928aee4356845252ac6b662d5c72c29903813eJake Slack                while (e.hasMoreElements())
210003928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.add(e.nextElement());
210103928aee4356845252ac6b662d5c72c29903813eJake Slack            }
210203928aee4356845252ac6b662d5c72c29903813eJake Slack            Enumeration<String> e = _attributes.getAttributeNames();
210303928aee4356845252ac6b662d5c72c29903813eJake Slack            while (e.hasMoreElements())
210403928aee4356845252ac6b662d5c72c29903813eJake Slack                set.add(e.nextElement());
210503928aee4356845252ac6b662d5c72c29903813eJake Slack
210603928aee4356845252ac6b662d5c72c29903813eJake Slack            return Collections.enumeration(set);
210703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
210803928aee4356845252ac6b662d5c72c29903813eJake Slack
210903928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
211003928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
211103928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object)
211203928aee4356845252ac6b662d5c72c29903813eJake Slack         */
211303928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
211403928aee4356845252ac6b662d5c72c29903813eJake Slack        public synchronized void setAttribute(String name, Object value)
211503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
211603928aee4356845252ac6b662d5c72c29903813eJake Slack            checkManagedAttribute(name,value);
211703928aee4356845252ac6b662d5c72c29903813eJake Slack            Object old_value = _contextAttributes.getAttribute(name);
211803928aee4356845252ac6b662d5c72c29903813eJake Slack
211903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (value == null)
212003928aee4356845252ac6b662d5c72c29903813eJake Slack                _contextAttributes.removeAttribute(name);
212103928aee4356845252ac6b662d5c72c29903813eJake Slack            else
212203928aee4356845252ac6b662d5c72c29903813eJake Slack                _contextAttributes.setAttribute(name,value);
212303928aee4356845252ac6b662d5c72c29903813eJake Slack
212403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_contextAttributeListeners != null)
212503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
212603928aee4356845252ac6b662d5c72c29903813eJake Slack                ServletContextAttributeEvent event = new ServletContextAttributeEvent(_scontext,name,old_value == null?value:old_value);
212703928aee4356845252ac6b662d5c72c29903813eJake Slack
212803928aee4356845252ac6b662d5c72c29903813eJake Slack                for (int i = 0; i < LazyList.size(_contextAttributeListeners); i++)
212903928aee4356845252ac6b662d5c72c29903813eJake Slack                {
213003928aee4356845252ac6b662d5c72c29903813eJake Slack                    ServletContextAttributeListener l = (ServletContextAttributeListener)LazyList.get(_contextAttributeListeners,i);
213103928aee4356845252ac6b662d5c72c29903813eJake Slack
213203928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (old_value == null)
213303928aee4356845252ac6b662d5c72c29903813eJake Slack                        l.attributeAdded(event);
213403928aee4356845252ac6b662d5c72c29903813eJake Slack                    else if (value == null)
213503928aee4356845252ac6b662d5c72c29903813eJake Slack                        l.attributeRemoved(event);
213603928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
213703928aee4356845252ac6b662d5c72c29903813eJake Slack                        l.attributeReplaced(event);
213803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
213903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
214003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
214103928aee4356845252ac6b662d5c72c29903813eJake Slack
214203928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
214303928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
214403928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
214503928aee4356845252ac6b662d5c72c29903813eJake Slack         */
214603928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
214703928aee4356845252ac6b662d5c72c29903813eJake Slack        public synchronized void removeAttribute(String name)
214803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
214903928aee4356845252ac6b662d5c72c29903813eJake Slack            checkManagedAttribute(name,null);
215003928aee4356845252ac6b662d5c72c29903813eJake Slack
215103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_contextAttributes == null)
215203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
215303928aee4356845252ac6b662d5c72c29903813eJake Slack                // Set it on the handler
215403928aee4356845252ac6b662d5c72c29903813eJake Slack                _attributes.removeAttribute(name);
215503928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
215603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
215703928aee4356845252ac6b662d5c72c29903813eJake Slack
215803928aee4356845252ac6b662d5c72c29903813eJake Slack            Object old_value = _contextAttributes.getAttribute(name);
215903928aee4356845252ac6b662d5c72c29903813eJake Slack            _contextAttributes.removeAttribute(name);
216003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (old_value != null)
216103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
216203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_contextAttributeListeners != null)
216303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
216403928aee4356845252ac6b662d5c72c29903813eJake Slack                    ServletContextAttributeEvent event = new ServletContextAttributeEvent(_scontext,name,old_value);
216503928aee4356845252ac6b662d5c72c29903813eJake Slack
216603928aee4356845252ac6b662d5c72c29903813eJake Slack                    for (int i = 0; i < LazyList.size(_contextAttributeListeners); i++)
216703928aee4356845252ac6b662d5c72c29903813eJake Slack                        ((ServletContextAttributeListener)LazyList.get(_contextAttributeListeners,i)).attributeRemoved(event);
216803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
216903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
217003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
217103928aee4356845252ac6b662d5c72c29903813eJake Slack
217203928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
217303928aee4356845252ac6b662d5c72c29903813eJake Slack        /*
217403928aee4356845252ac6b662d5c72c29903813eJake Slack         * @see javax.servlet.ServletContext#getServletContextName()
217503928aee4356845252ac6b662d5c72c29903813eJake Slack         */
217603928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
217703928aee4356845252ac6b662d5c72c29903813eJake Slack        public String getServletContextName()
217803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
217903928aee4356845252ac6b662d5c72c29903813eJake Slack            String name = ContextHandler.this.getDisplayName();
218003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (name == null)
218103928aee4356845252ac6b662d5c72c29903813eJake Slack                name = ContextHandler.this.getContextPath();
218203928aee4356845252ac6b662d5c72c29903813eJake Slack            return name;
218303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
218403928aee4356845252ac6b662d5c72c29903813eJake Slack
218503928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
218603928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
218703928aee4356845252ac6b662d5c72c29903813eJake Slack        public String getContextPath()
218803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
218903928aee4356845252ac6b662d5c72c29903813eJake Slack            if ((_contextPath != null) && _contextPath.equals(URIUtil.SLASH))
219003928aee4356845252ac6b662d5c72c29903813eJake Slack                return "";
219103928aee4356845252ac6b662d5c72c29903813eJake Slack
219203928aee4356845252ac6b662d5c72c29903813eJake Slack            return _contextPath;
219303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
219403928aee4356845252ac6b662d5c72c29903813eJake Slack
219503928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
219603928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
219703928aee4356845252ac6b662d5c72c29903813eJake Slack        public String toString()
219803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
219903928aee4356845252ac6b662d5c72c29903813eJake Slack            return "ServletContext@" + ContextHandler.this.toString();
220003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
220103928aee4356845252ac6b662d5c72c29903813eJake Slack
220203928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
220303928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
220403928aee4356845252ac6b662d5c72c29903813eJake Slack        public boolean setInitParameter(String name, String value)
220503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
220603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (ContextHandler.this.getInitParameter(name) != null)
220703928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
220803928aee4356845252ac6b662d5c72c29903813eJake Slack            ContextHandler.this.getInitParams().put(name,value);
220903928aee4356845252ac6b662d5c72c29903813eJake Slack            return true;
221003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
221103928aee4356845252ac6b662d5c72c29903813eJake Slack
221203928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
221303928aee4356845252ac6b662d5c72c29903813eJake Slack        final private static String __unimplmented="Unimplemented - use org.eclipse.jetty.servlet.ServletContextHandler";
221403928aee4356845252ac6b662d5c72c29903813eJake Slack
221503928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
221603928aee4356845252ac6b662d5c72c29903813eJake Slack        public Dynamic addFilter(String filterName, Class<? extends Filter> filterClass)
221703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
221803928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
221903928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
222003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
222103928aee4356845252ac6b662d5c72c29903813eJake Slack
222203928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
222303928aee4356845252ac6b662d5c72c29903813eJake Slack        public Dynamic addFilter(String filterName, Filter filter)
222403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
222503928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
222603928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
222703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
222803928aee4356845252ac6b662d5c72c29903813eJake Slack
222903928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
223003928aee4356845252ac6b662d5c72c29903813eJake Slack        public Dynamic addFilter(String filterName, String className)
223103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
223203928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
223303928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
223403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
223503928aee4356845252ac6b662d5c72c29903813eJake Slack
223603928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
223703928aee4356845252ac6b662d5c72c29903813eJake Slack        public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass)
223803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
223903928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
224003928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
224103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
224203928aee4356845252ac6b662d5c72c29903813eJake Slack
224303928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
224403928aee4356845252ac6b662d5c72c29903813eJake Slack        public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
224503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
224603928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
224703928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
224803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
224903928aee4356845252ac6b662d5c72c29903813eJake Slack
225003928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
225103928aee4356845252ac6b662d5c72c29903813eJake Slack        public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, String className)
225203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
225303928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
225403928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
225503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
225603928aee4356845252ac6b662d5c72c29903813eJake Slack
225703928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
225803928aee4356845252ac6b662d5c72c29903813eJake Slack        public <T extends Filter> T createFilter(Class<T> c) throws ServletException
225903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
226003928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
226103928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
226203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
226303928aee4356845252ac6b662d5c72c29903813eJake Slack
226403928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
226503928aee4356845252ac6b662d5c72c29903813eJake Slack        public <T extends Servlet> T createServlet(Class<T> c) throws ServletException
226603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
226703928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
226803928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
226903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
227003928aee4356845252ac6b662d5c72c29903813eJake Slack
227103928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
227203928aee4356845252ac6b662d5c72c29903813eJake Slack        public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
227303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
227403928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
227503928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
227603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
227703928aee4356845252ac6b662d5c72c29903813eJake Slack
227803928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
227903928aee4356845252ac6b662d5c72c29903813eJake Slack        public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
228003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
228103928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
228203928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
228303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
228403928aee4356845252ac6b662d5c72c29903813eJake Slack
228503928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
228603928aee4356845252ac6b662d5c72c29903813eJake Slack        public FilterRegistration getFilterRegistration(String filterName)
228703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
228803928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
228903928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
229003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
229103928aee4356845252ac6b662d5c72c29903813eJake Slack
229203928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
229303928aee4356845252ac6b662d5c72c29903813eJake Slack        public Map<String, ? extends FilterRegistration> getFilterRegistrations()
229403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
229503928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
229603928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
229703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
229803928aee4356845252ac6b662d5c72c29903813eJake Slack
229903928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
230003928aee4356845252ac6b662d5c72c29903813eJake Slack        public ServletRegistration getServletRegistration(String servletName)
230103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
230203928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
230303928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
230403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
230503928aee4356845252ac6b662d5c72c29903813eJake Slack
230603928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
230703928aee4356845252ac6b662d5c72c29903813eJake Slack        public Map<String, ? extends ServletRegistration> getServletRegistrations()
230803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
230903928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
231003928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
231103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
231203928aee4356845252ac6b662d5c72c29903813eJake Slack
231303928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
231403928aee4356845252ac6b662d5c72c29903813eJake Slack        public SessionCookieConfig getSessionCookieConfig()
231503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
231603928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
231703928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
231803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
231903928aee4356845252ac6b662d5c72c29903813eJake Slack
232003928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
232103928aee4356845252ac6b662d5c72c29903813eJake Slack        public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
232203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
232303928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
232403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
232503928aee4356845252ac6b662d5c72c29903813eJake Slack
232603928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
232703928aee4356845252ac6b662d5c72c29903813eJake Slack        public void addListener(String className)
232803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
232903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!_enabled)
233003928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new UnsupportedOperationException();
233103928aee4356845252ac6b662d5c72c29903813eJake Slack
233203928aee4356845252ac6b662d5c72c29903813eJake Slack            try
233303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
233403928aee4356845252ac6b662d5c72c29903813eJake Slack                Class<? extends EventListener> clazz = _classLoader==null?Loader.loadClass(ContextHandler.class,className):_classLoader.loadClass(className);
233503928aee4356845252ac6b662d5c72c29903813eJake Slack                addListener(clazz);
233603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
233703928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (ClassNotFoundException e)
233803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
233903928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalArgumentException(e);
234003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
234103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
234203928aee4356845252ac6b662d5c72c29903813eJake Slack
234303928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
234403928aee4356845252ac6b662d5c72c29903813eJake Slack        public <T extends EventListener> void addListener(T t)
234503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
234603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!_enabled)
234703928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new UnsupportedOperationException();
234803928aee4356845252ac6b662d5c72c29903813eJake Slack            ContextHandler.this.addEventListener(t);
234903928aee4356845252ac6b662d5c72c29903813eJake Slack            ContextHandler.this.restrictEventListener(t);
235003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
235103928aee4356845252ac6b662d5c72c29903813eJake Slack
235203928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
235303928aee4356845252ac6b662d5c72c29903813eJake Slack        public void addListener(Class<? extends EventListener> listenerClass)
235403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
235503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!_enabled)
235603928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new UnsupportedOperationException();
235703928aee4356845252ac6b662d5c72c29903813eJake Slack
235803928aee4356845252ac6b662d5c72c29903813eJake Slack            try
235903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
236003928aee4356845252ac6b662d5c72c29903813eJake Slack                EventListener e = createListener(listenerClass);
236103928aee4356845252ac6b662d5c72c29903813eJake Slack                ContextHandler.this.addEventListener(e);
236203928aee4356845252ac6b662d5c72c29903813eJake Slack                ContextHandler.this.restrictEventListener(e);
236303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
236403928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (ServletException e)
236503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
236603928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalArgumentException(e);
236703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
236803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
236903928aee4356845252ac6b662d5c72c29903813eJake Slack
237003928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
237103928aee4356845252ac6b662d5c72c29903813eJake Slack        public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException
237203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
237303928aee4356845252ac6b662d5c72c29903813eJake Slack            try
237403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
237503928aee4356845252ac6b662d5c72c29903813eJake Slack                return clazz.newInstance();
237603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
237703928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (InstantiationException e)
237803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
237903928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new ServletException(e);
238003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
238103928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IllegalAccessException e)
238203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
238303928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new ServletException(e);
238403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
238503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
238603928aee4356845252ac6b662d5c72c29903813eJake Slack
238703928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
238803928aee4356845252ac6b662d5c72c29903813eJake Slack        public ClassLoader getClassLoader()
238903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
239003928aee4356845252ac6b662d5c72c29903813eJake Slack            AccessController.checkPermission(new RuntimePermission("getClassLoader"));
239103928aee4356845252ac6b662d5c72c29903813eJake Slack            return _classLoader;
239203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
239303928aee4356845252ac6b662d5c72c29903813eJake Slack
239403928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
239503928aee4356845252ac6b662d5c72c29903813eJake Slack        public int getEffectiveMajorVersion()
239603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
239703928aee4356845252ac6b662d5c72c29903813eJake Slack            return _majorVersion;
239803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
239903928aee4356845252ac6b662d5c72c29903813eJake Slack
240003928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
240103928aee4356845252ac6b662d5c72c29903813eJake Slack        public int getEffectiveMinorVersion()
240203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
240303928aee4356845252ac6b662d5c72c29903813eJake Slack            return _minorVersion;
240403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
240503928aee4356845252ac6b662d5c72c29903813eJake Slack
240603928aee4356845252ac6b662d5c72c29903813eJake Slack        public void setEffectiveMajorVersion (int v)
240703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
240803928aee4356845252ac6b662d5c72c29903813eJake Slack            _majorVersion = v;
240903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
241003928aee4356845252ac6b662d5c72c29903813eJake Slack
241103928aee4356845252ac6b662d5c72c29903813eJake Slack        public void setEffectiveMinorVersion (int v)
241203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
241303928aee4356845252ac6b662d5c72c29903813eJake Slack            _minorVersion = v;
241403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
241503928aee4356845252ac6b662d5c72c29903813eJake Slack
241603928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
241703928aee4356845252ac6b662d5c72c29903813eJake Slack        public JspConfigDescriptor getJspConfigDescriptor()
241803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
241903928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(__unimplmented);
242003928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
242103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
242203928aee4356845252ac6b662d5c72c29903813eJake Slack
242303928aee4356845252ac6b662d5c72c29903813eJake Slack        public void setJspConfigDescriptor(JspConfigDescriptor d)
242403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
242503928aee4356845252ac6b662d5c72c29903813eJake Slack
242603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
242703928aee4356845252ac6b662d5c72c29903813eJake Slack
242803928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
242903928aee4356845252ac6b662d5c72c29903813eJake Slack        public void declareRoles(String... roleNames)
243003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
243103928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!isStarting())
243203928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new IllegalStateException ();
243303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!_enabled)
243403928aee4356845252ac6b662d5c72c29903813eJake Slack                throw new UnsupportedOperationException();
243503928aee4356845252ac6b662d5c72c29903813eJake Slack
243603928aee4356845252ac6b662d5c72c29903813eJake Slack            // TODO Auto-generated method stub
243703928aee4356845252ac6b662d5c72c29903813eJake Slack
243803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
243903928aee4356845252ac6b662d5c72c29903813eJake Slack
244003928aee4356845252ac6b662d5c72c29903813eJake Slack        public void setEnabled(boolean enabled)
244103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
244203928aee4356845252ac6b662d5c72c29903813eJake Slack            _enabled = enabled;
244303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
244403928aee4356845252ac6b662d5c72c29903813eJake Slack
244503928aee4356845252ac6b662d5c72c29903813eJake Slack        public boolean isEnabled()
244603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
244703928aee4356845252ac6b662d5c72c29903813eJake Slack            return _enabled;
244803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
244903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
245003928aee4356845252ac6b662d5c72c29903813eJake Slack
245103928aee4356845252ac6b662d5c72c29903813eJake Slack    private static class CLDump implements Dumpable
245203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
245303928aee4356845252ac6b662d5c72c29903813eJake Slack        final ClassLoader _loader;
245403928aee4356845252ac6b662d5c72c29903813eJake Slack
245503928aee4356845252ac6b662d5c72c29903813eJake Slack        CLDump(ClassLoader loader)
245603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
245703928aee4356845252ac6b662d5c72c29903813eJake Slack            _loader = loader;
245803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
245903928aee4356845252ac6b662d5c72c29903813eJake Slack
246003928aee4356845252ac6b662d5c72c29903813eJake Slack        public String dump()
246103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
246203928aee4356845252ac6b662d5c72c29903813eJake Slack            return AggregateLifeCycle.dump(this);
246303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
246403928aee4356845252ac6b662d5c72c29903813eJake Slack
246503928aee4356845252ac6b662d5c72c29903813eJake Slack        public void dump(Appendable out, String indent) throws IOException
246603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
246703928aee4356845252ac6b662d5c72c29903813eJake Slack            out.append(String.valueOf(_loader)).append("\n");
246803928aee4356845252ac6b662d5c72c29903813eJake Slack
246903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_loader != null)
247003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
247103928aee4356845252ac6b662d5c72c29903813eJake Slack                Object parent = _loader.getParent();
247203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (parent != null)
247303928aee4356845252ac6b662d5c72c29903813eJake Slack                {
247403928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (!(parent instanceof Dumpable))
247503928aee4356845252ac6b662d5c72c29903813eJake Slack                        parent = new CLDump((ClassLoader)parent);
247603928aee4356845252ac6b662d5c72c29903813eJake Slack
247703928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_loader instanceof URLClassLoader)
247803928aee4356845252ac6b662d5c72c29903813eJake Slack                        AggregateLifeCycle.dump(out,indent,TypeUtil.asList(((URLClassLoader)_loader).getURLs()),Collections.singleton(parent));
247903928aee4356845252ac6b662d5c72c29903813eJake Slack                    else
248003928aee4356845252ac6b662d5c72c29903813eJake Slack                        AggregateLifeCycle.dump(out,indent,Collections.singleton(parent));
248103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
248203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
248303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
248403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
248503928aee4356845252ac6b662d5c72c29903813eJake Slack
248603928aee4356845252ac6b662d5c72c29903813eJake Slack
248703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
248803928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Interface to check aliases
248903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
249003928aee4356845252ac6b662d5c72c29903813eJake Slack    public interface AliasCheck
249103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
249203928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
249303928aee4356845252ac6b662d5c72c29903813eJake Slack        /** Check an alias
249403928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param path The path the aliased resource was created for
249503928aee4356845252ac6b662d5c72c29903813eJake Slack         * @param resource The aliased resourced
249603928aee4356845252ac6b662d5c72c29903813eJake Slack         * @return True if the resource is OK to be served.
249703928aee4356845252ac6b662d5c72c29903813eJake Slack         */
249803928aee4356845252ac6b662d5c72c29903813eJake Slack        boolean check(String path, Resource resource);
249903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
250003928aee4356845252ac6b662d5c72c29903813eJake Slack
250103928aee4356845252ac6b662d5c72c29903813eJake Slack
250203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
250303928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Approve Aliases with same suffix.
250403928aee4356845252ac6b662d5c72c29903813eJake Slack     * Eg. a symbolic link from /foobar.html to /somewhere/wibble.html would be
250503928aee4356845252ac6b662d5c72c29903813eJake Slack     * approved because both the resource and alias end with ".html".
250603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
250703928aee4356845252ac6b662d5c72c29903813eJake Slack    @Deprecated
250803928aee4356845252ac6b662d5c72c29903813eJake Slack    public static class ApproveSameSuffixAliases implements AliasCheck
250903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
251003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
251103928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn("ApproveSameSuffixAlias is not safe for production");
251203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
251303928aee4356845252ac6b662d5c72c29903813eJake Slack
251403928aee4356845252ac6b662d5c72c29903813eJake Slack        public boolean check(String path, Resource resource)
251503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
251603928aee4356845252ac6b662d5c72c29903813eJake Slack            int dot = path.lastIndexOf('.');
251703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (dot<0)
251803928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
251903928aee4356845252ac6b662d5c72c29903813eJake Slack            String suffix=path.substring(dot);
252003928aee4356845252ac6b662d5c72c29903813eJake Slack            return resource.toString().endsWith(suffix);
252103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
252203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
252303928aee4356845252ac6b662d5c72c29903813eJake Slack
252403928aee4356845252ac6b662d5c72c29903813eJake Slack
252503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
252603928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Approve Aliases with a path prefix.
252703928aee4356845252ac6b662d5c72c29903813eJake Slack     * Eg. a symbolic link from /dirA/foobar.html to /dirB/foobar.html would be
252803928aee4356845252ac6b662d5c72c29903813eJake Slack     * approved because both the resource and alias end with "/foobar.html".
252903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
253003928aee4356845252ac6b662d5c72c29903813eJake Slack    @Deprecated
253103928aee4356845252ac6b662d5c72c29903813eJake Slack    public static class ApprovePathPrefixAliases implements AliasCheck
253203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
253303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
253403928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn("ApprovePathPrefixAliases is not safe for production");
253503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
253603928aee4356845252ac6b662d5c72c29903813eJake Slack
253703928aee4356845252ac6b662d5c72c29903813eJake Slack        public boolean check(String path, Resource resource)
253803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
253903928aee4356845252ac6b662d5c72c29903813eJake Slack            int slash = path.lastIndexOf('/');
254003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (slash<0 || slash==path.length()-1)
254103928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
254203928aee4356845252ac6b662d5c72c29903813eJake Slack            String suffix=path.substring(slash);
254303928aee4356845252ac6b662d5c72c29903813eJake Slack            return resource.toString().endsWith(suffix);
254403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
254503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
254603928aee4356845252ac6b662d5c72c29903813eJake Slack
254703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
254803928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Approve Aliases of a non existent directory.
254903928aee4356845252ac6b662d5c72c29903813eJake Slack     * If a directory "/foobar/" does not exist, then the resource is
255003928aee4356845252ac6b662d5c72c29903813eJake Slack     * aliased to "/foobar".  Accept such aliases.
255103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
255203928aee4356845252ac6b662d5c72c29903813eJake Slack    public static class ApproveNonExistentDirectoryAliases implements AliasCheck
255303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
255403928aee4356845252ac6b662d5c72c29903813eJake Slack        public boolean check(String path, Resource resource)
255503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
255603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (resource.exists())
255703928aee4356845252ac6b662d5c72c29903813eJake Slack                return false;
255803928aee4356845252ac6b662d5c72c29903813eJake Slack
255903928aee4356845252ac6b662d5c72c29903813eJake Slack            String a=resource.getAlias().toString();
256003928aee4356845252ac6b662d5c72c29903813eJake Slack            String r=resource.getURL().toString();
256103928aee4356845252ac6b662d5c72c29903813eJake Slack
256203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (a.length()>r.length())
256303928aee4356845252ac6b662d5c72c29903813eJake Slack                return a.startsWith(r) && a.length()==r.length()+1 && a.endsWith("/");
256403928aee4356845252ac6b662d5c72c29903813eJake Slack            else
256503928aee4356845252ac6b662d5c72c29903813eJake Slack                return r.startsWith(a) && r.length()==a.length()+1 && r.endsWith("/");
256603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
256703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
256803928aee4356845252ac6b662d5c72c29903813eJake Slack
256903928aee4356845252ac6b662d5c72c29903813eJake Slack}
2570