You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2012/05/11 01:51:27 UTC
svn commit: r1336969 - in
/sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp:
./ jasper/ jasper/compiler/ jasper/servlet/
Author: cziegeler
Date: Thu May 10 23:51:27 2012
New Revision: 1336969
URL: http://svn.apache.org/viewvc?rev=1336969&view=rev
Log:
SLING-2471 : Free classloaders as soon as possible
Removed:
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/JspServletWrapperAdapter.java
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/servlet/JasperLoader.java
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/servlet/JspCServletContext.java
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/servlet/JspServlet.java
Modified:
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/JspScriptEngineFactory.java
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/IsolatedClassLoader.java
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/JspCompilationContext.java
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/Compiler.java
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/JspRuntimeContext.java
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/Node.java
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/TagLibraryInfoImpl.java
sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/servlet/JspServletWrapper.java
Modified: sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/JspScriptEngineFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/JspScriptEngineFactory.java?rev=1336969&r1=1336968&r2=1336969&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/JspScriptEngineFactory.java (original)
+++ sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/JspScriptEngineFactory.java Thu May 10 23:51:27 2012
@@ -49,11 +49,11 @@ import org.apache.sling.commons.classloa
import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
import org.apache.sling.scripting.api.AbstractScriptEngineFactory;
import org.apache.sling.scripting.api.AbstractSlingScriptEngine;
-import org.apache.sling.scripting.jsp.jasper.JasperException;
import org.apache.sling.scripting.jsp.jasper.Options;
import org.apache.sling.scripting.jsp.jasper.compiler.JspRuntimeContext;
import org.apache.sling.scripting.jsp.jasper.runtime.AnnotationProcessor;
import org.apache.sling.scripting.jsp.jasper.runtime.JspApplicationContextImpl;
+import org.apache.sling.scripting.jsp.jasper.servlet.JspServletWrapper;
import org.apache.sling.scripting.jsp.util.TagUtil;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
@@ -181,7 +181,7 @@ public class JspScriptEngineFactory
io.setRequestResourceResolver(resolver);
jspFactoryHandler.incUsage();
try {
- final JspServletWrapperAdapter errorJsp = getJspWrapperAdapter(scriptName);
+ final JspServletWrapper errorJsp = getJspWrapper(scriptName, slingBindings);
errorJsp.service(slingBindings);
// The error page could be inside an include.
@@ -225,10 +225,11 @@ public class JspScriptEngineFactory
io.setRequestResourceResolver(resolver);
jspFactoryHandler.incUsage();
try {
- final JspServletWrapperAdapter jsp = getJspWrapperAdapter(scriptHelper);
- // create a SlingBindings object
final SlingBindings slingBindings = new SlingBindings();
slingBindings.putAll(bindings);
+
+ final JspServletWrapper jsp = getJspWrapper(scriptHelper, slingBindings);
+ // create a SlingBindings object
jsp.service(slingBindings);
} finally {
jspFactoryHandler.decUsage();
@@ -236,42 +237,40 @@ public class JspScriptEngineFactory
}
}
- private JspServletWrapperAdapter getJspWrapperAdapter(final String scriptName)
+ private JspServletWrapper getJspWrapper(final String scriptName, final SlingBindings bindings)
throws SlingException {
- final JspRuntimeContext rctxt = jspRuntimeContext;
+ JspRuntimeContext rctxt = this.getJspRuntimeContext();
- JspServletWrapperAdapter wrapper = (JspServletWrapperAdapter) rctxt.getWrapper(scriptName);
+ JspServletWrapper wrapper = rctxt.getWrapper(scriptName);
if (wrapper != null) {
- return wrapper;
+ if ( wrapper.isValid() ) {
+ return wrapper;
+ }
+ rctxt.removeWrapper(wrapper.getJspUri());
+ this.renewJspRuntimeContext();
+ rctxt = this.getJspRuntimeContext();
+ wrapper = null;
}
synchronized (rctxt) {
- wrapper = (JspServletWrapperAdapter) rctxt.getWrapper(scriptName);
+ wrapper = rctxt.getWrapper(scriptName);
if (wrapper != null) {
return wrapper;
}
- try {
-
- wrapper = new JspServletWrapperAdapter(servletConfig, options,
- scriptName, false, rctxt);
- rctxt.addWrapper(scriptName, wrapper);
+ wrapper = new JspServletWrapper(servletConfig, options,
+ scriptName, false, rctxt);
+ rctxt.addWrapper(scriptName, wrapper);
- return wrapper;
- } catch (JasperException je) {
- if (je.getCause() != null) {
- throw new SlingException(je.getMessage(), je.getCause());
- }
- throw new SlingException("Cannot create JSP: " + scriptName, je);
- }
+ return wrapper;
}
}
- private JspServletWrapperAdapter getJspWrapperAdapter(final SlingScriptHelper scriptHelper)
+ private JspServletWrapper getJspWrapper(final SlingScriptHelper scriptHelper, final SlingBindings bindings)
throws SlingException {
final SlingScript script = scriptHelper.getScript();
final String scriptName = script.getScriptResource().getPath();
- return getJspWrapperAdapter(scriptName);
+ return getJspWrapper(scriptName, bindings);
}
// ---------- SCR integration ----------------------------------------------
@@ -297,10 +296,6 @@ public class JspScriptEngineFactory
options = new JspServletOptions(slingServletContext, ioProvider,
componentContext, tldLocationsCache);
- // Initialize the JSP Runtime Context
- this.jspRuntimeContext = new JspRuntimeContext(slingServletContext,
- options, ioProvider);
-
jspServletContext = new JspServletContext(ioProvider,
slingServletContext, tldLocationsCache);
@@ -340,13 +335,7 @@ public class JspScriptEngineFactory
this.eventHandlerRegistration = null;
}
if (jspRuntimeContext != null) {
- try {
- jspRuntimeContext.destroy();
- } catch (NullPointerException npe) {
- // SLING-530, might be thrown on system shutdown in a servlet
- // container when using the Equinox servlet container bridge
- logger.debug("deactivate: ServletContext might already be unavailable", npe);
- }
+ this.destroyJspRuntimeContext(this.jspRuntimeContext);
jspRuntimeContext = null;
}
@@ -484,6 +473,31 @@ public class JspScriptEngineFactory
}
}
+ private void destroyJspRuntimeContext(final JspRuntimeContext jrc) {
+ if (jrc != null) {
+ try {
+ jrc.destroy();
+ } catch (NullPointerException npe) {
+ // SLING-530, might be thrown on system shutdown in a servlet
+ // container when using the Equinox servlet container bridge
+ logger.debug("deactivate: ServletContext might already be unavailable", npe);
+ }
+ }
+ }
+
+ private JspRuntimeContext getJspRuntimeContext() {
+ if ( this.jspRuntimeContext == null ) {
+ synchronized ( this ) {
+ if ( this.jspRuntimeContext == null ) {
+ // Initialize the JSP Runtime Context
+ this.jspRuntimeContext = new JspRuntimeContext(slingServletContext,
+ options, ioProvider);
+ }
+ }
+ }
+ return this.jspRuntimeContext;
+ }
+
/**
* Fixes {@link ScriptException} that overwrites the
* {@link ScriptException#getMessage()} method to display its own
@@ -500,7 +514,7 @@ public class JspScriptEngineFactory
private static final long serialVersionUID = -6490165487977283019L;
- public BetterScriptException(String message, Exception cause) {
+ public BetterScriptException(final String message, final Exception cause) {
super(message);
this.initCause(cause);
}
@@ -510,10 +524,27 @@ public class JspScriptEngineFactory
/**
* @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
*/
- public void handleEvent(Event event) {
+ public void handleEvent(final Event event) {
final String path = (String)event.getProperty(SlingConstants.PROPERTY_PATH);
if ( path != null ) {
- this.jspRuntimeContext.handleModification(path);
+ final JspRuntimeContext rctxt = this.jspRuntimeContext;
+ if ( rctxt != null && rctxt.handleModification(path) ) {
+ renewJspRuntimeContext();
+ }
}
}
+
+ private void renewJspRuntimeContext() {
+ final JspRuntimeContext jrc;
+ synchronized ( this ) {
+ jrc = this.jspRuntimeContext;
+ this.jspRuntimeContext = null;
+ }
+ final Thread t = new Thread() {
+ public void run() {
+ destroyJspRuntimeContext(jrc);
+ }
+ };
+ t.start();
+ }
}
Modified: sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/IsolatedClassLoader.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/IsolatedClassLoader.java?rev=1336969&r1=1336968&r2=1336969&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/IsolatedClassLoader.java (original)
+++ sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/IsolatedClassLoader.java Thu May 10 23:51:27 2012
@@ -33,13 +33,11 @@ public final class IsolatedClassLoader
private final IOProvider ioProvider;
- public IsolatedClassLoader(final ClassLoader parent,
- final IOProvider ioProvider) {
- super(parent);
+ public IsolatedClassLoader(final IOProvider ioProvider) {
+ super(ioProvider.getClassLoader());
this.ioProvider = ioProvider;
}
-
//---------- Class loader overwrites -------------------------------------
/**
Modified: sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/JspCompilationContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/JspCompilationContext.java?rev=1336969&r1=1336968&r2=1336969&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/JspCompilationContext.java (original)
+++ sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/JspCompilationContext.java Thu May 10 23:51:27 2012
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.sling.scripting.jsp.jasper;
import java.io.File;
@@ -32,6 +31,7 @@ import javax.servlet.ServletContext;
import javax.servlet.jsp.tagext.TagInfo;
import org.apache.sling.scripting.jsp.jasper.compiler.Compiler;
+import org.apache.sling.scripting.jsp.jasper.compiler.JDTCompiler;
import org.apache.sling.scripting.jsp.jasper.compiler.JspRuntimeContext;
import org.apache.sling.scripting.jsp.jasper.compiler.JspUtil;
import org.apache.sling.scripting.jsp.jasper.compiler.Localizer;
@@ -54,42 +54,32 @@ import org.apache.sling.scripting.jsp.ja
*/
public class JspCompilationContext {
- protected org.apache.juli.logging.Log log =
- org.apache.juli.logging.LogFactory.getLog(JspCompilationContext.class);
-
- protected Map<String, URL> tagFileJarUrls;
- protected boolean isPackagedTagFile;
+ private Map<String, URL> tagFileJarUrls;
- protected String className;
- protected String jspUri;
- protected boolean isErrPage;
- protected String basePackageName;
- protected String derivedPackageName;
- protected String servletJavaFileName;
- protected String javaPath;
- protected String classFileName;
- protected String contentType;
- protected ServletWriter writer;
- protected Options options;
- protected JspServletWrapper jsw;
- protected Compiler jspCompiler;
- protected String classPath;
-
- protected String baseURI;
- protected String outputDir;
- protected ServletContext context;
-
- protected JspRuntimeContext rctxt;
-
- protected int removed = 0;
-
- protected URL baseUrl;
- protected Class<?> servletClass;
-
- protected boolean isTagFile;
- protected boolean protoTypeMode;
- protected TagInfo tagInfo;
- protected URL tagFileJarUrl;
+ private String className;
+ private String jspUri;
+ private boolean isErrPage;
+ private String basePackageName;
+ private String derivedPackageName;
+ private String servletJavaFileName;
+ private String javaPath;
+ private String classFileName;
+ private String contentType;
+ private ServletWriter writer;
+ private Options options;
+ private JspServletWrapper jsw;
+ private Compiler jspCompiler;
+
+ private String baseURI;
+ private String outputDir;
+ private ServletContext context;
+
+ private JspRuntimeContext rctxt;
+
+ private boolean isTagFile;
+ private boolean protoTypeMode;
+ private TagInfo tagInfo;
+ private URL tagFileJarUrl;
// jspURI _must_ be relative to the context
public JspCompilationContext(String jspUri,
@@ -134,9 +124,6 @@ public class JspCompilationContext {
this.isTagFile = true;
this.tagInfo = tagInfo;
this.tagFileJarUrl = tagFileJarUrl;
- if (tagFileJarUrl != null) {
- isPackagedTagFile = true;
- }
}
/**
@@ -195,9 +182,9 @@ public class JspCompilationContext {
* plus the directory derived from the package name.
*/
public String getOutputDir() {
- if (outputDir == null) {
- createOutputDir();
- }
+ if (outputDir == null) {
+ createOutputDir();
+ }
return outputDir;
}
@@ -207,57 +194,23 @@ public class JspCompilationContext {
* is not done yet. Right now we're just hardcoding the actual
* compilers that are created.
*/
- public Compiler createCompiler() throws JasperException {
+ private Compiler createCompiler() {
if (jspCompiler != null ) {
return jspCompiler;
}
- jspCompiler = null;
- if (options.getCompilerClassName() != null) {
- jspCompiler = createCompiler(options.getCompilerClassName());
- } else {
- if (options.getCompiler() == null) {
- jspCompiler = createCompiler("org.apache.sling.scripting.jsp.jasper.compiler.JDTCompiler");
- if (jspCompiler == null) {
- jspCompiler = createCompiler("org.apache.sling.scripting.jsp.jasper.compiler.AntCompiler");
- }
- } else {
- jspCompiler = createCompiler("org.apache.sling.scripting.jsp.jasper.compiler.AntCompiler");
- if (jspCompiler == null) {
- jspCompiler = createCompiler("org.apache.sling.scripting.jsp.jasper.compiler.JDTCompiler");
- }
- }
- }
- if (jspCompiler == null) {
- throw new IllegalStateException(Localizer.getMessage("jsp.error.compiler"));
- }
- jspCompiler.init(this, jsw);
+ jspCompiler = new JDTCompiler();
+ jspCompiler.init(this);
return jspCompiler;
}
- protected Compiler createCompiler(String className) {
- Compiler compiler = null;
- try {
- compiler = (Compiler) this.getClass().getClassLoader().loadClass(className).newInstance();
- } catch (InstantiationException e) {
- log.warn(Localizer.getMessage("jsp.error.compiler"), e);
- } catch (IllegalAccessException e) {
- log.warn(Localizer.getMessage("jsp.error.compiler"), e);
- } catch (NoClassDefFoundError e) {
- if (log.isDebugEnabled()) {
- log.debug(Localizer.getMessage("jsp.error.compiler"), e);
- }
- } catch (ClassNotFoundException e) {
- if (log.isDebugEnabled()) {
- log.debug(Localizer.getMessage("jsp.error.compiler"), e);
- }
- }
- return compiler;
- }
-
public Compiler getCompiler() {
return jspCompiler;
}
+ public void reset() {
+ this.jspCompiler = null;
+ }
+
/** ---------- Access resources in the webapp ---------- */
/**
@@ -543,60 +496,37 @@ public class JspCompilationContext {
return getOptions().getKeepGenerated();
}
- // ==================== Removal ====================
-
- public void incrementRemoved() {
- if (removed == 0 && rctxt != null) {
- rctxt.removeWrapper(jspUri);
- }
- removed++;
- }
-
- public boolean isRemoved() {
- if (removed > 1 ) {
- return true;
- }
- return false;
- }
-
// ==================== Compile and reload ====================
- public void compile() throws JasperException, IOException, FileNotFoundException {
- createCompiler();
- if (isPackagedTagFile || jspCompiler.isOutDated()) {
- try {
- jspCompiler.removeGeneratedFiles();
- jspCompiler.compile();
- jsw.setReload(true);
- jsw.setCompilationException(null);
- this.getRuntimeContext().addJspDependencies(jsw);
- } catch (JasperException ex) {
- // Cache compilation exception
- jsw.setCompilationException(ex);
- throw ex;
- } catch (IOException ioe) {
- JasperException je = new JasperException(
+ public JasperException compile() {
+ final Compiler c = createCompiler();
+ try {
+ c.removeGeneratedFiles();
+ c.compile();
+ this.getRuntimeContext().addJspDependencies(jsw);
+ } catch (final JasperException ex) {
+ return ex;
+ } catch (final IOException ioe) {
+ final JasperException je = new JasperException(
+ Localizer.getMessage("jsp.error.unable.compile"),
+ ioe);
+ return je;
+ } catch (final Exception ex) {
+ JasperException je = new JasperException(
Localizer.getMessage("jsp.error.unable.compile"),
- ioe);
- // Cache compilation exception
- jsw.setCompilationException(je);
- throw ioe;
- } catch (Exception ex) {
- JasperException je = new JasperException(
- Localizer.getMessage("jsp.error.unable.compile"),
- ex);
- // Cache compilation exception
- jsw.setCompilationException(je);
- throw je;
- }
+ ex);
+ return je;
+ } finally {
+ c.clean();
}
+
+ return null;
}
// ==================== Manipulating the class ====================
public Class<?> load()
- throws JasperException, FileNotFoundException
- {
+ throws JasperException {
try {
String name;
if (isTagFile()) {
@@ -604,7 +534,8 @@ public class JspCompilationContext {
} else {
name = getServletPackageName() + "." + getServletClassName();
}
- servletClass = getClassLoader().loadClass(name);
+ final Class<?> servletClass = getClassLoader().loadClass(name);
+ return servletClass;
} catch (ClassNotFoundException cex) {
throw new JasperException(Localizer.getMessage("jsp.error.unable.load"),
cex);
@@ -612,57 +543,40 @@ public class JspCompilationContext {
throw new JasperException(Localizer.getMessage("jsp.error.unable.compile"),
ex);
}
- removed = 0;
- return servletClass;
}
// ==================== protected methods ====================
- static Object outputDirLock = new Object();
-
public void checkOutputDir() {
- if (outputDir != null) {
- if (!(new File(outputDir)).exists()) {
- makeOutputDir();
- }
- } else {
- createOutputDir();
- }
+ getOutputDir();
}
- protected boolean makeOutputDir() {
- synchronized(outputDirLock) {
- return getRuntimeContext().getIOProvider().mkdirs(outputDir);
- }
+ private boolean makeOutputDir() {
+ return getRuntimeContext().getIOProvider().mkdirs(outputDir);
}
- protected void createOutputDir() {
+ private void createOutputDir() {
String path = null;
if (isTagFile()) {
- String tagName = tagInfo.getTagClassName();
+ String tagName = tagInfo.getTagClassName();
path = tagName.replace('.', '/');
- path = path.substring(0, path.lastIndexOf('/'));
+ path = path.substring(0, path.lastIndexOf('/'));
} else {
path = getServletPackageName().replace('.', '/');
- }
+ }
- // Append servlet or tag handler path to scratch dir
- try {
- baseUrl = new File(options.getScratchDir()).toURI().toURL();
- outputDir = options.getScratchDir() + File.separator + path + File.separator;
- if (!makeOutputDir()) {
- throw new IllegalStateException(Localizer.getMessage("jsp.error.outputfolder"));
- }
- } catch (MalformedURLException e) {
- throw new IllegalStateException(Localizer.getMessage("jsp.error.outputfolder"), e);
- }
+ // Append servlet or tag handler path to scratch dir
+ outputDir = options.getScratchDir() + File.separator + path + File.separator;
+ if (!makeOutputDir()) {
+ throw new IllegalStateException(Localizer.getMessage("jsp.error.outputfolder"));
+ }
}
- protected static final boolean isPathSeparator(char c) {
+ private static final boolean isPathSeparator(char c) {
return (c == '/' || c == '\\');
}
- protected static final String canonicalURI(String s) {
+ private static final String canonicalURI(String s) {
if (s == null) return null;
StringBuffer result = new StringBuffer();
final int len = s.length();
Modified: sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/Compiler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/Compiler.java?rev=1336969&r1=1336968&r2=1336969&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/Compiler.java (original)
+++ sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/Compiler.java Thu May 10 23:51:27 2012
@@ -22,15 +22,11 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.Iterator;
-import java.util.List;
import org.apache.sling.scripting.jsp.jasper.JasperException;
import org.apache.sling.scripting.jsp.jasper.JspCompilationContext;
import org.apache.sling.scripting.jsp.jasper.Options;
-import org.apache.sling.scripting.jsp.jasper.servlet.JspServletWrapper;
+import org.apache.sling.scripting.jsp.jasper.compiler.Node.CustomTag;
/**
* Main JSP compiler class. This class uses Ant for compiling.
@@ -55,8 +51,6 @@ public abstract class Compiler {
protected PageInfo pageInfo;
- protected JspServletWrapper jsw;
-
protected TagFileProcessor tfp;
protected Options options;
@@ -65,8 +59,7 @@ public abstract class Compiler {
// ------------------------------------------------------------ Constructor
- public void init(JspCompilationContext ctxt, JspServletWrapper jsw) {
- this.jsw = jsw;
+ public void init(final JspCompilationContext ctxt) {
this.ctxt = ctxt;
this.options = ctxt.getOptions();
}
@@ -340,100 +333,6 @@ public abstract class Compiler {
}
/**
- * This is a protected method intended to be overridden by subclasses of
- * Compiler. This is used by the compile method to do all the compilation.
- */
- public boolean isOutDated() {
- return isOutDated(true);
- }
-
- /**
- * Determine if a compilation is necessary by checking the time stamp of the
- * JSP page with that of the corresponding .class or .java file. If the page
- * has dependencies, the check is also extended to its dependeants, and so
- * on. This method can by overidden by a subclasses of Compiler.
- *
- * @param checkClass
- * If true, check against .class file, if false, check against
- * .java file.
- */
- public boolean isOutDated(final boolean checkClass) {
- final long lastModifiedTest = jsw.getLastModificationTest();
- if ( lastModifiedTest > 0 ) {
- return false;
- } else if ( lastModifiedTest < 0 ) {
- return true;
- }
- final String jsp = ctxt.getJspFile();
-
- long jspRealLastModified = ctxt.getRuntimeContext().getIOProvider().lastModified(jsp);
-
- long targetLastModified = 0;
- String targetFile;
-
- if (checkClass) {
- targetFile = ctxt.getClassFileName();
- } else {
- targetFile = ctxt.getServletJavaFileName();
- }
-
- targetLastModified = ctxt.getRuntimeContext().getIOProvider().lastModified(targetFile);
- if (targetLastModified < 0) {
- return true;
- }
-
- if (checkClass && jsw != null) {
- jsw.setServletClassLastModifiedTime(targetLastModified);
- }
- if (targetLastModified < jspRealLastModified) {
- if (log.isDebugEnabled()) {
- log.debug("Compiler: outdated: " + targetFile + " "
- + targetLastModified);
- }
- return true;
- }
-
- // determine if source dependent files (e.g. includes using include
- // directives) have been changed.
- if (jsw == null) {
- return false;
- }
-
- List<String> depends = jsw.getDependants();
- if (depends == null) {
- return false;
- }
-
- final Iterator<String> it = depends.iterator();
- while (it.hasNext()) {
- final String include = it.next();
- // ignore tag libs, we are reloaded if a taglib changes anyway
- if ( include.startsWith("tld:") ) {
- continue;
- }
- try {
- final URL includeUrl = ctxt.getResource(include);
- if (includeUrl == null) {
- return true;
- }
-
- URLConnection includeUconn = includeUrl.openConnection();
- long includeLastModified = includeUconn.getLastModified();
- includeUconn.getInputStream().close();
-
- if (includeLastModified > targetLastModified) {
- return true;
- }
- } catch (Exception e) {
- return true;
- }
- }
-
- return false;
-
- }
-
- /**
* Gets the error dispatcher.
*/
public ErrorDispatcher getErrorDispatcher() {
@@ -492,4 +391,23 @@ public abstract class Compiler {
// Remove as much as possible, ignore possible exceptions
}
}
+
+ public void clean() {
+ if ( this.pageNodes != null ) {
+ try {
+ pageNodes.visit(new CleanVisitor());
+ } catch ( final JasperException ignore) {
+ // ignore
+ }
+ }
+
+ }
+
+ private static final class CleanVisitor extends Node.Visitor {
+
+ public void visit(final CustomTag n) throws JasperException {
+ n.clean();
+ visitBody(n);
+ }
+ }
}
Modified: sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/JspRuntimeContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/JspRuntimeContext.java?rev=1336969&r1=1336968&r2=1336969&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/JspRuntimeContext.java (original)
+++ sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/JspRuntimeContext.java Thu May 10 23:51:27 2012
@@ -66,17 +66,7 @@ import org.apache.sling.scripting.jsp.ja
public final class JspRuntimeContext {
// Logger
- private Log log = LogFactory.getLog(JspRuntimeContext.class);
-
- /**
- * Prefixes, in which repository paths and script paths can differ.
- */
- private static final String[] PATH_PREFIXES = {"", "/WEB-INF/tags"};
-
- /*
- * Counts how many times the webapp's JSPs have been reloaded.
- */
- private int jspReloadCount;
+ private final Log log = LogFactory.getLog(JspRuntimeContext.class);
/** The {@link IOProvider} used to get access to output */
private final IOProvider ioProvider;
@@ -214,28 +204,6 @@ public final class JspRuntimeContext {
this.context = context;
this.options = options;
this.ioProvider = ioProvider;
-/*
- // Get the parent class loader
- parentClassLoader = Thread.currentThread().getContextClassLoader();
- if (parentClassLoader == null) {
- parentClassLoader = this.getClass().getClassLoader();
- }
-
- if (log.isDebugEnabled()) {
- if (parentClassLoader != null) {
- log.debug(Localizer.getMessage("jsp.message.parent_class_loader_is",
- parentClassLoader.toString()));
- } else {
- log.debug(Localizer.getMessage("jsp.message.parent_class_loader_is",
- "<none>"));
- }
- }
-
- initClassPath();
-*/
- if (context instanceof org.apache.sling.scripting.jsp.jasper.servlet.JspCServletContext) {
- return;
- }
if (Constants.IS_SECURITY_ENABLED) {
initSecurity();
@@ -249,20 +217,17 @@ public final class JspRuntimeContext {
*/
private ServletContext context;
private Options options;
-// private ClassLoader parentClassLoader;
private PermissionCollection permissionCollection;
- private CodeSource codeSource;
- // private String classpath;
/**
* Maps JSP pages to their JspServletWrapper's
*/
- private Map<String, JspServletWrapper> jsps = new ConcurrentHashMap<String, JspServletWrapper>();
+ private final Map<String, JspServletWrapper> jsps = new ConcurrentHashMap<String, JspServletWrapper>();
/**
* Maps dependencies to the using jsp.
*/
- private Map<String, Set<String>> depToJsp = new HashMap<String, Set<String>>();
+ private final Map<String, Set<String>> depToJsp = new HashMap<String, Set<String>>();
// ------------------------------------------------------ Public Methods
@@ -283,56 +248,48 @@ public final class JspRuntimeContext {
}
}
- private void invalidate(final JspServletWrapper jsw) {
- log.debug("Invalidating script " + jsw.getJspUri());
- jsw.clearLastModificationTest();
- }
+ /**
+ * Handle jsp modifications
+ */
+ public boolean handleModification(final String scriptName) {
+ JspServletWrapper wrapper = jsps.remove(scriptName);
- public void handleModification(final String repositoryPath) {
- final String scriptName = getScriptPath(repositoryPath);
- synchronized ( this ) {
- // first check if jsps contains this
- JspServletWrapper wrapper = jsps.get(scriptName);
- if ( wrapper != null ) {
- invalidate(wrapper);
- }
- if (wrapperIsValid(wrapper)) {
- synchronized ( depToJsp ) {
- final Set<String> deps = depToJsp.get(scriptName);
- if ( deps != null ) {
- for(final String jspName : deps) {
- wrapper = jsps.get(jspName);
- if ( wrapper != null ) {
- invalidate(wrapper);
- }
- }
- }
- }
- }
- }
- }
+ // first check if jsps contains this
+ boolean removed = this.invalidate(wrapper);
- private String getScriptPath(String repositoryPath) {
- for (final String prefix : PATH_PREFIXES) {
- final String path = prefix + repositoryPath;
- if (depToJsp.containsKey(path)) {
- return path;
+ final Set<String> deps;
+ synchronized ( depToJsp ) {
+ deps = depToJsp.remove(scriptName);
+ }
+ if ( deps != null ) {
+ for(final String dep : deps) {
+ wrapper = jsps.remove(dep);
+ removed |= this.invalidate(wrapper);
}
}
- return repositoryPath;
+ return removed;
}
- private boolean wrapperIsValid(JspServletWrapper wrapper) {
- return wrapper == null || wrapper.getLastModificationTest() == -1;
+ /**
+ * Invalidate a wrapper and destroy it.
+ */
+ private boolean invalidate(final JspServletWrapper wrapper) {
+ if ( wrapper != null ) {
+ log.debug("Invalidating jsp " + wrapper.getJspUri());
+ this.ioProvider.delete(wrapper.getJspUri());
+ wrapper.destroy(true);
+ return true;
+ }
+ return false;
}
/**
- * Add a new JspServletWrapper.
+ * Add a new wrapper
*
* @param jspUri JSP URI
* @param jsw Servlet wrapper for JSP
*/
- public void addWrapper(String jspUri, JspServletWrapper jsw) {
+ public void addWrapper(final String jspUri, final JspServletWrapper jsw) {
jsps.put(jspUri, jsw);
addJspDependencies(jsw);
}
@@ -343,17 +300,10 @@ public final class JspRuntimeContext {
* @param jspUri JSP URI
* @return JspServletWrapper for JSP
*/
- public JspServletWrapper getWrapper(String jspUri) {
+ public JspServletWrapper getWrapper(final String jspUri) {
return jsps.get(jspUri);
}
- public JspServletWrapper getAWrapper() {
- if ( jsps.size() > 0 ) {
- return jsps.values().iterator().next();
- }
- return null;
- }
-
/**
* Remove a JspServletWrapper.
*
@@ -364,87 +314,20 @@ public final class JspRuntimeContext {
}
/**
- * Returns the number of JSPs for which JspServletWrappers exist, i.e.,
- * the number of JSPs that have been loaded into the webapp.
- *
- * @return The number of JSPs that have been loaded into the webapp
- */
- public int getJspCount() {
- return jsps.size();
- }
-
- /**
- * Get the SecurityManager Policy CodeSource for this web
- * applicaiton context.
- *
- * @return CodeSource for JSP
- */
- public CodeSource getCodeSource() {
- return codeSource;
- }
-
- /**
- * Get the parent URLClassLoader.
- *
- * @return URLClassLoader parent
- public ClassLoader getParentClassLoader() {
- return parentClassLoader;
- }
- */
-
- /**
- * Get the SecurityManager PermissionCollection for this
- * web application context.
- *
- * @return PermissionCollection permissions
- */
- public PermissionCollection getPermissionCollection() {
- return permissionCollection;
- }
-
- /**
* Process a "destroy" event for this web application context.
*/
public void destroy() {
Iterator<JspServletWrapper> servlets = jsps.values().iterator();
while (servlets.hasNext()) {
- servlets.next().destroy();
+ servlets.next().destroy(false);
+ }
+ jsps.clear();
+ synchronized ( depToJsp ) {
+ depToJsp.clear();
}
}
/**
- * Increments the JSP reload counter.
- */
- public synchronized void incrementJspReloadCount() {
- jspReloadCount++;
- }
-
- /**
- * Resets the JSP reload counter.
- *
- * @param count Value to which to reset the JSP reload counter
- */
- public synchronized void setJspReloadCount(int count) {
- this.jspReloadCount = count;
- }
-
- /**
- * Gets the current value of the JSP reload counter.
- *
- * @return The current value of the JSP reload counter
- */
- public int getJspReloadCount() {
- return jspReloadCount;
- }
-
- /**
- * The classpath that is passed off to the Java compiler.
- public String getClassPath() {
- return classpath;
- }
- */
-
- /**
* Returns the current {@link IOProvider} of this context.
*/
public IOProvider getIOProvider() {
@@ -453,41 +336,6 @@ public final class JspRuntimeContext {
// -------------------------------------------------------- Private Methods
-
- /**
- * Method used to initialize classpath for compiles.
- private void initClassPath() {
-
- StringBuffer cpath = new StringBuffer();
- String sep = System.getProperty("path.separator");
-
- if (parentClassLoader instanceof URLClassLoader) {
- URL[] urls = ((URLClassLoader) parentClassLoader).getURLs();
-
- for (int i = 0; i < urls.length; i++) {
- // Tomcat 4 can use URL's other than file URL's,
- // a protocol other than file: will generate a
- // bad file system path, so only add file:
- // protocol URL's to the classpath.
-
- if (urls[i].getProtocol().equals("file")) {
- cpath.append(urls[i].getFile() + sep);
- }
- }
- }
-
- cpath.append(options.getScratchDir() + sep);
-
- String cp = (String) context.getAttribute(Constants.SERVLET_CLASSPATH);
-
- classpath = cpath.toString() + cp;
-
- if(log.isDebugEnabled()) {
- log.debug("Compilation classpath initialized: " + getClassPath());
- }
- }
- */
-
/**
* Method used to initialize SecurityManager data.
*/
@@ -511,7 +359,7 @@ public final class JspRuntimeContext {
}
File contextDir = new File(codeBase);
URL url = contextDir.getCanonicalFile().toURL();
- codeSource = new CodeSource(url,(Certificate[])null);
+ final CodeSource codeSource = new CodeSource(url,(Certificate[])null);
permissionCollection = policy.getPermissions(codeSource);
// Create a file read permission for web app context directory
@@ -541,37 +389,7 @@ public final class JspRuntimeContext {
// Allow the JSP to access org.apache.sling.scripting.jsp.jasper.runtime.HttpJspBase
permissionCollection.add( new RuntimePermission(
"accessClassInPackage.org.apache.jasper.runtime") );
-/*
- if (parentClassLoader instanceof URLClassLoader) {
- URL [] urls = ((URLClassLoader) 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(Exception e) {
+ } catch (final Exception e) {
context.log("Security Init for context failed",e);
}
}
Modified: sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/Node.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/Node.java?rev=1336969&r1=1336968&r2=1336969&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/Node.java (original)
+++ sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/Node.java Thu May 10 23:51:27 2012
@@ -5,9 +5,9 @@
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,10 +17,10 @@
package org.apache.sling.scripting.jsp.jasper.compiler;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
-import java.util.ArrayList;
import javax.el.ELContext;
import javax.el.ELException;
@@ -46,7 +46,7 @@ import org.xml.sax.Attributes;
/**
* An internal data representation of a JSP page or a JSP docuement (XML). Also
* included here is a visitor class for tranversing nodes.
- *
+ *
* @author Kin-man Chung
* @author Jan Luehe
* @author Shawn Bayern
@@ -104,7 +104,7 @@ abstract class Node implements TagConsta
/**
* Constructor.
- *
+ *
* @param start
* The location of the jsp page
* @param parent
@@ -118,7 +118,7 @@ abstract class Node implements TagConsta
/**
* Constructor.
- *
+ *
* @param qName
* The action's qualified name
* @param localName
@@ -138,7 +138,7 @@ abstract class Node implements TagConsta
/**
* Constructor for Nodes parsed from standard syntax.
- *
+ *
* @param qName
* The action's qualified name
* @param localName
@@ -162,7 +162,7 @@ abstract class Node implements TagConsta
/**
* Constructor for Nodes parsed from XML syntax.
- *
+ *
* @param qName
* The action's qualified name
* @param localName
@@ -194,7 +194,7 @@ abstract class Node implements TagConsta
/*
* Constructor.
- *
+ *
* @param qName The action's qualified name @param localName The action's
* local name @param text The text associated with this node @param start
* The location of the jsp page @param parent The enclosing node
@@ -219,10 +219,10 @@ abstract class Node implements TagConsta
/*
* Gets this Node's attributes.
- *
+ *
* In the case of a Node parsed from standard syntax, this method returns
* all the Node's attributes.
- *
+ *
* In the case of a Node parsed from XML syntax, this method returns only
* those attributes whose name does not start with xmlns.
*/
@@ -309,7 +309,7 @@ abstract class Node implements TagConsta
/**
* Searches all subnodes of this node for jsp:attribute standard actions,
* and returns that set of nodes as a Node.Nodes object.
- *
+ *
* @return Possibly empty Node.Nodes object containing any jsp:attribute
* subnodes of this Node
*/
@@ -400,7 +400,7 @@ abstract class Node implements TagConsta
/**
* Selects and invokes a method in the visitor class based on the node type.
* This is abstract and should be overrode by the extending classes.
- *
+ *
* @param v
* The visitor class
*/
@@ -446,7 +446,7 @@ abstract class Node implements TagConsta
/*
* Flag indicating if the default page encoding is being used (only
* applicable with standard syntax).
- *
+ *
* True if the page does not provide a page directive with a
* 'contentType' attribute (or the 'contentType' attribute doesn't have
* a CHARSET value), the page does not provide a page directive with a
@@ -594,7 +594,7 @@ abstract class Node implements TagConsta
* Parses the comma-separated list of class or package names in the
* given attribute value and adds each component to this PageDirective's
* vector of imported classes and packages.
- *
+ *
* @param value
* A comma-separated string of imports.
*/
@@ -680,7 +680,7 @@ abstract class Node implements TagConsta
* Parses the comma-separated list of class or package names in the
* given attribute value and adds each component to this PageDirective's
* vector of imported classes and packages.
- *
+ *
* @param value
* A comma-separated string of imports.
*/
@@ -826,7 +826,7 @@ abstract class Node implements TagConsta
* was stored as a String in the "text" field, whereas when this node
* was created from a JSP document, its text was stored as one or more
* TemplateText nodes in its body. This method handles either case.
- *
+ *
* @return The text string
*/
public String getText() {
@@ -1736,13 +1736,13 @@ abstract class Node implements TagConsta
/*
* Computes this custom tag's custom nesting level, which corresponds to
* the number of times this custom tag is nested inside itself.
- *
+ *
* Example:
- *
+ *
* <g:h> <a:b> -- nesting level 0 <c:d> <e:f> <a:b> -- nesting level 1
* <a:b> -- nesting level 2 </a:b> </a:b> <a:b> -- nesting level 1
* </a:b> </e:f> </c:d> </a:b> </g:h>
- *
+ *
* @return Custom tag's nesting level
*/
private int makeCustomNestingLevel() {
@@ -1761,7 +1761,7 @@ abstract class Node implements TagConsta
/**
* Returns true if this custom action has an empty body, and false
* otherwise.
- *
+ *
* A custom action is considered to have an empty body if the following
* holds true: - getBody() returns null, or - all immediate children are
* jsp:attribute actions, or - the action's jsp:body is empty.
@@ -1786,6 +1786,19 @@ abstract class Node implements TagConsta
return hasEmptyBody;
}
+
+ public void clean() {
+ tagHandlerClass = null;
+ jspAttrs = null;
+ tagData = null;
+ tagInfo = null;
+ tagFileInfo = null;
+ varInfos = null;
+ atBeginScriptingVars = null;
+ atEndScriptingVars = null;
+ nestedScriptingVars = null;
+ tagPluginContext = null;
+ }
}
/**
@@ -2033,7 +2046,7 @@ abstract class Node implements TagConsta
/**
* Add a source to Java line mapping
- *
+ *
* @param srcLine
* The postion of the source line, relative to the line at
* the start of this node. The corresponding java line is
@@ -2057,7 +2070,7 @@ abstract class Node implements TagConsta
/**
* Represents attributes that can be request time expressions.
- *
+ *
* Can either be a plain attribute, an attribute that represents a request
* time expression value, or a named attribute (specified using the
* jsp:attribute standard action).
@@ -2104,7 +2117,7 @@ abstract class Node implements TagConsta
/**
* Allow node to validate itself
- *
+ *
* @param ef
* @param ctx
* @throws ELException
@@ -2162,7 +2175,7 @@ abstract class Node implements TagConsta
}
/**
- *
+ *
* @return return true if there's TagAttributeInfo meaning we need to
* assign a ValueExpression
*/
@@ -2171,7 +2184,7 @@ abstract class Node implements TagConsta
}
/**
- *
+ *
* @return return true if there's TagAttributeInfo meaning we need to
* assign a MethodExpression
*/
@@ -2195,7 +2208,7 @@ abstract class Node implements TagConsta
}
return "java.lang.Object";
}
-
+
public String[] getParameterTypeNames() {
if (this.tai != null) {
if (this.isDeferredMethodInput()) {
@@ -2219,7 +2232,7 @@ abstract class Node implements TagConsta
/**
* Only makes sense if namedAttribute is false.
- *
+ *
* @return the value for the attribute, or the expression string
* (stripped of "<%=", "%>", "%=", or "%" but containing "${"
* and "}" for EL expressions)
@@ -2230,7 +2243,7 @@ abstract class Node implements TagConsta
/**
* Only makes sense if namedAttribute is true.
- *
+ *
* @return the nodes that evaluate to the body of this attribute.
*/
public NamedAttribute getNamedAttributeNode() {
@@ -2306,7 +2319,7 @@ abstract class Node implements TagConsta
/**
* Appends a node to the list
- *
+ *
* @param n
* The node to add
*/
@@ -2317,7 +2330,7 @@ abstract class Node implements TagConsta
/**
* Removes the given node from the list.
- *
+ *
* @param n
* The node to be removed
*/
@@ -2327,7 +2340,7 @@ abstract class Node implements TagConsta
/**
* Visit the nodes in the list with the supplied visitor
- *
+ *
* @param v
* The visitor used
*/
Modified: sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/TagLibraryInfoImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/TagLibraryInfoImpl.java?rev=1336969&r1=1336968&r2=1336969&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/TagLibraryInfoImpl.java (original)
+++ sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/compiler/TagLibraryInfoImpl.java Thu May 10 23:51:27 2012
@@ -5,9 +5,9 @@
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -54,7 +54,7 @@ import org.apache.sling.scripting.jsp.ja
/**
* Implementation of the TagLibraryInfo class from the JSP spec.
- *
+ *
* @author Anil K. Vijendran
* @author Mandar Raje
* @author Pierre Delisle
@@ -67,7 +67,7 @@ class TagLibraryInfoImpl extends TagLibr
private Log log = LogFactory.getLog(TagLibraryInfoImpl.class);
private JspCompilationContext ctxt;
-
+
private PageInfo pi;
private ErrorDispatcher err;
@@ -162,7 +162,7 @@ class TagLibraryInfoImpl extends TagLibr
parseTLD(ctxt, location[0], in, null);
// Add TLD to dependency list
- PageInfo pageInfo = ctxt.createCompiler().getPageInfo();
+ PageInfo pageInfo = ctxt.getCompiler().getPageInfo();
if (pageInfo != null) {
pageInfo.addDependant(location[0]);
}
@@ -204,7 +204,7 @@ class TagLibraryInfoImpl extends TagLibr
Collection coll = pi.getTaglibs();
return (TagLibraryInfo[]) coll.toArray(new TagLibraryInfo[0]);
}
-
+
/*
* @param ctxt The JSP compilation context @param uri The TLD's uri @param
* in The TLD's input stream @param jarFileUrl The JAR file containing the
@@ -301,7 +301,7 @@ class TagLibraryInfoImpl extends TagLibr
/*
* @param uri The uri of the TLD @param ctxt The compilation context
- *
+ *
* @return String array whose first element denotes the path to the TLD. If
* the path to the TLD points to a jar file, then the second element denotes
* the name of the TLD entry in the jar file, which is hardcoded to
@@ -438,11 +438,11 @@ class TagLibraryInfoImpl extends TagLibr
/*
* Parses the tag file directives of the given TagFile and turns them into a
* TagInfo.
- *
+ *
* @param elem The <tag-file> element in the TLD @param uri The location of
* the TLD, in case the tag file is specified relative to it @param jarFile
* The JAR file, in case the tag file is packaged in a JAR
- *
+ *
* @return TagInfo correspoding to tag file directives
*/
private TagFileInfo createTagFileInfo(TreeNode elem, String uri,
@@ -463,8 +463,8 @@ class TagLibraryInfoImpl extends TagLibr
// Ignore <example> element: Bugzilla 33538
} else if ("tag-extension".equals(tname)) {
// Ignore <tag-extension> element: Bugzilla 33538
- } else if ("icon".equals(tname)
- || "display-name".equals(tname)
+ } else if ("icon".equals(tname)
+ || "display-name".equals(tname)
|| "description".equals(tname)) {
// Ignore these elements: Bugzilla 38015
} else {
@@ -580,7 +580,7 @@ class TagLibraryInfoImpl extends TagLibr
// translation time) the type is fixed at java.lang.String.
type = "java.lang.String";
}
-
+
return new TagAttributeInfo(name, required, type, rtexprvalue,
isFragment, null, deferredValue, deferredMethod, expectedType,
methodSignature);
@@ -732,7 +732,7 @@ class TagLibraryInfoImpl extends TagLibr
/**
* The instance (if any) for the TagLibraryValidator class.
- *
+ *
* @return The TagLibraryValidator instance, if any.
*/
public TagLibraryValidator getTagLibraryValidator() {
@@ -743,7 +743,7 @@ class TagLibraryInfoImpl extends TagLibr
* Translation-time validation of the XML document associated with the JSP
* page. This is a convenience method on the associated TagLibraryValidator
* class.
- *
+ *
* @param thePage
* The JSP page object
* @return A string indicating whether the page is valid or not.
Modified: sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/servlet/JspServletWrapper.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/servlet/JspServletWrapper.java?rev=1336969&r1=1336968&r2=1336969&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/servlet/JspServletWrapper.java (original)
+++ sling/trunk/bundles/scripting/jsp/src/main/java/org/apache/sling/scripting/jsp/jasper/servlet/JspServletWrapper.java Thu May 10 23:51:27 2012
@@ -17,9 +17,11 @@
package org.apache.sling.scripting.jsp.jasper.servlet;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
+import java.net.URLConnection;
+import java.util.Iterator;
+import java.util.List;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
@@ -34,9 +36,14 @@ import javax.servlet.jsp.tagext.TagInfo;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.sling.api.SlingException;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingIOException;
+import org.apache.sling.api.SlingServletException;
import org.apache.sling.api.scripting.ScriptEvaluationException;
+import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.commons.classloader.DynamicClassLoader;
import org.apache.sling.scripting.jsp.SlingPageException;
+import org.apache.sling.scripting.jsp.jasper.IsolatedClassLoader;
import org.apache.sling.scripting.jsp.jasper.JasperException;
import org.apache.sling.scripting.jsp.jasper.JspCompilationContext;
import org.apache.sling.scripting.jsp.jasper.Options;
@@ -68,36 +75,34 @@ import org.apache.sling.scripting.jsp.ja
public class JspServletWrapper {
// Logger
- private Log log = LogFactory.getLog(JspServletWrapper.class);
+ private final Log log = LogFactory.getLog(JspServletWrapper.class);
private Servlet theServlet;
- private String jspUri;
- private Class<?> servletClass;
- private Class<?> tagHandlerClass;
- private JspCompilationContext ctxt;
+ private final String jspUri;
+ private final JspCompilationContext ctxt;
private long available = 0L;
- private ServletConfig config;
- private Options options;
- private boolean firstTime = true;
- private volatile boolean reload = true;
- private boolean isTagFile;
- private int tripCount;
- private JasperException compileException;
- private long servletClassLastModifiedTime;
- private volatile long lastModificationTest = 0L;
+ private final ServletConfig config;
+ private final Options options;
+ private final boolean isTagFile;
+ private volatile JasperException compileException;
+ private volatile long lastModificationTest = -1L;
+ private volatile int tripCount;
- /*
+ private volatile List<String> dependents;
+
+ /**
* JspServletWrapper for JSP pages.
*/
- public JspServletWrapper(ServletConfig config, Options options, String jspUri,
- boolean isErrorPage, JspRuntimeContext rctxt)
- throws JasperException {
-
- this.isTagFile = false;
+ public JspServletWrapper(final ServletConfig config,
+ final Options options,
+ final String jspUri,
+ final boolean isErrorPage,
+ final JspRuntimeContext rctxt) {
+ this.isTagFile = false;
this.config = config;
this.options = options;
this.jspUri = jspUri;
- ctxt = new JspCompilationContext(jspUri, isErrorPage, options,
+ this.ctxt = new JspCompilationContext(jspUri, isErrorPage, options,
config.getServletContext(),
this, rctxt);
}
@@ -105,19 +110,18 @@ public class JspServletWrapper {
/**
* JspServletWrapper for tag files.
*/
- public JspServletWrapper(ServletContext servletContext,
- Options options,
- String tagFilePath,
- TagInfo tagInfo,
- JspRuntimeContext rctxt,
- URL tagFileJarUrl)
+ public JspServletWrapper(final ServletContext servletContext,
+ final Options options,
+ final String tagFilePath,
+ final TagInfo tagInfo,
+ final JspRuntimeContext rctxt,
+ final URL tagFileJarUrl)
throws JasperException {
this.isTagFile = true;
this.config = null; // not used
this.options = options;
this.jspUri = tagFilePath;
- this.tripCount = 0;
- ctxt = new JspCompilationContext(jspUri, tagInfo, options,
+ this.ctxt = new JspCompilationContext(jspUri, tagInfo, options,
servletContext, this, rctxt,
tagFileJarUrl);
}
@@ -126,135 +130,63 @@ public class JspServletWrapper {
return ctxt;
}
- public void setReload(boolean reload) {
- this.reload = reload;
- }
-
- public Servlet getServlet()
- throws ServletException, IOException, FileNotFoundException
- {
- // check if the used class loader is still alive
- if (!reload) {
- if ( servletClass.getClassLoader() instanceof DynamicClassLoader ) {
- reload = !((DynamicClassLoader)servletClass.getClassLoader()).isLive();
+ public boolean isValid() {
+ if ( theServlet != null ) {
+ if ( theServlet.getClass().getClassLoader() instanceof DynamicClassLoader ) {
+ return ((DynamicClassLoader)theServlet.getClass().getClassLoader()).isLive();
}
}
- if (reload) {
- synchronized (this) {
- // Synchronizing on jsw enables simultaneous loading
- // of different pages, but not the same page.
- if (reload) {
- // This is to maintain the original protocol.
- destroy();
-
- Servlet servlet = null;
-
- try {
- servletClass = ctxt.load();
- servlet = (Servlet) servletClass.newInstance();
- AnnotationProcessor annotationProcessor = (AnnotationProcessor) config.getServletContext().getAttribute(AnnotationProcessor.class.getName());
- if (annotationProcessor != null) {
- annotationProcessor.processAnnotations(servlet);
- annotationProcessor.postConstruct(servlet);
- }
- } catch (IllegalAccessException e) {
- throw new JasperException(e);
- } catch (InstantiationException e) {
- throw new JasperException(e);
- } catch (IOException e) {
- throw e;
- } catch (Exception e) {
- throw new JasperException(e);
- }
-
- servlet.init(config);
+ return false;
+ }
- if (!firstTime) {
- ctxt.getRuntimeContext().incrementJspReloadCount();
- }
+ private Servlet loadServlet()
+ throws ServletException, IOException {
+ Servlet servlet = null;
- theServlet = servlet;
- reload = false;
- }
+ try {
+ servlet = (Servlet) ctxt.load().newInstance();
+ AnnotationProcessor annotationProcessor = (AnnotationProcessor) config.getServletContext().getAttribute(AnnotationProcessor.class.getName());
+ if (annotationProcessor != null) {
+ annotationProcessor.processAnnotations(servlet);
+ annotationProcessor.postConstruct(servlet);
}
+ } catch (IllegalAccessException e) {
+ throw new JasperException(e);
+ } catch (InstantiationException e) {
+ throw new JasperException(e);
+ } catch (Exception e) {
+ throw new JasperException(e);
}
- return theServlet;
- }
- public ServletContext getServletContext() {
- return config.getServletContext();
- }
+ servlet.init(config);
- /**
- * Sets the compilation exception for this JspServletWrapper.
- *
- * @param je The compilation exception
- */
- public void setCompilationException(JasperException je) {
- this.compileException = je;
- }
-
- /**
- * Sets the last-modified time of the servlet class file associated with
- * this JspServletWrapper.
- *
- * @param lastModified Last-modified time of servlet class
- */
- public void setServletClassLastModifiedTime(long lastModified) {
- if (this.servletClassLastModifiedTime < lastModified) {
- synchronized (this) {
- if (this.servletClassLastModifiedTime < lastModified) {
- this.servletClassLastModifiedTime = lastModified;
- reload = true;
- }
- }
- }
+ return servlet;
}
/**
* Compile (if needed) and load a tag file
*/
public Class<?> loadTagFile() throws JasperException {
-
- try {
- if (ctxt.isRemoved()) {
- throw new FileNotFoundException(jspUri);
- }
- if (firstTime || this.lastModificationTest <= 0) {
- synchronized (this) {
- if (firstTime || this.lastModificationTest <= 0 ) {
- ctxt.compile();
- this.lastModificationTest = System.currentTimeMillis();
- firstTime = false;
- } else if ( compileException != null ) {
- // Throw cached compilation exception
+ if (this.lastModificationTest <= 0) {
+ synchronized (this) {
+ if (this.lastModificationTest <= 0 ) {
+ this.compileException = ctxt.compile();
+ this.lastModificationTest = System.currentTimeMillis();
+ if ( compileException != null ) {
throw compileException;
}
- }
- } else {
- if (compileException != null) {
+ } else if ( compileException != null ) {
+ // Throw cached compilation exception
throw compileException;
}
}
-
- if (!reload) {
- if ( tagHandlerClass.getClassLoader() instanceof DynamicClassLoader ) {
- reload = !((DynamicClassLoader)tagHandlerClass.getClassLoader()).isLive();
- }
- }
- if (reload) {
- synchronized ( this ) {
- if ( reload ) {
- tagHandlerClass = ctxt.load();
- reload = false;
- }
- }
+ } else {
+ if (compileException != null) {
+ throw compileException;
}
- } catch (IOException ex) {
- throw new JasperException(ex);
- }
+ }
- return tagHandlerClass;
+ return ctxt.load();
}
/**
@@ -264,7 +196,6 @@ public class JspServletWrapper {
* generated and compiled.
*/
public Class<?> loadTagFilePrototype() throws JasperException {
-
ctxt.setPrototypeMode(true);
try {
return loadTagFile();
@@ -277,33 +208,26 @@ public class JspServletWrapper {
* Get a list of files that the current page has source dependency on.
*/
@SuppressWarnings("unchecked")
- public java.util.List<String> getDependants() {
- try {
- Object target;
- if (isTagFile) {
- if (!reload) {
- if ( tagHandlerClass.getClassLoader() instanceof DynamicClassLoader ) {
- reload = !((DynamicClassLoader)tagHandlerClass.getClassLoader()).isLive();
- }
+ public List<String> getDependants() {
+ if ( this.dependents == null ) {
+ try {
+ Object target;
+ if (isTagFile) {
+ target = ctxt.load().newInstance();
+ } else {
+ // we load the servlet with a separate class loader
+ final String name = this.ctxt.getServletPackageName() + "." + this.ctxt.getServletClassName();
+ final ClassLoader cl = new IsolatedClassLoader(this.ctxt.getRuntimeContext().getIOProvider());
+ target = cl.loadClass(name).newInstance();
}
- if (reload) {
- synchronized ( this ) {
- if ( reload ) {
- tagHandlerClass = ctxt.load();
- reload = false;
- }
- }
+ if (target != null && target instanceof JspSourceDependent) {
+ this.dependents = (List<String>) ((JspSourceDependent) target).getDependants();
}
- target = tagHandlerClass.newInstance();
- } else {
- target = getServlet();
+ } catch (final Throwable ex) {
+ // ignore
}
- if (target != null && target instanceof JspSourceDependent) {
- return ((java.util.List) ((JspSourceDependent) target).getDependants());
- }
- } catch (Throwable ex) {
}
- return null;
+ return this.dependents;
}
public boolean isTagFile() {
@@ -322,17 +246,116 @@ public class JspServletWrapper {
return jspUri;
}
- public void service(HttpServletRequest request,
- HttpServletResponse response,
- boolean precompile)
- throws ServletException, IOException, FileNotFoundException {
+ private boolean isOutDated() {
+ final String jsp = ctxt.getJspFile();
- try {
+ long jspRealLastModified = ctxt.getRuntimeContext().getIOProvider().lastModified(jsp);
+
+ long targetLastModified = 0;
+ final String targetFile = ctxt.getClassFileName();
+
+ targetLastModified = ctxt.getRuntimeContext().getIOProvider().lastModified(targetFile);
+ if (targetLastModified < 0) {
+ return true;
+ }
+
+ if (targetLastModified < jspRealLastModified) {
+ if (log.isDebugEnabled()) {
+ log.debug("Compiler: outdated: " + targetFile + " "
+ + targetLastModified);
+ }
+ return true;
+ }
+
+ final List<String> depends = this.getDependants();
+ if (depends == null) {
+ return false;
+ }
+
+ final Iterator<String> it = depends.iterator();
+ while (it.hasNext()) {
+ final String include = it.next();
+ // ignore tag libs, we are reloaded if a taglib changes anyway
+ if ( include.startsWith("tld:") ) {
+ continue;
+ }
+ try {
+ final URL includeUrl = ctxt.getResource(include);
+ if (includeUrl == null) {
+ return true;
+ }
+
+ URLConnection includeUconn = includeUrl.openConnection();
+ long includeLastModified = includeUconn.getLastModified();
+ includeUconn.getInputStream().close();
+
+ if (includeLastModified > targetLastModified) {
+ return true;
+ }
+ } catch (Exception e) {
+ return true;
+ }
+ }
+
+ return false;
+
+ }
- if (ctxt.isRemoved()) {
- throw new FileNotFoundException(jspUri);
+ /**
+ * Prepare the servlet:
+ * - compile it if it either hasn't been compiled yet or is out dated
+ * - load the servlet
+ *
+ */
+ private void prepareServlet(final HttpServletRequest request,
+ final HttpServletResponse response)
+ throws IOException, ServletException {
+ if ( isOutDated() ) {
+ // Compile...
+ log.debug("Compiling " + this.jspUri);
+ this.compileException = ctxt.compile();
+ if ( compileException != null ) {
+ throw compileException;
}
+ }
+
+ // (Re)load servlet class file
+ log.debug("Loading " + this.jspUri);
+ this.theServlet = this.loadServlet();
+ }
+ /**
+ * @param bindings
+ * @throws SlingIOException
+ * @throws SlingServletException
+ * @throws IllegalArgumentException if the Jasper Precompile controller
+ * request parameter has an illegal value.
+ */
+ public void service(final SlingBindings bindings) {
+ final SlingHttpServletRequest request = bindings.getRequest();
+ final Object oldValue = request.getAttribute(SlingBindings.class.getName());
+ try {
+ request.setAttribute(SlingBindings.class.getName(), bindings);
+ service(request, bindings.getResponse());
+ } catch (SlingException se) {
+ // rethrow as is
+ throw se;
+ } catch (IOException ioe) {
+ throw new SlingIOException(ioe);
+ } catch (ServletException se) {
+ throw new SlingServletException(se);
+ } finally {
+ request.setAttribute(SlingBindings.class.getName(), oldValue);
+ }
+ }
+
+ /**
+ * Process the request.
+ */
+ public void service(final HttpServletRequest request,
+ final HttpServletResponse response)
+ throws ServletException, IOException {
+ try {
if ((available > 0L) && (available < Long.MAX_VALUE)) {
if (available > System.currentTimeMillis()) {
response.setDateHeader("Retry-After", available);
@@ -344,72 +367,18 @@ public class JspServletWrapper {
// Wait period has expired. Reset.
available = 0;
}
-
- /*
- * (1) Compile
- */
- if (firstTime || this.lastModificationTest <= 0 ) {
- synchronized (this) {
- if (firstTime || this.lastModificationTest <= 0 ) {
- // The following sets reload to true, if necessary
- ctxt.compile();
- this.lastModificationTest = System.currentTimeMillis();
- firstTime = false;
- } else if ( compileException != null ) {
- // Throw cached compilation exception
- throw compileException;
-
+ if ( theServlet == null ) {
+ synchronized ( this ) {
+ if ( theServlet == null ) {
+ this.prepareServlet(request, response);
}
}
- } else if (compileException != null) {
- // Throw cached compilation exception
- throw compileException;
- }
-
- /*
- * (2) (Re)load servlet class file
- */
- getServlet();
-
- // If a page is to be precompiled only, return.
- if (precompile) {
- return;
}
-
- } catch (FileNotFoundException ex) {
- ctxt.incrementRemoved();
- 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);
- }
- try {
- response.sendError(HttpServletResponse.SC_NOT_FOUND,
- ex.getMessage());
- } catch (IllegalStateException ise) {
- log.error(Localizer.getMessage("jsp.error.file.not.found",
- ex.getMessage()),
- ex);
+ if ( compileException != null ) {
+ throw compileException;
}
- return;
- } catch (final ServletException ex) {
- handleJspException(ex);
- } catch (final IOException ex) {
- handleJspException(ex);
- } catch (final IllegalStateException ex) {
- handleJspException(ex);
- } catch (final Exception ex) {
- handleJspException(ex);
- }
- try {
-
- /*
- * (3) Service request
- */
+ // Service request
if (theServlet instanceof SingleThreadModel) {
// sync on the wrapper so that the freshness
// of the page is determined right before servicing
@@ -420,7 +389,7 @@ public class JspServletWrapper {
theServlet.service(request, response);
}
- } catch (UnavailableException ex) {
+ } catch (final UnavailableException ex) {
String includeRequestUri = (String)
request.getAttribute("javax.servlet.include.request_uri");
if (includeRequestUri != null) {
@@ -452,8 +421,14 @@ public class JspServletWrapper {
}
}
- public void destroy() {
+ public void destroy(boolean deleteGeneratedFiles) {
if (theServlet != null) {
+ if ( deleteGeneratedFiles ) {
+ final org.apache.sling.scripting.jsp.jasper.compiler.Compiler c = this.ctxt.getCompiler();
+ if ( c != null ) {
+ c.removeGeneratedFiles();
+ }
+ }
theServlet.destroy();
AnnotationProcessor annotationProcessor = (AnnotationProcessor) config.getServletContext().getAttribute(AnnotationProcessor.class.getName());
if (annotationProcessor != null) {
@@ -465,23 +440,11 @@ public class JspServletWrapper {
e.getMessage()), e);
}
}
+ theServlet = null;
}
}
/**
- * @return Returns the lastModificationTest.
- */
- public long getLastModificationTest() {
- return lastModificationTest;
- }
- /**
- *Clea the lastModificationTest.
- */
- public void clearLastModificationTest() {
- this.lastModificationTest = -1;
- }
-
- /**
* <p>Attempts to construct a JasperException that contains helpful information
* about what went wrong. Uses the JSP compiler system to translate the line
* number in the generated servlet that originated the exception to a line
@@ -531,7 +494,7 @@ public class JspServletWrapper {
StackTraceElement jspFrame = null;
for (int i=0; i<frames.length; ++i) {
- if ( frames[i].getClassName().equals(this.getServlet().getClass().getName()) ) {
+ if ( frames[i].getClassName().equals(this.theServlet.getClass().getName()) ) {
jspFrame = frames[i];
break;
}