JspServletpublic class JspServlet extends HttpServlet This is an iPlanet adaptation of the Apache Jasper JSPServlet.
This servlet has several performance enhancements over the Apache
JspServlet. These include:
- Reducing the overall number of file stats per request
- Checking for JSP modifications based on a reload interval
- Caching compilation exceptions and recompiling the JSP only when
it is modified |
Fields Summary |
---|
protected ServletContext | context | protected Map | jsps | protected ServletConfig | config | protected org.apache.jasper.Options | options | protected URLClassLoader | parentClassLoader | private PermissionCollection | permissionCollection | private CodeSource | codeSource | private long | reloadInterval | private boolean | checkJSPmods | private boolean | debugLogEnabled | String | outputDir | URL[] | loaderURLs | static boolean | firstTime |
Methods Summary |
---|
public void | destroy()
if (Constants.jasperLog != null)
Constants.jasperLog.log("JspServlet.destroy()", Logger.INFORMATION);
// ensure that only one thread destroys the jsps
synchronized (this) {
Iterator iter = jsps.values().iterator();
while (iter.hasNext())
((JspServletWrapper)iter.next()).destroy();
jsps.clear();
}
| private synchronized com.sun.enterprise.web.jsp.JspServlet$JspServletWrapper | getWrapper(java.lang.String jspUri)The following methods allow synchronized access to the jsps
map as well and perform refcounting on the wrappers as well.
These methods are called only when we check for JSP modifications
JspServletWrapper wrapper = (JspServletWrapper) jsps.get(jspUri);
if (wrapper != null)
wrapper.incrementRefCount();
return wrapper;
| public void | init(javax.servlet.ServletConfig config)
super.init(config);
this.config = config;
this.context = config.getServletContext();
Constants.jasperLog = new DefaultLogger(this.context);
Constants.jasperLog.setName("JASPER_LOG");
Constants.jasperLog.setTimestamp("false");
Constants.jasperLog.setVerbosityLevel(
config.getInitParameter("logVerbosityLevel"));
debugLogEnabled = Constants.jasperLog.matchVerbosityLevel(Logger.DEBUG);
// reload-interval (specified in seconds) is the interval at which
// JSP files are checked for modifications. Values that have 'special'
// significance are:
// 0 : Check JSPs for modifications on every request
// -1 : do not check for JSP modifications and disable recompilation
String interval = config.getInitParameter("reload-interval");
if (interval != null) {
try {
this.reloadInterval = Integer.parseInt(interval) * 1000;
if (this.reloadInterval < 0) {
checkJSPmods = false;
Constants.message("jsp.message.recompile.disabled",
Logger.INFORMATION );
} else if (this.reloadInterval > 0) {
Constants.message("jsp.message.reload.interval",
new Object[] {interval}, Logger.INFORMATION );
}
} catch (NumberFormatException nfe) {
Constants.message("jsp.warning.interval.invalid",
new Object[] {interval}, Logger.WARNING );
}
}
// In case of checking JSP for mods, use a HashMap instead of a
// Hashtable since we anyway synchronize on all accesses to the jsp
// wrappers for the sake of ref counting, so this avoids double
// synchronization
if (checkJSPmods)
jsps = new HashMap();
else
jsps = new Hashtable();
options = new EmbededServletOptions(config, context);
outputDir = options.getScratchDir().toString();
// set the loader urls to the output dir since that is where the
// java classes corresponding to the jsps can be found
File f = new File(outputDir);
// If the toplevel output directory does not exist, then
// create it at this point before adding it to the classloader path
// If the directory does not exist when adding to the classloader,
// the classloader has problems loading the classes later
if (f.exists() == false) {
f.mkdirs();
}
loaderURLs = new URL[1];
try {
loaderURLs[0] = f.toURL();
} catch(MalformedURLException mfe) {
throw new ServletException(mfe);
}
// Get the parent class loader. The servlet container is responsible
// for providing a URLClassLoader for the web application context
// the JspServlet is being used in.
parentClassLoader =
(URLClassLoader) Thread.currentThread().getContextClassLoader();
if (parentClassLoader == null)
parentClassLoader = (URLClassLoader)this.getClass().getClassLoader();
String loaderString = "<none>";
if (parentClassLoader != null)
loaderString = parentClassLoader.toString();
if (debugLogEnabled)
Constants.message("jsp.message.parent_class_loader_is",
new Object[] {loaderString}, Logger.DEBUG);
// Setup the PermissionCollection for this web app context
// based on the permissions configured for the root of the
// web app context directory, then add a file read permission
// for that directory.
Policy policy = Policy.getPolicy();
if( policy != null ) {
try {
// Get the permissions for the web app context
String contextDir = context.getRealPath("/");
if( contextDir == null )
contextDir = outputDir;
URL url = new URL("file:" + contextDir);
codeSource = new CodeSource(url,null);
permissionCollection = policy.getPermissions(codeSource);
// Create a file read permission for web app context directory
if (contextDir.endsWith(File.separator))
contextDir = contextDir + "-";
else
contextDir = contextDir + File.separator + "-";
permissionCollection.add( new FilePermission(contextDir,"read") );
// Allow the JSP to access org.apache.jasper.runtime.HttpJspBase
permissionCollection.add( new RuntimePermission(
"accessClassInPackage.org.apache.jasper.runtime") );
if (parentClassLoader instanceof URLClassLoader) {
URL [] urls = parentClassLoader.getURLs();
String jarUrl = null;
String jndiUrl = null;
for (int i=0; i<urls.length; i++) {
if (jndiUrl == null && urls[i].toString().startsWith("jndi:") ) {
jndiUrl = urls[i].toString() + "-";
}
if (jarUrl == null && urls[i].toString().startsWith("jar:jndi:") ) {
jarUrl = urls[i].toString();
jarUrl = jarUrl.substring(0,jarUrl.length() - 2);
jarUrl = jarUrl.substring(0,jarUrl.lastIndexOf('/")) + "/-";
}
}
if (jarUrl != null) {
permissionCollection.add( new FilePermission(jarUrl,"read") );
permissionCollection.add( new FilePermission(jarUrl.substring(4),"read") );
}
if (jndiUrl != null)
permissionCollection.add( new FilePermission(jndiUrl,"read") );
}
} catch(MalformedURLException mfe) {}
}
if (firstTime) {
firstTime = false;
if( System.getSecurityManager() != null ) {
// Make sure classes needed at runtime by a JSP servlet
// are already loaded by the class loader so that we
// don't get a defineClassInPackage security exception.
String apacheBase = "org.apache.jasper.";
String iplanetBase = "com.sun.enterprise.web.jsp.";
try {
parentClassLoader.loadClass( apacheBase +
"runtime.JspFactoryImpl$PrivilegedGetPageContext");
parentClassLoader.loadClass( apacheBase +
"runtime.JspFactoryImpl$PrivilegedReleasePageContext");
parentClassLoader.loadClass( apacheBase +
"runtime.JspRuntimeLibrary");
parentClassLoader.loadClass( apacheBase +
"runtime.JspRuntimeLibrary$PrivilegedIntrospectHelper");
parentClassLoader.loadClass( apacheBase +
"runtime.ServletResponseWrapperInclude");
this.getClass().getClassLoader().loadClass( iplanetBase +
"JspServlet$JspServletWrapper");
} catch (ClassNotFoundException ex) {
Constants.jasperLog.log(
Constants.getString("jsp.message.preload.failure"),
ex, Logger.WARNING);
}
}
Constants.message("jsp.message.scratch.dir.is",
new Object[] {outputDir}, Logger.INFORMATION );
Constants.message("jsp.message.dont.modify.servlets", Logger.INFORMATION);
JspFactory.setDefaultFactory(new JspFactoryImpl());
}
| boolean | preCompile(javax.servlet.http.HttpServletRequest request)Look for a precompilation request as described in
Section 8.4.2 of the JSP 1.2 Specification. WARNING
we cannot use request.getParameter() for this, because
that will trigger parsing all of the request parameters, and not give
a servlet the opportunity to call
request.setCharacterEncoding() first.
String queryString = request.getQueryString();
if (queryString == null)
return (false);
int start = queryString.indexOf(Constants.PRECOMPILE);
if (start < 0)
return (false);
queryString =
queryString.substring(start + Constants.PRECOMPILE.length());
if (queryString.length() == 0)
return (true); // ?jsp_precompile
if (queryString.startsWith("&"))
return (true); // ?jsp_precompile&foo=bar...
if (!queryString.startsWith("="))
return (false); // part of some other name or value
int limit = queryString.length();
int ampersand = queryString.indexOf("&");
if (ampersand > 0)
limit = ampersand;
String value = queryString.substring(1, limit);
if (value.equals("true"))
return (true); // ?jsp_precompile=true
else if (value.equals("false"))
return (true); // ?jsp_precompile=false
else
throw new ServletException("Cannot have request parameter " +
Constants.PRECOMPILE + " set to " +
value);
| private synchronized void | putWrapper(java.lang.String jspUri, com.sun.enterprise.web.jsp.JspServlet$JspServletWrapper wrapper)
wrapper.incrementRefCount();
JspServletWrapper replaced =
(JspServletWrapper)jsps.put(jspUri, wrapper);
// flag the wrapper that was replaced for destruction
if (replaced != null)
replaced.tryDestroy();
| private synchronized void | releaseWrapper(com.sun.enterprise.web.jsp.JspServlet$JspServletWrapper wrapper)
if (wrapper != null)
wrapper.decrementRefCount();
| private synchronized void | removeWrapper(java.lang.String jspUri)
JspServletWrapper removed = (JspServletWrapper)jsps.remove(jspUri);
// flag the wrapper that was removed for destruction
if (removed != null)
removed.tryDestroy();
| public void | service(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
try {
String jspUri;
String includeUri
= (String) request.getAttribute(Constants.INC_SERVLET_PATH);
if (includeUri == null)
jspUri = request.getServletPath();
else
jspUri = includeUri;
String jspFile = (String) request.getAttribute(Constants.JSP_FILE);
if (jspFile != null)
jspUri = jspFile;
if (debugLogEnabled) {
Logger jasperLog = Constants.jasperLog;
jasperLog.log("JspEngine --> "+jspUri);
jasperLog.log(" ServletPath: "+request.getServletPath());
jasperLog.log(" PathInfo: "+request.getPathInfo());
jasperLog.log(" RealPath: "+context.getRealPath(jspUri));
jasperLog.log(" RequestURI: "+request.getRequestURI());
jasperLog.log(" QueryString: "+request.getQueryString());
}
serviceJspFile(request, response, jspUri);
} catch (RuntimeException e) {
throw e;
} catch (ServletException e) {
throw e;
} catch (IOException e) {
throw e;
} catch (Throwable e) {
throw new ServletException(e);
}
| private void | serviceJspFile(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, java.lang.String jspUri)This is the main service function which creates the wrapper, loads
the JSP if not loaded, checks for JSP modifications if specified,
recompiles the JSP if needed and finally calls the service function
on the wrapper.
JspServletWrapper wrapper = null;
try {
if (checkJSPmods) {
// this increments the refcount
wrapper = getWrapper(jspUri);
if (wrapper == null) {
// ensure that only one thread creates the wrapper
synchronized (this) {
wrapper = getWrapper(jspUri);
if (wrapper == null) {
// create a new wrapper and load the jsp inside it
wrapper = new JspServletWrapper(jspUri);
wrapper.loadJSP(request, response);
// add the new wrapper to the map, this increments
// the refcount as well
putWrapper(jspUri, wrapper);
}
}
} else if (wrapper.isJspFileModified()) {
// create a new wrapper and load the jsp inside it
JspServletWrapper newWrapper =
new JspServletWrapper(jspUri);
newWrapper.loadJSP(request, response);
// add the new wrapper to the map, this increments the
// refcount as well
putWrapper(jspUri, newWrapper);
// decrement the refcount on the old wrapper
releaseWrapper(wrapper);
wrapper = newWrapper;
}
} else {
wrapper = (JspServletWrapper) jsps.get(jspUri);
if (wrapper == null) {
// ensure that only one thread creates the wrapper
synchronized (this) {
wrapper = (JspServletWrapper) jsps.get(jspUri);
if (wrapper == null) {
// create a new wrapper and load the jsp inside it
wrapper = new JspServletWrapper(jspUri);
wrapper.loadJSP(request, response);
// add the new wrapper to the map
jsps.put(jspUri, wrapper);
}
}
}
}
// throw any compile exception generated during compilation
JasperException compileException = wrapper.getCompileException();
if (compileException != null)
throw compileException;
// service the request if it is not a precompile request
if (!preCompile(request))
wrapper.service(request, response);
} catch (FileNotFoundException ex) {
// remove the wrapper from the map. In the case where we are not
// checking for JSP mods, the wrapper would never have been in
// the map since the exception would be thrown in loadJSP
if (checkJSPmods)
removeWrapper(jspUri);
String includeRequestUri = (String)
request.getAttribute("javax.servlet.include.request_uri");
if (includeRequestUri != null) {
// This file was included. Throw an exception as
// a response.sendError() will be ignored by the
// servlet engine.
throw new ServletException(ex);
} else {
try {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
ex.getMessage());
} catch (IllegalStateException ise) {
Constants.jasperLog.log(Constants.getString
("jsp.error.file.not.found",
new Object[] {ex.getMessage()}),
ex, Logger.ERROR);
}
}
} finally {
// decrement the refcount even in case of an exception
if (checkJSPmods)
releaseWrapper(wrapper);
}
|
|