FileDocCategorySizeDatePackage
InvokerServlet.javaAPI DocApache Tomcat 6.0.1414980Fri Jul 20 04:20:34 BST 2007org.apache.catalina.servlets

InvokerServlet

public final class InvokerServlet extends HttpServlet implements org.apache.catalina.ContainerServlet
The default servlet-invoking servlet for most web applications, used to serve requests to servlets that have not been registered in the web application deployment descriptor.
author
Craig R. McClanahan
version
$Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $

Fields Summary
private org.apache.catalina.Context
context
The Context container associated with our web application.
private int
debug
The debugging detail level for this servlet.
private static org.apache.catalina.util.StringManager
sm
The string manager for this package.
private org.apache.catalina.Wrapper
wrapper
The Wrapper container associated with this servlet.
Constructors Summary
Methods Summary
public voiddestroy()
Finalize this servlet.


        ;       // No actions necessary

    
public voiddoGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
Process a GET request for the specified resource.

param
request The servlet request we are processing
param
response The servlet response we are creating
exception
IOException if an input/output error occurs
exception
ServletException if a servlet-specified error occurs


        serveRequest(request, response);

    
public voiddoHead(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
Process a HEAD request for the specified resource.

param
request The servlet request we are processing
param
response The servlet response we are creating
exception
IOException if an input/output error occurs
exception
ServletException if a servlet-specified error occurs


        serveRequest(request, response);

    
public voiddoPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
Process a POST request for the specified resource.

param
request The servlet request we are processing
param
response The servlet response we are creating
exception
IOException if an input/output error occurs
exception
ServletException if a servlet-specified error occurs


        serveRequest(request, response);

    
public org.apache.catalina.WrappergetWrapper()
Return the Wrapper with which we are associated.



    // ----------------------------------------------- ContainerServlet Methods


                 
       

        return (this.wrapper);

    
public voidinit()
Initialize this servlet.


        // Ensure that our ContainerServlet properties have been set
        if ((wrapper == null) || (context == null))
            throw new UnavailableException
                (sm.getString("invokerServlet.noWrapper"));

        // Set our properties from the initialization parameters
        if (getServletConfig().getInitParameter("debug") != null)
            debug = Integer.parseInt(getServletConfig().getInitParameter("debug"));

        if (debug >= 1)
            log("init: Associated with Context '" + context.getPath() + "'");

    
public voidserveRequest(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
Serve the specified request, creating the corresponding response. After the first time a particular servlet class is requested, it will be served directly (like any registered servlet) because it will have been registered and mapped in our associated Context.

param
request The servlet request we are processing
param
response The servlet response we are creating
exception
IOException if an input/output error occurs
exception
ServletException if a servlet-specified error occurs


        // Disallow calling this servlet via a named dispatcher
        if (request.getAttribute(Globals.NAMED_DISPATCHER_ATTR) != null)
            throw new ServletException
                (sm.getString("invokerServlet.notNamed"));

        // Identify the input parameters and our "included" state
        String inRequestURI = null;
        String inServletPath = null;
        String inPathInfo = null;
        boolean included =
            (request.getAttribute(Globals.INCLUDE_REQUEST_URI_ATTR) != null);

        if (included) {
            inRequestURI =
                (String) request.getAttribute(Globals.INCLUDE_REQUEST_URI_ATTR);
            inServletPath =
                (String) request.getAttribute(Globals.INCLUDE_SERVLET_PATH_ATTR);
            inPathInfo =
                (String) request.getAttribute(Globals.INCLUDE_PATH_INFO_ATTR);
        } else {
            inRequestURI = request.getRequestURI();
            inServletPath = request.getServletPath();
            inPathInfo = request.getPathInfo();
        }
        if (debug >= 1) {
            log("included='" + included + "', requestURI='" +
                inRequestURI + "'");
            log("  servletPath='" + inServletPath + "', pathInfo='" +
                inPathInfo + "'");
        }

        // Make sure a servlet name or class name was specified
        if (inPathInfo == null) {
            if (debug >= 1)
                log("Invalid pathInfo '" + inPathInfo + "'");
            if (included)
                throw new ServletException
                    (sm.getString("invokerServlet.invalidPath", inRequestURI));
            else {
                response.sendError(HttpServletResponse.SC_NOT_FOUND,
                                   inRequestURI);
                return;
            }
        }

        // Identify the outgoing servlet name or class, and outgoing path info
        String pathInfo = inPathInfo;
        String servletClass = pathInfo.substring(1);
        int slash = servletClass.indexOf('/");
        if (slash >= 0) {
            pathInfo = servletClass.substring(slash);
            servletClass = servletClass.substring(0, slash);
        } else {
            pathInfo = "";
        }

        if (servletClass.startsWith("org.apache.catalina")) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND,
                               inRequestURI);
            return;
        }

        if (debug >= 1)
            log("Processing servlet '" + servletClass +
                "' with path info '" + pathInfo + "'");
        String name = "org.apache.catalina.INVOKER." + servletClass;
        String pattern = inServletPath + "/" + servletClass + "/*";
        Wrapper wrapper = null;

        // Synchronize to avoid race conditions when multiple requests
        // try to initialize the same servlet at the same time
        synchronized (this) {

            // Are we referencing an existing servlet class or name?
            wrapper = (Wrapper) context.findChild(servletClass);
            if (wrapper == null)
                wrapper = (Wrapper) context.findChild(name);
            if (wrapper != null) {
                String actualServletClass = wrapper.getServletClass();
                if ((actualServletClass != null)
                    && (actualServletClass.startsWith
                        ("org.apache.catalina"))) {
                    response.sendError(HttpServletResponse.SC_NOT_FOUND,
                                       inRequestURI);
                    return;
                }
                if (debug >= 1)
                    log("Using wrapper for servlet '" +
                        wrapper.getName() + "' with mapping '" +
                        pattern + "'");
                context.addServletMapping(pattern, wrapper.getName());
            }

            // No, create a new wrapper for the specified servlet class
            else {

                if (debug >= 1)
                    log("Creating wrapper for '" + servletClass +
                        "' with mapping '" + pattern + "'");

                try {
                    wrapper = context.createWrapper();
                    wrapper.setName(name);
                    wrapper.setLoadOnStartup(1);
                    wrapper.setServletClass(servletClass);
                    context.addChild(wrapper);
                    context.addServletMapping(pattern, name);
                } catch (Exception e) {
                    log(sm.getString("invokerServlet.cannotCreate",
                                     inRequestURI), e);
                    context.removeServletMapping(pattern);
                    context.removeChild(wrapper);
                    if (included)
                        throw new ServletException
                            (sm.getString("invokerServlet.cannotCreate",
                                          inRequestURI), e);
                    else {
                        response.sendError(HttpServletResponse.SC_NOT_FOUND,
                                           inRequestURI);
                        return;
                    }
                }
            }

        }

        // Create a request wrapper to pass on to the invoked servlet
        InvokerHttpRequest wrequest =
            new InvokerHttpRequest(request);
        wrequest.setRequestURI(inRequestURI);
        StringBuffer sb = new StringBuffer(inServletPath);
        sb.append("/");
        sb.append(servletClass);
        wrequest.setServletPath(sb.toString());
        if ((pathInfo == null) || (pathInfo.length() < 1)) {
            wrequest.setPathInfo(null);
            wrequest.setPathTranslated(null);
        } else {
            wrequest.setPathInfo(pathInfo);
            wrequest.setPathTranslated
                (getServletContext().getRealPath(pathInfo));
        }

        // Allocate a servlet instance to perform this request
        Servlet instance = null;
        try {
            instance = wrapper.allocate();
        } catch (ServletException e) {
            log(sm.getString("invokerServlet.allocate", inRequestURI), e);
            context.removeServletMapping(pattern);
            context.removeChild(wrapper);
            Throwable rootCause = e.getRootCause();
            if (rootCause == null)
                rootCause = e;
            if (rootCause instanceof ClassNotFoundException) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND,
                                   inRequestURI);
                return;
            } else if (rootCause instanceof IOException) {
                throw (IOException) rootCause;
            } else if (rootCause instanceof RuntimeException) {
                throw (RuntimeException) rootCause;
            } else if (rootCause instanceof ServletException) {
                throw (ServletException) rootCause;
            } else {
                throw new ServletException
                    (sm.getString("invokerServlet.allocate", inRequestURI),
                     rootCause);
            }
        }

        // After loading the wrapper, restore some of the fields when including
        if (included) {
            wrequest.setRequestURI(request.getRequestURI());
            wrequest.setPathInfo(request.getPathInfo());
            wrequest.setServletPath(request.getServletPath());
        }

        // Invoke the service() method of the allocated servlet
        try {
            String jspFile = wrapper.getJspFile();
            if (jspFile != null)
                request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
            else
                request.removeAttribute(Globals.JSP_FILE_ATTR);
            request.setAttribute(Globals.INVOKED_ATTR,
                                 request.getServletPath());
            instance.service(wrequest, response);
        } catch (UnavailableException e) {
            context.removeServletMapping(pattern);
            throw e;
        } finally {
            request.removeAttribute(Globals.INVOKED_ATTR);
            request.removeAttribute(Globals.JSP_FILE_ATTR);
            // Deallocate the allocated servlet instance
            try {
                wrapper.deallocate(instance);
            } catch (ServletException e) {
                log(sm.getString("invokerServlet.deallocate", inRequestURI), e);
                throw e;
            }
        }

    
public voidsetWrapper(org.apache.catalina.Wrapper wrapper)
Set the Wrapper with which we are associated.

param
wrapper The new wrapper


        this.wrapper = wrapper;
        if (wrapper == null)
            context = null;
        else
            context = (Context) wrapper.getParent();