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;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Collections;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Enumeration;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashSet;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Iterator;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Map;
2703928aee4356845252ac6b662d5c72c29903813eJake Slack
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.DispatcherType;
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.RequestDispatcher;
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletException;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletRequest;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletResponse;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletRequest;
3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletResponse;
3503928aee4356845252ac6b662d5c72c29903813eJake Slack
3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.handler.ContextHandler;
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.Attributes;
3803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.LazyList;
3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.MultiMap;
4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.UrlEncoded;
4103928aee4356845252ac6b662d5c72c29903813eJake Slack
4203928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
4303928aee4356845252ac6b662d5c72c29903813eJake Slack/** Servlet RequestDispatcher.
4403928aee4356845252ac6b662d5c72c29903813eJake Slack *
4503928aee4356845252ac6b662d5c72c29903813eJake Slack *
4603928aee4356845252ac6b662d5c72c29903813eJake Slack */
4703928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class Dispatcher implements RequestDispatcher
4803928aee4356845252ac6b662d5c72c29903813eJake Slack{
4903928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Dispatch include attribute names */
5003928aee4356845252ac6b662d5c72c29903813eJake Slack    public final static String __INCLUDE_PREFIX="javax.servlet.include.";
5103928aee4356845252ac6b662d5c72c29903813eJake Slack
5203928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Dispatch include attribute names */
5303928aee4356845252ac6b662d5c72c29903813eJake Slack    public final static String __FORWARD_PREFIX="javax.servlet.forward.";
5403928aee4356845252ac6b662d5c72c29903813eJake Slack
5503928aee4356845252ac6b662d5c72c29903813eJake Slack    /** JSP attributes */
5603928aee4356845252ac6b662d5c72c29903813eJake Slack    public final static String __JSP_FILE="org.apache.catalina.jsp_file";
5703928aee4356845252ac6b662d5c72c29903813eJake Slack
5803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
5903928aee4356845252ac6b662d5c72c29903813eJake Slack    private final ContextHandler _contextHandler;
6003928aee4356845252ac6b662d5c72c29903813eJake Slack    private final String _uri;
6103928aee4356845252ac6b662d5c72c29903813eJake Slack    private final String _path;
6203928aee4356845252ac6b662d5c72c29903813eJake Slack    private final String _dQuery;
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    private final String _named;
6403928aee4356845252ac6b662d5c72c29903813eJake Slack
6503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
6603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
6703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param contextHandler
6803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param uri
6903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param pathInContext
7003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param query
7103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
7203928aee4356845252ac6b662d5c72c29903813eJake Slack    public Dispatcher(ContextHandler contextHandler, String uri, String pathInContext, String query)
7303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7403928aee4356845252ac6b662d5c72c29903813eJake Slack        _contextHandler=contextHandler;
7503928aee4356845252ac6b662d5c72c29903813eJake Slack        _uri=uri;
7603928aee4356845252ac6b662d5c72c29903813eJake Slack        _path=pathInContext;
7703928aee4356845252ac6b662d5c72c29903813eJake Slack        _dQuery=query;
7803928aee4356845252ac6b662d5c72c29903813eJake Slack        _named=null;
7903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8003928aee4356845252ac6b662d5c72c29903813eJake Slack
8103928aee4356845252ac6b662d5c72c29903813eJake Slack
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Constructor.
8403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param contextHandler
8503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param name
8603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
8703928aee4356845252ac6b662d5c72c29903813eJake Slack    public Dispatcher(ContextHandler contextHandler,String name)
8803928aee4356845252ac6b662d5c72c29903813eJake Slack        throws IllegalStateException
8903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9003928aee4356845252ac6b662d5c72c29903813eJake Slack        _contextHandler=contextHandler;
9103928aee4356845252ac6b662d5c72c29903813eJake Slack        _named=name;
9203928aee4356845252ac6b662d5c72c29903813eJake Slack        _uri=null;
9303928aee4356845252ac6b662d5c72c29903813eJake Slack        _path=null;
9403928aee4356845252ac6b662d5c72c29903813eJake Slack        _dQuery=null;
9503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
9603928aee4356845252ac6b662d5c72c29903813eJake Slack
9703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9803928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
9903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
10003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
10103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException
10203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
10303928aee4356845252ac6b662d5c72c29903813eJake Slack        forward(request, response, DispatcherType.FORWARD);
10403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10503928aee4356845252ac6b662d5c72c29903813eJake Slack
10603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
10803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
10903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
11003928aee4356845252ac6b662d5c72c29903813eJake Slack    public void error(ServletRequest request, ServletResponse response) throws ServletException, IOException
11103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11203928aee4356845252ac6b662d5c72c29903813eJake Slack        forward(request, response, DispatcherType.ERROR);
11303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11403928aee4356845252ac6b662d5c72c29903813eJake Slack
11503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11603928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
11703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.RequestDispatcher#include(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
11803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
11903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
12003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12103928aee4356845252ac6b662d5c72c29903813eJake Slack        Request baseRequest=(request instanceof Request)?((Request)request):AbstractHttpConnection.getCurrentConnection().getRequest();
12203928aee4356845252ac6b662d5c72c29903813eJake Slack
12303928aee4356845252ac6b662d5c72c29903813eJake Slack
12403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!(request instanceof HttpServletRequest))
12503928aee4356845252ac6b662d5c72c29903813eJake Slack            request = new ServletRequestHttpWrapper(request);
12603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!(response instanceof HttpServletResponse))
12703928aee4356845252ac6b662d5c72c29903813eJake Slack            response = new ServletResponseHttpWrapper(response);
12803928aee4356845252ac6b662d5c72c29903813eJake Slack
12903928aee4356845252ac6b662d5c72c29903813eJake Slack
13003928aee4356845252ac6b662d5c72c29903813eJake Slack        // TODO - allow stream or writer????
13103928aee4356845252ac6b662d5c72c29903813eJake Slack
13203928aee4356845252ac6b662d5c72c29903813eJake Slack        final DispatcherType old_type = baseRequest.getDispatcherType();
13303928aee4356845252ac6b662d5c72c29903813eJake Slack        final Attributes old_attr=baseRequest.getAttributes();
13403928aee4356845252ac6b662d5c72c29903813eJake Slack        MultiMap old_params=baseRequest.getParameters();
13503928aee4356845252ac6b662d5c72c29903813eJake Slack        try
13603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
13703928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setDispatcherType(DispatcherType.INCLUDE);
13803928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.getConnection().include();
13903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_named!=null)
14003928aee4356845252ac6b662d5c72c29903813eJake Slack                _contextHandler.handle(_named,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
14103928aee4356845252ac6b662d5c72c29903813eJake Slack            else
14203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
14303928aee4356845252ac6b662d5c72c29903813eJake Slack                String query=_dQuery;
14403928aee4356845252ac6b662d5c72c29903813eJake Slack
14503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (query!=null)
14603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
14703928aee4356845252ac6b662d5c72c29903813eJake Slack                    // force parameter extraction
14803928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (old_params==null)
14903928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
15003928aee4356845252ac6b662d5c72c29903813eJake Slack                        baseRequest.extractParameters();
15103928aee4356845252ac6b662d5c72c29903813eJake Slack                        old_params=baseRequest.getParameters();
15203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
15303928aee4356845252ac6b662d5c72c29903813eJake Slack
15403928aee4356845252ac6b662d5c72c29903813eJake Slack                    MultiMap parameters=new MultiMap();
15503928aee4356845252ac6b662d5c72c29903813eJake Slack                    UrlEncoded.decodeTo(query,parameters,baseRequest.getCharacterEncoding());
15603928aee4356845252ac6b662d5c72c29903813eJake Slack
15703928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (old_params!=null && old_params.size()>0)
15803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
15903928aee4356845252ac6b662d5c72c29903813eJake Slack                        // Merge parameters.
16003928aee4356845252ac6b662d5c72c29903813eJake Slack                        Iterator iter = old_params.entrySet().iterator();
16103928aee4356845252ac6b662d5c72c29903813eJake Slack                        while (iter.hasNext())
16203928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
16303928aee4356845252ac6b662d5c72c29903813eJake Slack                            Map.Entry entry = (Map.Entry)iter.next();
16403928aee4356845252ac6b662d5c72c29903813eJake Slack                            String name=(String)entry.getKey();
16503928aee4356845252ac6b662d5c72c29903813eJake Slack                            Object values=entry.getValue();
16603928aee4356845252ac6b662d5c72c29903813eJake Slack                            for (int i=0;i<LazyList.size(values);i++)
16703928aee4356845252ac6b662d5c72c29903813eJake Slack                                parameters.add(name, LazyList.get(values, i));
16803928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
16903928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
17003928aee4356845252ac6b662d5c72c29903813eJake Slack                    baseRequest.setParameters(parameters);
17103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
17203928aee4356845252ac6b662d5c72c29903813eJake Slack
17303928aee4356845252ac6b662d5c72c29903813eJake Slack                IncludeAttributes attr = new IncludeAttributes(old_attr);
17403928aee4356845252ac6b662d5c72c29903813eJake Slack
17503928aee4356845252ac6b662d5c72c29903813eJake Slack                attr._requestURI=_uri;
17603928aee4356845252ac6b662d5c72c29903813eJake Slack                attr._contextPath=_contextHandler.getContextPath();
17703928aee4356845252ac6b662d5c72c29903813eJake Slack                attr._servletPath=null; // set by ServletHandler
17803928aee4356845252ac6b662d5c72c29903813eJake Slack                attr._pathInfo=_path;
17903928aee4356845252ac6b662d5c72c29903813eJake Slack                attr._query=query;
18003928aee4356845252ac6b662d5c72c29903813eJake Slack
18103928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setAttributes(attr);
18203928aee4356845252ac6b662d5c72c29903813eJake Slack
18303928aee4356845252ac6b662d5c72c29903813eJake Slack                _contextHandler.handle(_path,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
18403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
18503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
18603928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
18703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
18803928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setAttributes(old_attr);
18903928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.getConnection().included();
19003928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setParameters(old_params);
19103928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setDispatcherType(old_type);
19203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
19303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
19403928aee4356845252ac6b662d5c72c29903813eJake Slack
19503928aee4356845252ac6b662d5c72c29903813eJake Slack
19603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
19703928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
19803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see javax.servlet.RequestDispatcher#forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
19903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
20003928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void forward(ServletRequest request, ServletResponse response, DispatcherType dispatch) throws ServletException, IOException
20103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20203928aee4356845252ac6b662d5c72c29903813eJake Slack        Request baseRequest=(request instanceof Request)?((Request)request):AbstractHttpConnection.getCurrentConnection().getRequest();
20303928aee4356845252ac6b662d5c72c29903813eJake Slack        Response base_response=baseRequest.getResponse();
20403928aee4356845252ac6b662d5c72c29903813eJake Slack        response.resetBuffer();
20503928aee4356845252ac6b662d5c72c29903813eJake Slack        base_response.fwdReset();
20603928aee4356845252ac6b662d5c72c29903813eJake Slack
20703928aee4356845252ac6b662d5c72c29903813eJake Slack
20803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!(request instanceof HttpServletRequest))
20903928aee4356845252ac6b662d5c72c29903813eJake Slack            request = new ServletRequestHttpWrapper(request);
21003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!(response instanceof HttpServletResponse))
21103928aee4356845252ac6b662d5c72c29903813eJake Slack            response = new ServletResponseHttpWrapper(response);
21203928aee4356845252ac6b662d5c72c29903813eJake Slack
21303928aee4356845252ac6b662d5c72c29903813eJake Slack        final boolean old_handled=baseRequest.isHandled();
21403928aee4356845252ac6b662d5c72c29903813eJake Slack        final String old_uri=baseRequest.getRequestURI();
21503928aee4356845252ac6b662d5c72c29903813eJake Slack        final String old_context_path=baseRequest.getContextPath();
21603928aee4356845252ac6b662d5c72c29903813eJake Slack        final String old_servlet_path=baseRequest.getServletPath();
21703928aee4356845252ac6b662d5c72c29903813eJake Slack        final String old_path_info=baseRequest.getPathInfo();
21803928aee4356845252ac6b662d5c72c29903813eJake Slack        final String old_query=baseRequest.getQueryString();
21903928aee4356845252ac6b662d5c72c29903813eJake Slack        final Attributes old_attr=baseRequest.getAttributes();
22003928aee4356845252ac6b662d5c72c29903813eJake Slack        final DispatcherType old_type=baseRequest.getDispatcherType();
22103928aee4356845252ac6b662d5c72c29903813eJake Slack        MultiMap<String> old_params=baseRequest.getParameters();
22203928aee4356845252ac6b662d5c72c29903813eJake Slack
22303928aee4356845252ac6b662d5c72c29903813eJake Slack        try
22403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
22503928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setHandled(false);
22603928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setDispatcherType(dispatch);
22703928aee4356845252ac6b662d5c72c29903813eJake Slack
22803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_named!=null)
22903928aee4356845252ac6b662d5c72c29903813eJake Slack                _contextHandler.handle(_named,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
23003928aee4356845252ac6b662d5c72c29903813eJake Slack            else
23103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
23203928aee4356845252ac6b662d5c72c29903813eJake Slack
23303928aee4356845252ac6b662d5c72c29903813eJake Slack                // process any query string from the dispatch URL
23403928aee4356845252ac6b662d5c72c29903813eJake Slack                String query=_dQuery;
23503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (query!=null)
23603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
23703928aee4356845252ac6b662d5c72c29903813eJake Slack                    // force parameter extraction
23803928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (old_params==null)
23903928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
24003928aee4356845252ac6b662d5c72c29903813eJake Slack                        baseRequest.extractParameters();
24103928aee4356845252ac6b662d5c72c29903813eJake Slack                        old_params=baseRequest.getParameters();
24203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
24303928aee4356845252ac6b662d5c72c29903813eJake Slack
24403928aee4356845252ac6b662d5c72c29903813eJake Slack                    baseRequest.mergeQueryString(query);
24503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
24603928aee4356845252ac6b662d5c72c29903813eJake Slack
24703928aee4356845252ac6b662d5c72c29903813eJake Slack                ForwardAttributes attr = new ForwardAttributes(old_attr);
24803928aee4356845252ac6b662d5c72c29903813eJake Slack
24903928aee4356845252ac6b662d5c72c29903813eJake Slack                //If we have already been forwarded previously, then keep using the established
25003928aee4356845252ac6b662d5c72c29903813eJake Slack                //original value. Otherwise, this is the first forward and we need to establish the values.
25103928aee4356845252ac6b662d5c72c29903813eJake Slack                //Note: the established value on the original request for pathInfo and
25203928aee4356845252ac6b662d5c72c29903813eJake Slack                //for queryString is allowed to be null, but cannot be null for the other values.
25303928aee4356845252ac6b662d5c72c29903813eJake Slack                if (old_attr.getAttribute(FORWARD_REQUEST_URI) != null)
25403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
25503928aee4356845252ac6b662d5c72c29903813eJake Slack                    attr._pathInfo=(String)old_attr.getAttribute(FORWARD_PATH_INFO);
25603928aee4356845252ac6b662d5c72c29903813eJake Slack                    attr._query=(String)old_attr.getAttribute(FORWARD_QUERY_STRING);
25703928aee4356845252ac6b662d5c72c29903813eJake Slack                    attr._requestURI=(String)old_attr.getAttribute(FORWARD_REQUEST_URI);
25803928aee4356845252ac6b662d5c72c29903813eJake Slack                    attr._contextPath=(String)old_attr.getAttribute(FORWARD_CONTEXT_PATH);
25903928aee4356845252ac6b662d5c72c29903813eJake Slack                    attr._servletPath=(String)old_attr.getAttribute(FORWARD_SERVLET_PATH);
26003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
26103928aee4356845252ac6b662d5c72c29903813eJake Slack                else
26203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
26303928aee4356845252ac6b662d5c72c29903813eJake Slack                    attr._pathInfo=old_path_info;
26403928aee4356845252ac6b662d5c72c29903813eJake Slack                    attr._query=old_query;
26503928aee4356845252ac6b662d5c72c29903813eJake Slack                    attr._requestURI=old_uri;
26603928aee4356845252ac6b662d5c72c29903813eJake Slack                    attr._contextPath=old_context_path;
26703928aee4356845252ac6b662d5c72c29903813eJake Slack                    attr._servletPath=old_servlet_path;
26803928aee4356845252ac6b662d5c72c29903813eJake Slack                }
26903928aee4356845252ac6b662d5c72c29903813eJake Slack
27003928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setRequestURI(_uri);
27103928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setContextPath(_contextHandler.getContextPath());
27203928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setServletPath(null);
27303928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setPathInfo(_uri);
27403928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setAttributes(attr);
27503928aee4356845252ac6b662d5c72c29903813eJake Slack
27603928aee4356845252ac6b662d5c72c29903813eJake Slack                _contextHandler.handle(_path,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
27703928aee4356845252ac6b662d5c72c29903813eJake Slack
27803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!baseRequest.getAsyncContinuation().isAsyncStarted())
27903928aee4356845252ac6b662d5c72c29903813eJake Slack                    commitResponse(response,baseRequest);
28003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
28103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
28203928aee4356845252ac6b662d5c72c29903813eJake Slack        finally
28303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
28403928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setHandled(old_handled);
28503928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setRequestURI(old_uri);
28603928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setContextPath(old_context_path);
28703928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setServletPath(old_servlet_path);
28803928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setPathInfo(old_path_info);
28903928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setAttributes(old_attr);
29003928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setParameters(old_params);
29103928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setQueryString(old_query);
29203928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.setDispatcherType(old_type);
29303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
29403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
29503928aee4356845252ac6b662d5c72c29903813eJake Slack
29603928aee4356845252ac6b662d5c72c29903813eJake Slack
29703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
29803928aee4356845252ac6b662d5c72c29903813eJake Slack    private void commitResponse(ServletResponse response, Request baseRequest) throws IOException
29903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
30003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (baseRequest.getResponse().isWriting())
30103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
30203928aee4356845252ac6b662d5c72c29903813eJake Slack            try
30303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
30403928aee4356845252ac6b662d5c72c29903813eJake Slack                response.getWriter().close();
30503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
30603928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IllegalStateException e)
30703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
30803928aee4356845252ac6b662d5c72c29903813eJake Slack                response.getOutputStream().close();
30903928aee4356845252ac6b662d5c72c29903813eJake Slack            }
31003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
31103928aee4356845252ac6b662d5c72c29903813eJake Slack        else
31203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
31303928aee4356845252ac6b662d5c72c29903813eJake Slack            try
31403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
31503928aee4356845252ac6b662d5c72c29903813eJake Slack                response.getOutputStream().close();
31603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
31703928aee4356845252ac6b662d5c72c29903813eJake Slack            catch (IllegalStateException e)
31803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
31903928aee4356845252ac6b662d5c72c29903813eJake Slack                response.getWriter().close();
32003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
32103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
32203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
32303928aee4356845252ac6b662d5c72c29903813eJake Slack
32403928aee4356845252ac6b662d5c72c29903813eJake Slack
32503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
32603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
32703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
32803928aee4356845252ac6b662d5c72c29903813eJake Slack    private class ForwardAttributes implements Attributes
32903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
33003928aee4356845252ac6b662d5c72c29903813eJake Slack        final Attributes _attr;
33103928aee4356845252ac6b662d5c72c29903813eJake Slack
33203928aee4356845252ac6b662d5c72c29903813eJake Slack        String _requestURI;
33303928aee4356845252ac6b662d5c72c29903813eJake Slack        String _contextPath;
33403928aee4356845252ac6b662d5c72c29903813eJake Slack        String _servletPath;
33503928aee4356845252ac6b662d5c72c29903813eJake Slack        String _pathInfo;
33603928aee4356845252ac6b662d5c72c29903813eJake Slack        String _query;
33703928aee4356845252ac6b662d5c72c29903813eJake Slack
33803928aee4356845252ac6b662d5c72c29903813eJake Slack        ForwardAttributes(Attributes attributes)
33903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
34003928aee4356845252ac6b662d5c72c29903813eJake Slack            _attr=attributes;
34103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
34203928aee4356845252ac6b662d5c72c29903813eJake Slack
34303928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
34403928aee4356845252ac6b662d5c72c29903813eJake Slack        public Object getAttribute(String key)
34503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
34603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (Dispatcher.this._named==null)
34703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
34803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(FORWARD_PATH_INFO))
34903928aee4356845252ac6b662d5c72c29903813eJake Slack                    return _pathInfo;
35003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(FORWARD_REQUEST_URI))
35103928aee4356845252ac6b662d5c72c29903813eJake Slack                    return _requestURI;
35203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(FORWARD_SERVLET_PATH))
35303928aee4356845252ac6b662d5c72c29903813eJake Slack                    return _servletPath;
35403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(FORWARD_CONTEXT_PATH))
35503928aee4356845252ac6b662d5c72c29903813eJake Slack                    return _contextPath;
35603928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(FORWARD_QUERY_STRING))
35703928aee4356845252ac6b662d5c72c29903813eJake Slack                    return _query;
35803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
35903928aee4356845252ac6b662d5c72c29903813eJake Slack
36003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (key.startsWith(__INCLUDE_PREFIX))
36103928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
36203928aee4356845252ac6b662d5c72c29903813eJake Slack
36303928aee4356845252ac6b662d5c72c29903813eJake Slack            return _attr.getAttribute(key);
36403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
36503928aee4356845252ac6b662d5c72c29903813eJake Slack
36603928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
36703928aee4356845252ac6b662d5c72c29903813eJake Slack        public Enumeration getAttributeNames()
36803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
36903928aee4356845252ac6b662d5c72c29903813eJake Slack            HashSet set=new HashSet();
37003928aee4356845252ac6b662d5c72c29903813eJake Slack            Enumeration e=_attr.getAttributeNames();
37103928aee4356845252ac6b662d5c72c29903813eJake Slack            while(e.hasMoreElements())
37203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
37303928aee4356845252ac6b662d5c72c29903813eJake Slack                String name=(String)e.nextElement();
37403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!name.startsWith(__INCLUDE_PREFIX) &&
37503928aee4356845252ac6b662d5c72c29903813eJake Slack                    !name.startsWith(__FORWARD_PREFIX))
37603928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.add(name);
37703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
37803928aee4356845252ac6b662d5c72c29903813eJake Slack
37903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_named==null)
38003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
38103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_pathInfo!=null)
38203928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.add(FORWARD_PATH_INFO);
38303928aee4356845252ac6b662d5c72c29903813eJake Slack                else
38403928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.remove(FORWARD_PATH_INFO);
38503928aee4356845252ac6b662d5c72c29903813eJake Slack                set.add(FORWARD_REQUEST_URI);
38603928aee4356845252ac6b662d5c72c29903813eJake Slack                set.add(FORWARD_SERVLET_PATH);
38703928aee4356845252ac6b662d5c72c29903813eJake Slack                set.add(FORWARD_CONTEXT_PATH);
38803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_query!=null)
38903928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.add(FORWARD_QUERY_STRING);
39003928aee4356845252ac6b662d5c72c29903813eJake Slack                else
39103928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.remove(FORWARD_QUERY_STRING);
39203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
39303928aee4356845252ac6b662d5c72c29903813eJake Slack
39403928aee4356845252ac6b662d5c72c29903813eJake Slack            return Collections.enumeration(set);
39503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
39603928aee4356845252ac6b662d5c72c29903813eJake Slack
39703928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
39803928aee4356845252ac6b662d5c72c29903813eJake Slack        public void setAttribute(String key, Object value)
39903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
40003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_named==null && key.startsWith("javax.servlet."))
40103928aee4356845252ac6b662d5c72c29903813eJake Slack            {
40203928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(FORWARD_PATH_INFO))
40303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _pathInfo=(String)value;
40403928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (key.equals(FORWARD_REQUEST_URI))
40503928aee4356845252ac6b662d5c72c29903813eJake Slack                    _requestURI=(String)value;
40603928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (key.equals(FORWARD_SERVLET_PATH))
40703928aee4356845252ac6b662d5c72c29903813eJake Slack                    _servletPath=(String)value;
40803928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (key.equals(FORWARD_CONTEXT_PATH))
40903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _contextPath=(String)value;
41003928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (key.equals(FORWARD_QUERY_STRING))
41103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _query=(String)value;
41203928aee4356845252ac6b662d5c72c29903813eJake Slack
41303928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (value==null)
41403928aee4356845252ac6b662d5c72c29903813eJake Slack                    _attr.removeAttribute(key);
41503928aee4356845252ac6b662d5c72c29903813eJake Slack                else
41603928aee4356845252ac6b662d5c72c29903813eJake Slack                    _attr.setAttribute(key,value);
41703928aee4356845252ac6b662d5c72c29903813eJake Slack            }
41803928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (value==null)
41903928aee4356845252ac6b662d5c72c29903813eJake Slack                _attr.removeAttribute(key);
42003928aee4356845252ac6b662d5c72c29903813eJake Slack            else
42103928aee4356845252ac6b662d5c72c29903813eJake Slack                _attr.setAttribute(key,value);
42203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
42303928aee4356845252ac6b662d5c72c29903813eJake Slack
42403928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
42503928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
42603928aee4356845252ac6b662d5c72c29903813eJake Slack        public String toString()
42703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
42803928aee4356845252ac6b662d5c72c29903813eJake Slack            return "FORWARD+"+_attr.toString();
42903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
43003928aee4356845252ac6b662d5c72c29903813eJake Slack
43103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
43203928aee4356845252ac6b662d5c72c29903813eJake Slack        public void clearAttributes()
43303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
43403928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException();
43503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
43603928aee4356845252ac6b662d5c72c29903813eJake Slack
43703928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
43803928aee4356845252ac6b662d5c72c29903813eJake Slack        public void removeAttribute(String name)
43903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
44003928aee4356845252ac6b662d5c72c29903813eJake Slack            setAttribute(name,null);
44103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
44203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
44303928aee4356845252ac6b662d5c72c29903813eJake Slack
44403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
44503928aee4356845252ac6b662d5c72c29903813eJake Slack    private class IncludeAttributes implements Attributes
44603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
44703928aee4356845252ac6b662d5c72c29903813eJake Slack        final Attributes _attr;
44803928aee4356845252ac6b662d5c72c29903813eJake Slack
44903928aee4356845252ac6b662d5c72c29903813eJake Slack        String _requestURI;
45003928aee4356845252ac6b662d5c72c29903813eJake Slack        String _contextPath;
45103928aee4356845252ac6b662d5c72c29903813eJake Slack        String _servletPath;
45203928aee4356845252ac6b662d5c72c29903813eJake Slack        String _pathInfo;
45303928aee4356845252ac6b662d5c72c29903813eJake Slack        String _query;
45403928aee4356845252ac6b662d5c72c29903813eJake Slack
45503928aee4356845252ac6b662d5c72c29903813eJake Slack        IncludeAttributes(Attributes attributes)
45603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
45703928aee4356845252ac6b662d5c72c29903813eJake Slack            _attr=attributes;
45803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
45903928aee4356845252ac6b662d5c72c29903813eJake Slack
46003928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
46103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
46203928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
46303928aee4356845252ac6b662d5c72c29903813eJake Slack        public Object getAttribute(String key)
46403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
46503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (Dispatcher.this._named==null)
46603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
46703928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(INCLUDE_PATH_INFO))    return _pathInfo;
46803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(INCLUDE_SERVLET_PATH)) return _servletPath;
46903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(INCLUDE_CONTEXT_PATH)) return _contextPath;
47003928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(INCLUDE_QUERY_STRING)) return _query;
47103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(INCLUDE_REQUEST_URI))  return _requestURI;
47203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
47303928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (key.startsWith(__INCLUDE_PREFIX))
47403928aee4356845252ac6b662d5c72c29903813eJake Slack                    return null;
47503928aee4356845252ac6b662d5c72c29903813eJake Slack
47603928aee4356845252ac6b662d5c72c29903813eJake Slack
47703928aee4356845252ac6b662d5c72c29903813eJake Slack            return _attr.getAttribute(key);
47803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
47903928aee4356845252ac6b662d5c72c29903813eJake Slack
48003928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
48103928aee4356845252ac6b662d5c72c29903813eJake Slack        public Enumeration getAttributeNames()
48203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
48303928aee4356845252ac6b662d5c72c29903813eJake Slack            HashSet set=new HashSet();
48403928aee4356845252ac6b662d5c72c29903813eJake Slack            Enumeration e=_attr.getAttributeNames();
48503928aee4356845252ac6b662d5c72c29903813eJake Slack            while(e.hasMoreElements())
48603928aee4356845252ac6b662d5c72c29903813eJake Slack            {
48703928aee4356845252ac6b662d5c72c29903813eJake Slack                String name=(String)e.nextElement();
48803928aee4356845252ac6b662d5c72c29903813eJake Slack                if (!name.startsWith(__INCLUDE_PREFIX))
48903928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.add(name);
49003928aee4356845252ac6b662d5c72c29903813eJake Slack            }
49103928aee4356845252ac6b662d5c72c29903813eJake Slack
49203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_named==null)
49303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
49403928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_pathInfo!=null)
49503928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.add(INCLUDE_PATH_INFO);
49603928aee4356845252ac6b662d5c72c29903813eJake Slack                else
49703928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.remove(INCLUDE_PATH_INFO);
49803928aee4356845252ac6b662d5c72c29903813eJake Slack                set.add(INCLUDE_REQUEST_URI);
49903928aee4356845252ac6b662d5c72c29903813eJake Slack                set.add(INCLUDE_SERVLET_PATH);
50003928aee4356845252ac6b662d5c72c29903813eJake Slack                set.add(INCLUDE_CONTEXT_PATH);
50103928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_query!=null)
50203928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.add(INCLUDE_QUERY_STRING);
50303928aee4356845252ac6b662d5c72c29903813eJake Slack                else
50403928aee4356845252ac6b662d5c72c29903813eJake Slack                    set.remove(INCLUDE_QUERY_STRING);
50503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
50603928aee4356845252ac6b662d5c72c29903813eJake Slack
50703928aee4356845252ac6b662d5c72c29903813eJake Slack            return Collections.enumeration(set);
50803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
50903928aee4356845252ac6b662d5c72c29903813eJake Slack
51003928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
51103928aee4356845252ac6b662d5c72c29903813eJake Slack        public void setAttribute(String key, Object value)
51203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
51303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_named==null && key.startsWith("javax.servlet."))
51403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
51503928aee4356845252ac6b662d5c72c29903813eJake Slack                if (key.equals(INCLUDE_PATH_INFO))         _pathInfo=(String)value;
51603928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (key.equals(INCLUDE_REQUEST_URI))  _requestURI=(String)value;
51703928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (key.equals(INCLUDE_SERVLET_PATH)) _servletPath=(String)value;
51803928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (key.equals(INCLUDE_CONTEXT_PATH)) _contextPath=(String)value;
51903928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (key.equals(INCLUDE_QUERY_STRING)) _query=(String)value;
52003928aee4356845252ac6b662d5c72c29903813eJake Slack                else if (value==null)
52103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _attr.removeAttribute(key);
52203928aee4356845252ac6b662d5c72c29903813eJake Slack                else
52303928aee4356845252ac6b662d5c72c29903813eJake Slack                    _attr.setAttribute(key,value);
52403928aee4356845252ac6b662d5c72c29903813eJake Slack            }
52503928aee4356845252ac6b662d5c72c29903813eJake Slack            else if (value==null)
52603928aee4356845252ac6b662d5c72c29903813eJake Slack                _attr.removeAttribute(key);
52703928aee4356845252ac6b662d5c72c29903813eJake Slack            else
52803928aee4356845252ac6b662d5c72c29903813eJake Slack                _attr.setAttribute(key,value);
52903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
53003928aee4356845252ac6b662d5c72c29903813eJake Slack
53103928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
53203928aee4356845252ac6b662d5c72c29903813eJake Slack        @Override
53303928aee4356845252ac6b662d5c72c29903813eJake Slack        public String toString()
53403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
53503928aee4356845252ac6b662d5c72c29903813eJake Slack            return "INCLUDE+"+_attr.toString();
53603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
53703928aee4356845252ac6b662d5c72c29903813eJake Slack
53803928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
53903928aee4356845252ac6b662d5c72c29903813eJake Slack        public void clearAttributes()
54003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
54103928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException();
54203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
54303928aee4356845252ac6b662d5c72c29903813eJake Slack
54403928aee4356845252ac6b662d5c72c29903813eJake Slack        /* ------------------------------------------------------------ */
54503928aee4356845252ac6b662d5c72c29903813eJake Slack        public void removeAttribute(String name)
54603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
54703928aee4356845252ac6b662d5c72c29903813eJake Slack            setAttribute(name,null);
54803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
54903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
55003928aee4356845252ac6b662d5c72c29903813eJake Slack}
551