Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » servlets » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.catalina.servlets;
   20   
   21   
   22   import java.io.IOException;
   23   
   24   import javax.servlet.Servlet;
   25   import javax.servlet.ServletException;
   26   import javax.servlet.UnavailableException;
   27   import javax.servlet.http.HttpServlet;
   28   import javax.servlet.http.HttpServletRequest;
   29   import javax.servlet.http.HttpServletResponse;
   30   
   31   import org.apache.catalina.ContainerServlet;
   32   import org.apache.catalina.Context;
   33   import org.apache.catalina.Globals;
   34   import org.apache.catalina.Wrapper;
   35   import org.apache.catalina.util.StringManager;
   36   
   37   
   38   /**
   39    * The default servlet-invoking servlet for most web applications,
   40    * used to serve requests to servlets that have not been registered
   41    * in the web application deployment descriptor.
   42    *
   43    * @author Craig R. McClanahan
   44    * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
   45    */
   46   
   47   public final class InvokerServlet
   48       extends HttpServlet implements ContainerServlet {
   49   
   50   
   51       // ----------------------------------------------------- Instance Variables
   52   
   53   
   54       /**
   55        * The Context container associated with our web application.
   56        */
   57       private Context context = null;
   58   
   59   
   60       /**
   61        * The debugging detail level for this servlet.
   62        */
   63       private int debug = 0;
   64   
   65   
   66       /**
   67        * The string manager for this package.
   68        */
   69       private static StringManager sm =
   70           StringManager.getManager(Constants.Package);
   71   
   72   
   73       /**
   74        * The Wrapper container associated with this servlet.
   75        */
   76       private Wrapper wrapper = null;
   77   
   78   
   79       // ----------------------------------------------- ContainerServlet Methods
   80   
   81   
   82       /**
   83        * Return the Wrapper with which we are associated.
   84        */
   85       public Wrapper getWrapper() {
   86   
   87           return (this.wrapper);
   88   
   89       }
   90   
   91   
   92       /**
   93        * Set the Wrapper with which we are associated.
   94        *
   95        * @param wrapper The new wrapper
   96        */
   97       public void setWrapper(Wrapper wrapper) {
   98   
   99           this.wrapper = wrapper;
  100           if (wrapper == null)
  101               context = null;
  102           else
  103               context = (Context) wrapper.getParent();
  104   
  105       }
  106   
  107   
  108       // --------------------------------------------------------- Public Methods
  109   
  110   
  111       /**
  112        * Finalize this servlet.
  113        */
  114       public void destroy() {
  115   
  116           ;       // No actions necessary
  117   
  118       }
  119   
  120   
  121       /**
  122        * Process a GET request for the specified resource.
  123        *
  124        * @param request The servlet request we are processing
  125        * @param response The servlet response we are creating
  126        *
  127        * @exception IOException if an input/output error occurs
  128        * @exception ServletException if a servlet-specified error occurs
  129        */
  130       public void doGet(HttpServletRequest request,
  131                         HttpServletResponse response)
  132           throws IOException, ServletException {
  133   
  134           serveRequest(request, response);
  135   
  136       }
  137   
  138   
  139       /**
  140        * Process a HEAD request for the specified resource.
  141        *
  142        * @param request The servlet request we are processing
  143        * @param response The servlet response we are creating
  144        *
  145        * @exception IOException if an input/output error occurs
  146        * @exception ServletException if a servlet-specified error occurs
  147        */
  148       public void doHead(HttpServletRequest request,
  149                          HttpServletResponse response)
  150           throws IOException, ServletException {
  151   
  152           serveRequest(request, response);
  153   
  154       }
  155   
  156   
  157       /**
  158        * Process a POST request for the specified resource.
  159        *
  160        * @param request The servlet request we are processing
  161        * @param response The servlet response we are creating
  162        *
  163        * @exception IOException if an input/output error occurs
  164        * @exception ServletException if a servlet-specified error occurs
  165        */
  166       public void doPost(HttpServletRequest request,
  167                          HttpServletResponse response)
  168           throws IOException, ServletException {
  169   
  170           serveRequest(request, response);
  171   
  172       }
  173   
  174   
  175       /**
  176        * Initialize this servlet.
  177        */
  178       public void init() throws ServletException {
  179   
  180           // Ensure that our ContainerServlet properties have been set
  181           if ((wrapper == null) || (context == null))
  182               throw new UnavailableException
  183                   (sm.getString("invokerServlet.noWrapper"));
  184   
  185           // Set our properties from the initialization parameters
  186           if (getServletConfig().getInitParameter("debug") != null)
  187               debug = Integer.parseInt(getServletConfig().getInitParameter("debug"));
  188   
  189           if (debug >= 1)
  190               log("init: Associated with Context '" + context.getPath() + "'");
  191   
  192       }
  193   
  194   
  195   
  196       // -------------------------------------------------------- Private Methods
  197   
  198   
  199       /**
  200        * Serve the specified request, creating the corresponding response.
  201        * After the first time a particular servlet class is requested, it will
  202        * be served directly (like any registered servlet) because it will have
  203        * been registered and mapped in our associated Context.
  204        *
  205        * @param request The servlet request we are processing
  206        * @param response The servlet response we are creating
  207        *
  208        * @exception IOException if an input/output error occurs
  209        * @exception ServletException if a servlet-specified error occurs
  210        */
  211       public void serveRequest(HttpServletRequest request,
  212                                HttpServletResponse response)
  213           throws IOException, ServletException {
  214   
  215           // Disallow calling this servlet via a named dispatcher
  216           if (request.getAttribute(Globals.NAMED_DISPATCHER_ATTR) != null)
  217               throw new ServletException
  218                   (sm.getString("invokerServlet.notNamed"));
  219   
  220           // Identify the input parameters and our "included" state
  221           String inRequestURI = null;
  222           String inServletPath = null;
  223           String inPathInfo = null;
  224           boolean included =
  225               (request.getAttribute(Globals.INCLUDE_REQUEST_URI_ATTR) != null);
  226   
  227           if (included) {
  228               inRequestURI =
  229                   (String) request.getAttribute(Globals.INCLUDE_REQUEST_URI_ATTR);
  230               inServletPath =
  231                   (String) request.getAttribute(Globals.INCLUDE_SERVLET_PATH_ATTR);
  232               inPathInfo =
  233                   (String) request.getAttribute(Globals.INCLUDE_PATH_INFO_ATTR);
  234           } else {
  235               inRequestURI = request.getRequestURI();
  236               inServletPath = request.getServletPath();
  237               inPathInfo = request.getPathInfo();
  238           }
  239           if (debug >= 1) {
  240               log("included='" + included + "', requestURI='" +
  241                   inRequestURI + "'");
  242               log("  servletPath='" + inServletPath + "', pathInfo='" +
  243                   inPathInfo + "'");
  244           }
  245   
  246           // Make sure a servlet name or class name was specified
  247           if (inPathInfo == null) {
  248               if (debug >= 1)
  249                   log("Invalid pathInfo '" + inPathInfo + "'");
  250               if (included)
  251                   throw new ServletException
  252                       (sm.getString("invokerServlet.invalidPath", inRequestURI));
  253               else {
  254                   response.sendError(HttpServletResponse.SC_NOT_FOUND,
  255                                      inRequestURI);
  256                   return;
  257               }
  258           }
  259   
  260           // Identify the outgoing servlet name or class, and outgoing path info
  261           String pathInfo = inPathInfo;
  262           String servletClass = pathInfo.substring(1);
  263           int slash = servletClass.indexOf('/');
  264           if (slash >= 0) {
  265               pathInfo = servletClass.substring(slash);
  266               servletClass = servletClass.substring(0, slash);
  267           } else {
  268               pathInfo = "";
  269           }
  270   
  271           if (servletClass.startsWith("org.apache.catalina")) {
  272               response.sendError(HttpServletResponse.SC_NOT_FOUND,
  273                                  inRequestURI);
  274               return;
  275           }
  276   
  277           if (debug >= 1)
  278               log("Processing servlet '" + servletClass +
  279                   "' with path info '" + pathInfo + "'");
  280           String name = "org.apache.catalina.INVOKER." + servletClass;
  281           String pattern = inServletPath + "/" + servletClass + "/*";
  282           Wrapper wrapper = null;
  283   
  284           // Synchronize to avoid race conditions when multiple requests
  285           // try to initialize the same servlet at the same time
  286           synchronized (this) {
  287   
  288               // Are we referencing an existing servlet class or name?
  289               wrapper = (Wrapper) context.findChild(servletClass);
  290               if (wrapper == null)
  291                   wrapper = (Wrapper) context.findChild(name);
  292               if (wrapper != null) {
  293                   String actualServletClass = wrapper.getServletClass();
  294                   if ((actualServletClass != null)
  295                       && (actualServletClass.startsWith
  296                           ("org.apache.catalina"))) {
  297                       response.sendError(HttpServletResponse.SC_NOT_FOUND,
  298                                          inRequestURI);
  299                       return;
  300                   }
  301                   if (debug >= 1)
  302                       log("Using wrapper for servlet '" +
  303                           wrapper.getName() + "' with mapping '" +
  304                           pattern + "'");
  305                   context.addServletMapping(pattern, wrapper.getName());
  306               }
  307   
  308               // No, create a new wrapper for the specified servlet class
  309               else {
  310   
  311                   if (debug >= 1)
  312                       log("Creating wrapper for '" + servletClass +
  313                           "' with mapping '" + pattern + "'");
  314   
  315                   try {
  316                       wrapper = context.createWrapper();
  317                       wrapper.setName(name);
  318                       wrapper.setLoadOnStartup(1);
  319                       wrapper.setServletClass(servletClass);
  320                       context.addChild(wrapper);
  321                       context.addServletMapping(pattern, name);
  322                   } catch (Exception e) {
  323                       log(sm.getString("invokerServlet.cannotCreate",
  324                                        inRequestURI), e);
  325                       context.removeServletMapping(pattern);
  326                       context.removeChild(wrapper);
  327                       if (included)
  328                           throw new ServletException
  329                               (sm.getString("invokerServlet.cannotCreate",
  330                                             inRequestURI), e);
  331                       else {
  332                           response.sendError(HttpServletResponse.SC_NOT_FOUND,
  333                                              inRequestURI);
  334                           return;
  335                       }
  336                   }
  337               }
  338   
  339           }
  340   
  341           // Create a request wrapper to pass on to the invoked servlet
  342           InvokerHttpRequest wrequest =
  343               new InvokerHttpRequest(request);
  344           wrequest.setRequestURI(inRequestURI);
  345           StringBuffer sb = new StringBuffer(inServletPath);
  346           sb.append("/");
  347           sb.append(servletClass);
  348           wrequest.setServletPath(sb.toString());
  349           if ((pathInfo == null) || (pathInfo.length() < 1)) {
  350               wrequest.setPathInfo(null);
  351               wrequest.setPathTranslated(null);
  352           } else {
  353               wrequest.setPathInfo(pathInfo);
  354               wrequest.setPathTranslated
  355                   (getServletContext().getRealPath(pathInfo));
  356           }
  357   
  358           // Allocate a servlet instance to perform this request
  359           Servlet instance = null;
  360           try {
  361               instance = wrapper.allocate();
  362           } catch (ServletException e) {
  363               log(sm.getString("invokerServlet.allocate", inRequestURI), e);
  364               context.removeServletMapping(pattern);
  365               context.removeChild(wrapper);
  366               Throwable rootCause = e.getRootCause();
  367               if (rootCause == null)
  368                   rootCause = e;
  369               if (rootCause instanceof ClassNotFoundException) {
  370                   response.sendError(HttpServletResponse.SC_NOT_FOUND,
  371                                      inRequestURI);
  372                   return;
  373               } else if (rootCause instanceof IOException) {
  374                   throw (IOException) rootCause;
  375               } else if (rootCause instanceof RuntimeException) {
  376                   throw (RuntimeException) rootCause;
  377               } else if (rootCause instanceof ServletException) {
  378                   throw (ServletException) rootCause;
  379               } else {
  380                   throw new ServletException
  381                       (sm.getString("invokerServlet.allocate", inRequestURI),
  382                        rootCause);
  383               }
  384           }
  385   
  386           // After loading the wrapper, restore some of the fields when including
  387           if (included) {
  388               wrequest.setRequestURI(request.getRequestURI());
  389               wrequest.setPathInfo(request.getPathInfo());
  390               wrequest.setServletPath(request.getServletPath());
  391           }
  392   
  393           // Invoke the service() method of the allocated servlet
  394           try {
  395               String jspFile = wrapper.getJspFile();
  396               if (jspFile != null)
  397                   request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
  398               else
  399                   request.removeAttribute(Globals.JSP_FILE_ATTR);
  400               request.setAttribute(Globals.INVOKED_ATTR,
  401                                    request.getServletPath());
  402               instance.service(wrequest, response);
  403           } catch (UnavailableException e) {
  404               context.removeServletMapping(pattern);
  405               throw e;
  406           } finally {
  407               request.removeAttribute(Globals.INVOKED_ATTR);
  408               request.removeAttribute(Globals.JSP_FILE_ATTR);
  409               // Deallocate the allocated servlet instance
  410               try {
  411                   wrapper.deallocate(instance);
  412               } catch (ServletException e) {
  413                   log(sm.getString("invokerServlet.deallocate", inRequestURI), e);
  414                   throw e;
  415               }
  416           }
  417   
  418       }
  419   
  420   
  421   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » servlets » [javadoc | source]