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

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