Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » jasper » servlet » [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   package org.apache.jasper.servlet;
   19   
   20   import java.io.IOException;
   21   import java.lang.reflect.Constructor;
   22   import java.util.Enumeration;
   23   
   24   import javax.servlet.ServletConfig;
   25   import javax.servlet.ServletContext;
   26   import javax.servlet.ServletException;
   27   import javax.servlet.http.HttpServlet;
   28   import javax.servlet.http.HttpServletRequest;
   29   import javax.servlet.http.HttpServletResponse;
   30   
   31   import org.apache.PeriodicEventListener;
   32   
   33   import org.apache.jasper.Constants;
   34   import org.apache.jasper.EmbeddedServletOptions;
   35   import org.apache.jasper.Options;
   36   import org.apache.jasper.compiler.JspRuntimeContext;
   37   import org.apache.jasper.compiler.Localizer;
   38   import org.apache.juli.logging.Log;
   39   import org.apache.juli.logging.LogFactory;
   40   
   41   /**
   42    * The JSP engine (a.k.a Jasper).
   43    *
   44    * The servlet container is responsible for providing a
   45    * URLClassLoader for the web application context Jasper
   46    * is being used in. Jasper will try get the Tomcat
   47    * ServletContext attribute for its ServletContext class
   48    * loader, if that fails, it uses the parent class loader.
   49    * In either case, it must be a URLClassLoader.
   50    *
   51    * @author Anil K. Vijendran
   52    * @author Harish Prabandham
   53    * @author Remy Maucherat
   54    * @author Kin-man Chung
   55    * @author Glenn Nielsen
   56    */
   57   public class JspServlet extends HttpServlet implements PeriodicEventListener {
   58   
   59       // Logger
   60       private Log log = LogFactory.getLog(JspServlet.class);
   61   
   62       private ServletContext context;
   63       private ServletConfig config;
   64       private Options options;
   65       private JspRuntimeContext rctxt;
   66   
   67   
   68       /*
   69        * Initializes this JspServlet.
   70        */
   71       public void init(ServletConfig config) throws ServletException {
   72           
   73           super.init(config);
   74           this.config = config;
   75           this.context = config.getServletContext();
   76           
   77           // Initialize the JSP Runtime Context
   78           // Check for a custom Options implementation
   79           String engineOptionsName = 
   80               config.getInitParameter("engineOptionsClass");
   81           if (engineOptionsName != null) {
   82               // Instantiate the indicated Options implementation
   83               try {
   84                   ClassLoader loader = Thread.currentThread()
   85                           .getContextClassLoader();
   86                   Class engineOptionsClass = loader.loadClass(engineOptionsName);
   87                   Class[] ctorSig = { ServletConfig.class, ServletContext.class };
   88                   Constructor ctor = engineOptionsClass.getConstructor(ctorSig);
   89                   Object[] args = { config, context };
   90                   options = (Options) ctor.newInstance(args);
   91               } catch (Throwable e) {
   92                   // Need to localize this.
   93                   log.warn("Failed to load engineOptionsClass", e);
   94                   // Use the default Options implementation
   95                   options = new EmbeddedServletOptions(config, context);
   96               }
   97           } else {
   98               // Use the default Options implementation
   99               options = new EmbeddedServletOptions(config, context);
  100           }
  101           rctxt = new JspRuntimeContext(context, options);
  102           
  103           if (log.isDebugEnabled()) {
  104               log.debug(Localizer.getMessage("jsp.message.scratch.dir.is",
  105                       options.getScratchDir().toString()));
  106               log.debug(Localizer.getMessage("jsp.message.dont.modify.servlets"));
  107           }
  108       }
  109   
  110   
  111       /**
  112        * Returns the number of JSPs for which JspServletWrappers exist, i.e.,
  113        * the number of JSPs that have been loaded into the webapp with which
  114        * this JspServlet is associated.
  115        *
  116        * <p>This info may be used for monitoring purposes.
  117        *
  118        * @return The number of JSPs that have been loaded into the webapp with
  119        * which this JspServlet is associated
  120        */
  121       public int getJspCount() {
  122           return this.rctxt.getJspCount();
  123       }
  124   
  125   
  126       /**
  127        * Resets the JSP reload counter.
  128        *
  129        * @param count Value to which to reset the JSP reload counter
  130        */
  131       public void setJspReloadCount(int count) {
  132           this.rctxt.setJspReloadCount(count);
  133       }
  134   
  135   
  136       /**
  137        * Gets the number of JSPs that have been reloaded.
  138        *
  139        * <p>This info may be used for monitoring purposes.
  140        *
  141        * @return The number of JSPs (in the webapp with which this JspServlet is
  142        * associated) that have been reloaded
  143        */
  144       public int getJspReloadCount() {
  145           return this.rctxt.getJspReloadCount();
  146       }
  147   
  148   
  149       /**
  150        * <p>Look for a <em>precompilation request</em> as described in
  151        * Section 8.4.2 of the JSP 1.2 Specification.  <strong>WARNING</strong> -
  152        * we cannot use <code>request.getParameter()</code> for this, because
  153        * that will trigger parsing all of the request parameters, and not give
  154        * a servlet the opportunity to call
  155        * <code>request.setCharacterEncoding()</code> first.</p>
  156        *
  157        * @param request The servlet requset we are processing
  158        *
  159        * @exception ServletException if an invalid parameter value for the
  160        *  <code>jsp_precompile</code> parameter name is specified
  161        */
  162       boolean preCompile(HttpServletRequest request) throws ServletException {
  163   
  164           String queryString = request.getQueryString();
  165           if (queryString == null) {
  166               return (false);
  167           }
  168           int start = queryString.indexOf(Constants.PRECOMPILE);
  169           if (start < 0) {
  170               return (false);
  171           }
  172           queryString =
  173               queryString.substring(start + Constants.PRECOMPILE.length());
  174           if (queryString.length() == 0) {
  175               return (true);             // ?jsp_precompile
  176           }
  177           if (queryString.startsWith("&")) {
  178               return (true);             // ?jsp_precompile&foo=bar...
  179           }
  180           if (!queryString.startsWith("=")) {
  181               return (false);            // part of some other name or value
  182           }
  183           int limit = queryString.length();
  184           int ampersand = queryString.indexOf("&");
  185           if (ampersand > 0) {
  186               limit = ampersand;
  187           }
  188           String value = queryString.substring(1, limit);
  189           if (value.equals("true")) {
  190               return (true);             // ?jsp_precompile=true
  191           } else if (value.equals("false")) {
  192   	    // Spec says if jsp_precompile=false, the request should not
  193   	    // be delivered to the JSP page; the easiest way to implement
  194   	    // this is to set the flag to true, and precompile the page anyway.
  195   	    // This still conforms to the spec, since it says the
  196   	    // precompilation request can be ignored.
  197               return (true);             // ?jsp_precompile=false
  198           } else {
  199               throw new ServletException("Cannot have request parameter " +
  200                                          Constants.PRECOMPILE + " set to " +
  201                                          value);
  202           }
  203   
  204       }
  205       
  206   
  207       public void service (HttpServletRequest request, 
  208       			 HttpServletResponse response)
  209                   throws ServletException, IOException {
  210   
  211           String jspUri = null;
  212   
  213           String jspFile = (String) request.getAttribute(Constants.JSP_FILE);
  214           if (jspFile != null) {
  215               // JSP is specified via <jsp-file> in <servlet> declaration
  216               jspUri = jspFile;
  217           } else {
  218               /*
  219                * Check to see if the requested JSP has been the target of a
  220                * RequestDispatcher.include()
  221                */
  222               jspUri = (String) request.getAttribute(Constants.INC_SERVLET_PATH);
  223               if (jspUri != null) {
  224                   /*
  225   		 * Requested JSP has been target of
  226                    * RequestDispatcher.include(). Its path is assembled from the
  227                    * relevant javax.servlet.include.* request attributes
  228                    */
  229                   String pathInfo = (String) request.getAttribute(
  230                                       "javax.servlet.include.path_info");
  231                   if (pathInfo != null) {
  232                       jspUri += pathInfo;
  233                   }
  234               } else {
  235                   /*
  236                    * Requested JSP has not been the target of a 
  237                    * RequestDispatcher.include(). Reconstruct its path from the
  238                    * request's getServletPath() and getPathInfo()
  239                    */
  240                   jspUri = request.getServletPath();
  241                   String pathInfo = request.getPathInfo();
  242                   if (pathInfo != null) {
  243                       jspUri += pathInfo;
  244                   }
  245               }
  246           }
  247   
  248           if (log.isDebugEnabled()) {	    
  249               log.debug("JspEngine --> " + jspUri);
  250               log.debug("\t     ServletPath: " + request.getServletPath());
  251               log.debug("\t        PathInfo: " + request.getPathInfo());
  252               log.debug("\t        RealPath: " + context.getRealPath(jspUri));
  253               log.debug("\t      RequestURI: " + request.getRequestURI());
  254               log.debug("\t     QueryString: " + request.getQueryString());
  255               log.debug("\t  Request Params: ");
  256               Enumeration e = request.getParameterNames();
  257               while (e.hasMoreElements()) {
  258                   String name = (String) e.nextElement();
  259                   log.debug("\t\t " + name + " = " 
  260                             + request.getParameter(name));
  261               }
  262           }
  263   
  264           try {
  265               boolean precompile = preCompile(request);
  266               serviceJspFile(request, response, jspUri, null, precompile);
  267           } catch (RuntimeException e) {
  268               throw e;
  269           } catch (ServletException e) {
  270               throw e;
  271           } catch (IOException e) {
  272               throw e;
  273           } catch (Throwable e) {
  274               throw new ServletException(e);
  275           }
  276   
  277       }
  278   
  279       public void destroy() {
  280           if (log.isDebugEnabled()) {
  281               log.debug("JspServlet.destroy()");
  282           }
  283   
  284           rctxt.destroy();
  285       }
  286   
  287   
  288       public void periodicEvent() {
  289           rctxt.checkCompile();
  290       }
  291   
  292       // -------------------------------------------------------- Private Methods
  293   
  294       private void serviceJspFile(HttpServletRequest request,
  295                                   HttpServletResponse response, String jspUri,
  296                                   Throwable exception, boolean precompile)
  297           throws ServletException, IOException {
  298   
  299           JspServletWrapper wrapper =
  300               (JspServletWrapper) rctxt.getWrapper(jspUri);
  301           if (wrapper == null) {
  302               synchronized(this) {
  303                   wrapper = (JspServletWrapper) rctxt.getWrapper(jspUri);
  304                   if (wrapper == null) {
  305                       // Check if the requested JSP page exists, to avoid
  306                       // creating unnecessary directories and files.
  307                       if (null == context.getResource(jspUri)) {
  308                           String includeRequestUri = (String)
  309                           request.getAttribute(
  310                                   "javax.servlet.include.request_uri");
  311                           if (includeRequestUri != null) {
  312                               // This file was included. Throw an exception as
  313                               // a response.sendError() will be ignored
  314                               throw new ServletException(Localizer.getMessage(
  315                                       "jsp.error.file.not.found",jspUri));
  316                           } else {
  317                               try {
  318                                   response.sendError(
  319                                           HttpServletResponse.SC_NOT_FOUND,
  320                                           request.getRequestURI());
  321                               } catch (IllegalStateException ise) {
  322                                   log.error(Localizer.getMessage(
  323                                           "jsp.error.file.not.found",
  324                                           jspUri));
  325                               }
  326                           }
  327                           return;
  328                       }
  329                       boolean isErrorPage = exception != null;
  330                       wrapper = new JspServletWrapper(config, options, jspUri,
  331                                                       isErrorPage, rctxt);
  332                       rctxt.addWrapper(jspUri,wrapper);
  333                   }
  334               }
  335           }
  336   
  337           wrapper.service(request, response, precompile);
  338   
  339       }
  340   
  341   
  342   }

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