Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/jasper/servlet/JspServlet.java


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