You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 10:04:40 UTC
[sling-org-apache-sling-scripting-java] 07/43: SLING-1991 : Last
modified of java file should not be compared against compiled class if file
is modified
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to annotated tag org.apache.sling.scripting.java-2.0.10
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-java.git
commit 08f433dd4ce83def35574414cba68844f3643df1
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Thu Feb 24 09:09:10 2011 +0000
SLING-1991 : Last modified of java file should not be compared against compiled class if file is modified
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/java@1074080 13f79535-47bb-0310-9956-ffa450edef68
---
pom.xml | 7 ++
.../sling/scripting/java/impl/CompilerOptions.java | 14 ++-
.../java/impl/JavaScriptEngineFactory.java | 16 +--
.../sling/scripting/java/impl/ServletCache.java | 5 +-
.../sling/scripting/java/impl/ServletWrapper.java | 116 ++++++++++++++-------
.../sling/scripting/java/impl/SlingIOProvider.java | 11 ++
6 files changed, 123 insertions(+), 46 deletions(-)
diff --git a/pom.xml b/pom.xml
index 375c01d..71c3bc3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,13 @@
</dependency>
<dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.classloader</artifactId>
+ <version>1.2.0</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
diff --git a/src/main/java/org/apache/sling/scripting/java/impl/CompilerOptions.java b/src/main/java/org/apache/sling/scripting/java/impl/CompilerOptions.java
index ab7798e..7e937f7 100644
--- a/src/main/java/org/apache/sling/scripting/java/impl/CompilerOptions.java
+++ b/src/main/java/org/apache/sling/scripting/java/impl/CompilerOptions.java
@@ -31,7 +31,7 @@ public class CompilerOptions extends Options {
* the component configuration.
*/
public static CompilerOptions createOptions(final Dictionary<String, Object> props) {
- CompilerOptions opts = new CompilerOptions();
+ final CompilerOptions opts = new CompilerOptions();
final Boolean classDebugInfo = (Boolean)props.get(JavaScriptEngineFactory.PROPERTY_CLASSDEBUGINFO);
opts.put(Options.KEY_GENERATE_DEBUG_INFO, classDebugInfo != null ? classDebugInfo : true);
@@ -50,6 +50,18 @@ public class CompilerOptions extends Options {
return opts;
}
+ /**
+ * Copy options
+ */
+ public static CompilerOptions copyOptions(final CompilerOptions opt) {
+ final CompilerOptions opts = new CompilerOptions();
+ opts.putAll(opt);
+
+ opts.encoding = opt.getJavaEncoding();
+
+ return opts;
+ }
+
public String getJavaEncoding() {
return this.encoding;
}
diff --git a/src/main/java/org/apache/sling/scripting/java/impl/JavaScriptEngineFactory.java b/src/main/java/org/apache/sling/scripting/java/impl/JavaScriptEngineFactory.java
index 60d4063..41a8d74 100644
--- a/src/main/java/org/apache/sling/scripting/java/impl/JavaScriptEngineFactory.java
+++ b/src/main/java/org/apache/sling/scripting/java/impl/JavaScriptEngineFactory.java
@@ -250,16 +250,20 @@ public class JavaScriptEngineFactory
*/
public void handleEvent(Event event) {
if ( SlingConstants.TOPIC_RESOURCE_CHANGED.equals(event.getTopic()) ) {
- this.handleModification((String)event.getProperty(SlingConstants.PROPERTY_PATH));
+ this.handleModification((String)event.getProperty(SlingConstants.PROPERTY_PATH), false);
} else if ( SlingConstants.TOPIC_RESOURCE_REMOVED.equals(event.getTopic()) ) {
- this.handleModification((String)event.getProperty(SlingConstants.PROPERTY_PATH));
+ this.handleModification((String)event.getProperty(SlingConstants.PROPERTY_PATH), true);
}
}
- private void handleModification(final String scriptName) {
- final ServletWrapper wrapper = this.ioProvider.getServletCache().getWrapper(scriptName);
- if ( wrapper != null ) {
- wrapper.handleModification();
+ private void handleModification(final String scriptName, final boolean remove) {
+ if ( remove ) {
+ this.ioProvider.getServletCache().removeWrapper(scriptName);
+ } else {
+ final ServletWrapper wrapper = this.ioProvider.getServletCache().getWrapper(scriptName);
+ if ( wrapper != null ) {
+ wrapper.handleModification();
+ }
}
}
diff --git a/src/main/java/org/apache/sling/scripting/java/impl/ServletCache.java b/src/main/java/org/apache/sling/scripting/java/impl/ServletCache.java
index 02e01d5..7bed05f 100644
--- a/src/main/java/org/apache/sling/scripting/java/impl/ServletCache.java
+++ b/src/main/java/org/apache/sling/scripting/java/impl/ServletCache.java
@@ -57,7 +57,10 @@ public final class ServletCache {
* @param servletUri Servlet URI
*/
public void removeWrapper(String servletUri) {
- servlets.remove(servletUri);
+ final ServletWrapper wrapper = servlets.remove(servletUri);
+ if ( wrapper != null ) {
+ wrapper.destroy();
+ }
}
/**
diff --git a/src/main/java/org/apache/sling/scripting/java/impl/ServletWrapper.java b/src/main/java/org/apache/sling/scripting/java/impl/ServletWrapper.java
index 71a7a8d..17471cc 100644
--- a/src/main/java/org/apache/sling/scripting/java/impl/ServletWrapper.java
+++ b/src/main/java/org/apache/sling/scripting/java/impl/ServletWrapper.java
@@ -17,7 +17,6 @@
package org.apache.sling.scripting.java.impl;
-import java.io.IOException;
import java.util.List;
import javax.servlet.Servlet;
@@ -28,6 +27,7 @@ import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.sling.commons.classloader.DynamicClassLoader;
import org.apache.sling.commons.compiler.CompilationResult;
import org.apache.sling.commons.compiler.CompilerMessage;
import org.slf4j.Logger;
@@ -54,14 +54,16 @@ public class ServletWrapper {
/** The path to the servlet. */
private final String sourcePath;
+ /** Flag for handling modifications. */
private volatile long lastModificationTest = 0L;
- private volatile Class<?> servletClass;
-
+ /** The compiled and instantiated servlet. */
private volatile Servlet theServlet;
- private long available = 0L;
+ /** Flag handling an unavailable exception. */
+ private volatile long available = 0L;
+ /** The exception thrown by the compilation. */
private volatile Exception compileException;
/**
@@ -80,8 +82,7 @@ public class ServletWrapper {
* Call the servlet.
* @param request The current request.
* @param response The current response.
- * @throws ServletException
- * @throws IOException
+ * @throws Exception
*/
public void service(HttpServletRequest request,
HttpServletResponse response)
@@ -101,20 +102,10 @@ public class ServletWrapper {
}
// check for compilation
- if (this.lastModificationTest == 0 ) {
+ if (this.lastModificationTest <= 0 ) {
synchronized (this) {
- if (this.lastModificationTest == 0 ) {
- try {
- // clear exception
- this.compileException = null;
- this.compile();
- } catch (Exception ex) {
- // store exception for futher access attempts
- this.compileException = ex;
- throw ex;
- } finally {
- this.lastModificationTest = System.currentTimeMillis();
- }
+ if (this.lastModificationTest <= 0 ) {
+ this.compile();
} else if (compileException != null) {
// Throw cached compilation exception
throw compileException;
@@ -125,15 +116,17 @@ public class ServletWrapper {
throw compileException;
}
+ final Servlet servlet = getServlet();
+
// invoke the servlet
- if (theServlet instanceof SingleThreadModel) {
+ if (servlet instanceof SingleThreadModel) {
// sync on the wrapper so that the freshness
// of the page is determined right before servicing
synchronized (this) {
- theServlet.service(request, response);
+ servlet.service(request, response);
}
} else {
- theServlet.service(request, response);
+ servlet.service(request, response);
}
} catch (UnavailableException ex) {
@@ -147,7 +140,6 @@ public class ServletWrapper {
(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
ex.getMessage());
logger.error("Java servlet {} is unavailable.", this.sourcePath);
- return;
}
}
@@ -161,32 +153,80 @@ public class ServletWrapper {
}
}
- /** Handle the modification. */
+ /**
+ * Handle the modification.
+ */
public void handleModification() {
- this.lastModificationTest = 0;
+ logger.debug("Received modification event for {}", this.sourcePath);
+ this.lastModificationTest = -1;
}
- private void compile() throws Exception {
- final CompilationUnit unit = new CompilationUnit(this.sourcePath, className, ioProvider);
- final CompilationResult result = this.ioProvider.getCompiler().compile(new org.apache.sling.commons.compiler.CompilationUnit[] {unit},
- ioProvider.getOptions());
+ /**
+ * Check if the used classloader is still valid
+ */
+ private boolean checkReload() {
+ final Servlet servlet = this.theServlet;
+ final Class<?> servletClass = servlet != null ? servlet.getClass() : null;
+ if ( servletClass != null && servletClass.getClassLoader() instanceof DynamicClassLoader ) {
+ return !((DynamicClassLoader)servletClass.getClassLoader()).isLive();
+ }
+ return false;
+ }
- final List<CompilerMessage> errors = result.getErrors();
- if ( errors != null && errors.size() > 0 ) {
- throw CompilerException.create(errors, this.sourcePath);
+ /**
+ * Get the servlet class - if the used classloader is not valid anymore
+ * the class is reloaded.
+ */
+ public Servlet getServlet()
+ throws Exception {
+ // check if the used class loader is still alive
+ if (this.checkReload()) {
+ synchronized (this) {
+ if (this.checkReload()) {
+ this.compile();
+ }
+ }
}
- if ( result.didCompile() || this.theServlet == null ) {
- destroy();
+ return theServlet;
+ }
- this.servletClass = result.loadCompiledClass(this.className);
- final Servlet servlet = (Servlet) servletClass.newInstance();
- servlet.init(config);
+ /**
+ * Compile the servlet java class
+ * and instantiate the servlet
+ */
+ private void compile()
+ throws Exception {
+ logger.debug("Compiling {}", this.sourcePath);
+ // clear exception
+ this.compileException = null;
+ try {
+ final CompilerOptions opts = (this.lastModificationTest == -1 ? this.ioProvider.getForceCompileOptions() : this.ioProvider.getOptions());
+ final CompilationUnit unit = new CompilationUnit(this.sourcePath, className, ioProvider);
+ final CompilationResult result = this.ioProvider.getCompiler().compile(new org.apache.sling.commons.compiler.CompilationUnit[] {unit},
+ opts);
- theServlet = servlet;
+ final List<CompilerMessage> errors = result.getErrors();
+ if ( errors != null && errors.size() > 0 ) {
+ throw CompilerException.create(errors, this.sourcePath);
+ }
+ if ( result.didCompile() || this.theServlet == null ) {
+ destroy();
+ final Class<?> servletClass = result.loadCompiledClass(this.className);
+ final Servlet servlet = (Servlet) servletClass.newInstance();
+ servlet.init(this.config);
+ this.theServlet = servlet;
+ }
+ } catch (final Exception ex) {
+ // store exception for futher access attempts
+ this.compileException = ex;
+ throw ex;
+ } finally {
+ this.lastModificationTest = System.currentTimeMillis();
}
}
+ /** Compiler exception .*/
protected final static class CompilerException extends ServletException {
private static final long serialVersionUID = 7353686069328527452L;
diff --git a/src/main/java/org/apache/sling/scripting/java/impl/SlingIOProvider.java b/src/main/java/org/apache/sling/scripting/java/impl/SlingIOProvider.java
index fdba2e7..a7ef07a 100644
--- a/src/main/java/org/apache/sling/scripting/java/impl/SlingIOProvider.java
+++ b/src/main/java/org/apache/sling/scripting/java/impl/SlingIOProvider.java
@@ -30,6 +30,7 @@ import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.compiler.JavaCompiler;
+import org.apache.sling.commons.compiler.Options;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,8 +46,12 @@ public class SlingIOProvider {
private final JavaCompiler compiler;
+ /** Options for compilation. */
private final CompilerOptions options;
+ /** Options for compilation including the force compile option. */
+ private final CompilerOptions forceCompileOptions;
+
/**
* Servlet cache.
*/
@@ -60,6 +65,8 @@ public class SlingIOProvider {
this.requestResourceResolver = new ThreadLocal<ResourceResolver>();
this.compiler = compiler;
this.options = options;
+ this.forceCompileOptions = CompilerOptions.copyOptions(options);
+ this.forceCompileOptions.put(Options.KEY_FORCE_COMPILATION, true);
}
void destroy() {
@@ -84,6 +91,10 @@ public class SlingIOProvider {
return this.options;
}
+ public CompilerOptions getForceCompileOptions() {
+ return this.forceCompileOptions;
+ }
+
public ServletCache getServletCache() {
return this.servletCache;
}
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.