⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 requestdispatcherimpl.java

📁 低版本的tomcat 对于有些老版本的应用还真的需要老版的中间件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * ====================================================================
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * [Additional notices, if required by prior licensing conditions]
 *
 */


package org.apache.tomcat.facade;

import org.apache.tomcat.core.*;
import org.apache.tomcat.util.StringManager;
import java.io.*;
import java.util.*;
import java.security.*;
import javax.servlet.*;
import javax.servlet.http.*;

/* This code needs a re-write, it's very ugly.
   The hardest problem is the requirement to pass the "same" request, but with
   small modifications. One solution is to use a facade ( was used in tomcat
   origianlly ). The current solution is to save the modified attributes
   and restore after the method returns. This saves one object creation -
   since the subRequest object still has to be created.

   The details are facade-specific, shouldn't affect the core.
*/

/*
  We do a new sub-request for each include() or forward().
  Even if today we take all decisions based only on path, that may
  change ( i.e. a request can take different paths based on authentication,
  headers, etc - other Interceptors may affect it), that means we need to
  call CM.

  I think this is the correct action - instead of doing a lookup when
  we construct the dispatcher. ( costin )
 */

/**
 *
 *
 * @author James Duncan Davidson [duncan@eng.sun.com]
 * @author Jason Hunter [jch@eng.sun.com]
 * @author James Todd [gonzo@eng.sun.com]
 * @author Alex Cruikshank [alex@epitonic.com]
 * @author costin@dnt.ro
 */
final class RequestDispatcherImpl implements RequestDispatcher {
    // Use the strings from core
    private static StringManager sm = StringManager.
	getManager("org.apache.tomcat.core");
    
    Context context;
    // path dispatchers
    String path;
    String queryString;

    // name dispatchers
    String name;

    /** Used for Context.getRD( path )
     */
    public RequestDispatcherImpl(Context context) {
        this.context = context;
    }

    public void setPath( String urlPath ) {
	// separate the query string
	int i = urlPath.indexOf("?");
	if( i<0 )
	    this.path=urlPath;
	else {
	    this.path=urlPath.substring( 0,i );
	    int len=urlPath.length();
	    if( i< len )
		this.queryString =urlPath.substring(i + 1);
        }
    }

    public void setName( String name ) {
	this.name=name;
    }

    // -------------------- Public methods --------------------
    
    public void forward(ServletRequest request, ServletResponse response)
	throws ServletException, IOException
    {
	if( System.getSecurityManager() != null ) {
	    final ServletRequest req = request;
	    final ServletResponse res = response;
	    try {
	        java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedExceptionAction()
                    {
                        public Object run() throws ServletException, IOException {
			    doForward(req,res);
                            return null;
			}
                    }               
	        );
	    } catch( PrivilegedActionException pe) {
		Exception e = pe.getException();
		if( e.getClass().getName().equals("javax.servlet.ServletException") )
		    throw (ServletException)e;
		throw (IOException)e;
	    }
	} else {
	    doForward(request,response);
	}
    }

    private void doForward(ServletRequest request, ServletResponse response)
        throws ServletException, IOException
    {
	/** We need to find the request/response. The servlet API
	 *  guarantees that we will receive the original request as parameter.
	 */
	Request realRequest = ((HttpServletRequestFacade)request).
	    getRealRequest();
        Response realResponse = realRequest.getResponse();

	// according to specs (as of 2.2: started is OK, just not committed)
	if (realResponse.isBufferCommitted()) 
	    throw new IllegalStateException(sm.getString("rdi.forward.ise"));

	// reset the output buffer but not the headers and cookies
	realResponse.resetBuffer();

	// the strange case in a separate method.
	if( name!=null) {
	    forwardNamed( request, response );
	    return;
	}
	
	// from strange spec reasons, forward and include are very different in
	// the way they process the request - if you don't understand the code
	// try to understand the spec.
	
	// in forward case, the Path parametrs of the request are what you 
	// expect, so we just do a new processRequest on the modified request

	// set the context - no need to fire context parsing again
	realRequest.setContext( context );

	realRequest.setRequestURI( context.getPath() + path );

	// merge query string as specified in specs - before, it may affect
	// the way the request is handled by special interceptors
	if( queryString != null )
	    addQueryString( realRequest, queryString );
	
	// run the new request through the context manager
	// not that this is a very particular case of forwarding
	context.getContextManager().processRequest(realRequest);

	// unset "included" attribute if any - we may be in a servlet
	// included from another servlet,
	// in which case the attribute will create problems
	realRequest.removeAttribute( "javax.servlet.include.request_uri");
	realRequest.removeAttribute( "javax.servlet.include.servlet_path");


	// CM should have set the wrapper - call it
	ServletWrapper wr=realRequest.getWrapper();
        Throwable t = null;
        if( wr != null ) {
            try {
                wr.service(realRequest, realResponse);
            } catch (Throwable t1) {
                t = t1;
            }
        }

        // Clean up the request and response as needed
        ;       // No action required

        // Rethrow any exception thrown by the forwarded-to servlet
        if (t != null) {
            if (t instanceof IOException)
                throw (IOException) t;
            else if (t instanceof ServletException)
                throw (ServletException) t;
            else
                throw new ServletException
                    (sm.getString("dispatcher.forwardException", t));
        }

	// close the response - output after this point will be discarded.
	realResponse.finish();
	
    }

    public void include(ServletRequest request, ServletResponse response)
	throws ServletException, IOException
    {
        if( System.getSecurityManager() != null ) {
            final ServletRequest req = request;
            final ServletResponse res = response;
            try {
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedExceptionAction()
                    {
                        public Object run() throws ServletException, IOException {
                            doInclude(req,res);
                            return null;     
                        }               
                    }    
                );   
            } catch( PrivilegedActionException pe) {
                Exception e = pe.getException();       
                if( e.getClass().getName().equals("javax.servlet.ServletException") )
                    throw (ServletException)e;
                throw (IOException)e;
            }
        } else {
	    doInclude(request,response);
	}
    }

    private void doInclude(ServletRequest request, ServletResponse response)
        throws ServletException, IOException
    {
        Request realRequest = ((HttpServletRequestFacade)request).
	    getRealRequest();
	Response realResponse = realRequest.getResponse();

	// the strange case in a separate method
	if( name!=null) {
	    includeNamed( request, response );
	    return;
	}
	
	// Add an unspecified response.flushBuffer() call to work around
	// a fundamental problem in the way that the session interceptor
	// works.  If we do not do this, the session cookie gets dropped (!)
	// if the first flush of the buffer happens inside an included
	// servlet.  This occurs because the session interceptor uses the
	// normal response.addHeader() method to add the cookie -- but such
	// header changes are suppressed inside an included servlet.
	// (Reference: BugRat bug report #316)
	//
	// NOTE:  This *must* be done before the include flag is set for
	// this request!
	response.flushBuffer();

	// Implement the spec that "no changes in response, only write"
	// can also be done by setting the response to 0.9 mode
	//	IncludedResponse iResponse = new IncludedResponse(realResponse);
	boolean old_included=realResponse.isIncluded();
	if( ! old_included ) {
	    realResponse.setIncluded( true );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -