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;
                 }