SLING-874 : Use new commons compiler for java servlet scripting
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@926970 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index db84dac..12fb9a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,17 +90,11 @@
<version>2.0.2-incubator</version>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.commons.classloader</artifactId>
- <version>1.0.0</version>
- <scope>provided</scope>
- </dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.compiler</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
diff --git a/src/main/java/org/apache/sling/scripting/java/impl/CompilationUnit.java b/src/main/java/org/apache/sling/scripting/java/impl/CompilationUnit.java
index 86660af..81d386f 100644
--- a/src/main/java/org/apache/sling/scripting/java/impl/CompilationUnit.java
+++ b/src/main/java/org/apache/sling/scripting/java/impl/CompilationUnit.java
@@ -16,165 +16,54 @@
*/
package org.apache.sling.scripting.java.impl;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.OutputStream;
import java.io.Reader;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.sling.commons.compiler.ClassWriter;
-import org.apache.sling.commons.compiler.CompileUnit;
-import org.apache.sling.commons.compiler.CompilerEnvironment;
-import org.apache.sling.commons.compiler.ErrorHandler;
public class CompilationUnit
- implements CompileUnit, CompilerEnvironment, ErrorHandler, ClassWriter {
+ implements org.apache.sling.commons.compiler.CompilationUnit {
private final SlingIOProvider ioProvider;
private final String className;
private final String sourceFile;
- /** The list of compile errors - this is created lazily. */
- private List<CompilerError> errors;
-
- public CompilationUnit(String sourceFile,
- String className,
- SlingIOProvider ioProvider) {
+ public CompilationUnit(final String sourceFile,
+ final String className,
+ final SlingIOProvider ioProvider) {
this.className = className;
this.sourceFile = sourceFile;
this.ioProvider = ioProvider;
}
/**
- * @see org.apache.sling.commons.compiler.CompileUnit#getSourceFileName()
+ * @see org.apache.sling.commons.compiler.CompilationUnit#getMainClassName()
*/
- public String getSourceFileName() {
- return getMainTypeName() + ".java";
+ public String getMainClassName() {
+ return this.className;
}
/**
- * @see org.apache.sling.commons.compiler.CompileUnit#getSourceFileContents()
+ * @see org.apache.sling.commons.compiler.CompilationUnit#getSource()
*/
- public char[] getSourceFileContents() {
- char[] result = null;
+ public Reader getSource() throws IOException {
InputStream fr = null;
try {
fr = ioProvider.getInputStream(this.sourceFile);
- final Reader reader = new BufferedReader(new InputStreamReader(fr, ioProvider.getOptions().getJavaEncoding()));
- try {
- char[] chars = new char[8192];
- StringBuilder buf = new StringBuilder();
- int count;
- while ((count = reader.read(chars, 0, chars.length)) > 0) {
- buf.append(chars, 0, count);
- }
- result = new char[buf.length()];
- buf.getChars(0, result.length, result, 0);
- } finally {
- reader.close();
- }
+ return new InputStreamReader(fr, ioProvider.getOptions().getJavaEncoding());
} catch (IOException e) {
- this.onError(e.getMessage(), this.sourceFile, 0, 0);
- }
- return result;
- }
-
- /**
- * @see org.apache.sling.commons.compiler.CompileUnit#getMainTypeName()
- */
- public String getMainTypeName() {
- int dot = className.lastIndexOf('.');
- if (dot > 0) {
- return className.substring(dot + 1);
- }
- return className;
- }
-
- /**
- * @see org.apache.sling.commons.compiler.CompilerEnvironment#isPackage(java.lang.String)
- */
- public boolean isPackage(String result) {
- if (result.equals(this.className)) {
- return false;
- }
- String resourceName = result.replace('.', '/') + ".class";
- if ( resourceName.startsWith("/") ) {
- resourceName = resourceName.substring(1);
- }
- final InputStream is = this.ioProvider.getClassLoader().getResourceAsStream(resourceName);
- if ( is != null ) {
- try {
- is.close();
- } catch (IOException ignore) {}
- }
- return is == null;
- }
-
- /**
- * @see org.apache.sling.commons.compiler.CompilerEnvironment#findClass(java.lang.String)
- */
- public byte[] findClass(String name) throws Exception {
- final String resourceName = name.replace('.', '/') + ".class";
- final InputStream is = this.ioProvider.getClassLoader().getResourceAsStream(resourceName);
- if (is != null) {
- try {
- byte[] buf = new byte[8192];
- ByteArrayOutputStream baos = new ByteArrayOutputStream(buf.length);
- int count;
- while ((count = is.read(buf, 0, buf.length)) > 0) {
- baos.write(buf, 0, count);
- }
- baos.flush();
- return baos.toByteArray();
- } finally {
- try {
- is.close();
- } catch (IOException ignore) {}
+ if ( fr != null ) {
+ try { fr.close(); } catch (IOException ignore) {}
}
+ throw e;
}
- return null;
}
/**
- * @see org.apache.sling.commons.compiler.CompilerEnvironment#cleanup()
+ * @see org.apache.sling.commons.compiler.CompilationUnit#getLastModified()
*/
- public void cleanup() {
- // EMPTY
- }
-
- /**
- * @see org.apache.sling.commons.compiler.ErrorHandler#onError(java.lang.String, java.lang.String, int, int)
- */
- public void onError(String msg, String sourceFile, int line, int position) {
- if ( errors == null ) {
- errors = new ArrayList<CompilerError>();
- }
- errors.add(new CompilerError(sourceFile, line, position, msg));
- }
-
- /**
- * @see org.apache.sling.commons.compiler.ErrorHandler#onWarning(java.lang.String, java.lang.String, int, int)
- */
- public void onWarning(String msg, String sourceFile, int line, int position) {
- // we ignore warnings
- }
-
- /**
- * @see org.apache.sling.commons.compiler.ClassWriter#write(java.lang.String, byte[])
- */
- public void write(String name, byte[] data) throws Exception {
- final OutputStream os = this.ioProvider.getOutputStream('/' + name.replace('.', '/') + ".class");
- os.write(data);
- os.close();
- }
-
- /** Return the list of errors. */
- public List<CompilerError> getErrors() throws IOException {
- return errors;
+ public long getLastModified() {
+ return this.ioProvider.lastModified(this.sourceFile);
}
}
diff --git a/src/main/java/org/apache/sling/scripting/java/impl/CompilerError.java b/src/main/java/org/apache/sling/scripting/java/impl/CompilerError.java
deleted file mode 100644
index 4f7dcb9..0000000
--- a/src/main/java/org/apache/sling/scripting/java/impl/CompilerError.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sling.scripting.java.impl;
-
-/**
- * This class encapsulates an error message produced by a programming language
- * processor (whether interpreted or compiled)
- */
-public class CompilerError {
-
- /**
- * The start line number of the offending program text
- */
- private final int startline;
-
- /**
- * The start column number of the offending program text
- */
- private final int startcolumn;
-
- /**
- * The name of the file containing the offending program text
- */
- private final String file;
-
- /**
- * The actual error text produced by the language processor
- */
- private final String message;
-
- /**
- * The error message constructor.
- *
- * @param file The name of the file containing the offending program text
- * @param startline The start line number of the offending program text
- * @param startcolumn The start column number of the offending program text
- * @param message The actual error text produced by the language processor
- */
- public CompilerError(final String file,
- final int startline,
- final int startcolumn,
- final String message) {
- this.file = file;
- this.startline = startline;
- this.startcolumn = startcolumn;
- this.message = message;
- }
-
- /**
- * Return the filename associated with this compiler error.
- *
- * @return The filename associated with this compiler error
- */
- public String getFile() {
- return file;
- }
-
- /**
- * Return the starting line number of the program text originating this error
- *
- * @return The starting line number of the program text originating this error
- */
- public int getStartLine() {
- return startline;
- }
-
- /**
- * Return the starting column number of the program text originating this
- * error
- *
- * @return The starting column number of the program text originating this
- * error
- */
- public int getStartColumn() {
- return startcolumn;
- }
-
- /**
- * Return the message produced by the language processor
- *
- * @return The message produced by the language processor
- */
- public String getMessage() {
- return message;
- }
-}
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 18ce68e..056373a 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
@@ -32,14 +32,16 @@
CompilerOptions opts = new CompilerOptions();
final Boolean classDebugInfo = (Boolean)props.get(JavaScriptEngineFactory.PROPERTY_CLASSDEBUGINFO);
- opts.setGenerateDebugInfo(classDebugInfo != null ? classDebugInfo : true);
+ opts.put(Options.KEY_GENERATE_DEBUG_INFO, classDebugInfo != null ? classDebugInfo : true);
final String sourceVM = (String) props.get(JavaScriptEngineFactory.PROPERTY_COMPILER_SOURCE_V_M);
- opts.setSourceVersion(sourceVM != null && sourceVM.length() > 0 ? sourceVM : JavaScriptEngineFactory.DEFAULT_VM_VERSION);
+ opts.put(Options.KEY_SOURCE_VERSION, sourceVM != null && sourceVM.length() > 0 ? sourceVM : JavaScriptEngineFactory.DEFAULT_VM_VERSION);
final String encoding = (String) props.get(JavaScriptEngineFactory.PROPERTY_ENCODING);
opts.encoding = encoding != null && encoding.length() > 0 ? encoding : "UTF-8";
+ opts.put(Options.KEY_IGNORE_WARNINGS, true);
+
return opts;
}
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 81e167f..3795897 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
@@ -41,8 +41,6 @@
import org.apache.sling.api.scripting.SlingScript;
import org.apache.sling.api.scripting.SlingScriptConstants;
import org.apache.sling.api.scripting.SlingScriptHelper;
-import org.apache.sling.commons.classloader.ClassLoaderWriter;
-import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
import org.apache.sling.commons.compiler.JavaCompiler;
import org.apache.sling.scripting.api.AbstractScriptEngineFactory;
import org.apache.sling.scripting.api.AbstractSlingScriptEngine;
@@ -79,24 +77,11 @@
/**
* @scr.reference
*/
- private DynamicClassLoaderManager dynamicClassLoaderManager;
-
- /**
- * @scr.reference
- */
private JavaCompiler javaCompiler;
- /**
- * The class loader
- */
- private ClassLoader javaClassLoader;
-
/** @scr.reference */
private ServletContext slingServletContext;
- /** @scr.reference */
- private ClassLoaderWriter classLoaderWriter;
-
private SlingIOProvider ioProvider;
private JavaServletContext javaServletContext;
@@ -141,9 +126,7 @@
*/
@SuppressWarnings("unchecked")
protected void activate(final ComponentContext componentContext) {
- this.ioProvider = new SlingIOProvider(this.classLoaderWriter,
- this.javaCompiler,
- this.javaClassLoader,
+ this.ioProvider = new SlingIOProvider(this.javaCompiler,
CompilerOptions.createOptions(componentContext.getProperties()));
this.javaServletContext = new JavaServletContext(ioProvider,
slingServletContext);
@@ -248,44 +231,6 @@
}
/**
- * Bind the class load provider.
- * @param repositoryClassLoaderProvider the new provider
- */
- protected void bindDynamicClassLoaderManager(DynamicClassLoaderManager rclp) {
- if ( this.javaClassLoader != null ) {
- this.ungetClassLoader();
- }
- this.getClassLoader(rclp);
- }
-
- /**
- * Unbind the class loader provider.
- * @param repositoryClassLoaderProvider the old provider
- */
- protected void unbindDynamicClassLoaderManager(DynamicClassLoaderManager rclp) {
- if ( this.dynamicClassLoaderManager == rclp ) {
- this.ungetClassLoader();
- }
- }
-
- /**
- * Get the class loader
- */
- private void getClassLoader(DynamicClassLoaderManager rclp) {
- this.dynamicClassLoaderManager = rclp;
- this.javaClassLoader = rclp.getDynamicClassLoader();
- }
-
- /**
- * Unget the class loader
- */
- private void ungetClassLoader() {
- this.dynamicClassLoaderManager = null;
- this.javaClassLoader = null;
- }
- // ---------- Internal -----------------------------------------------------
-
- /**
* @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
*/
public void handleEvent(Event event) {
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 536f4c5..ba38f94 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.FileNotFoundException;
import java.io.IOException;
import java.util.List;
@@ -29,7 +28,8 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.sling.commons.compiler.CompileUnit;
+import org.apache.sling.commons.compiler.CompilationResult;
+import org.apache.sling.commons.compiler.CompilerMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -77,23 +77,6 @@
}
/**
- * Get the servlet.
- * @throws ServletException
- * @throws IOException
- * @throws FileNotFoundException
- */
- private void getServlet()
- throws IllegalAccessException, InstantiationException, ClassNotFoundException, ServletException {
- destroy();
-
- this.servletClass = this.ioProvider.getClassLoader().loadClass(this.className);
- final Servlet servlet = (Servlet) servletClass.newInstance();
- servlet.init(config);
-
- theServlet = servlet;
- }
-
- /**
* Call the servlet.
* @param request The current request.
* @param response The current response.
@@ -122,12 +105,9 @@
synchronized (this) {
if (this.lastModificationTest == 0 ) {
try {
- if ( this.compile() || this.theServlet == null ) {
- // clear exception
- this.compileException = null;
- // (re)load the servlet class
- getServlet();
- }
+ // clear exception
+ this.compileException = null;
+ this.compile();
} catch (Exception ex) {
// store exception for futher access attempts
this.compileException = ex;
@@ -186,48 +166,38 @@
this.lastModificationTest = 0;
}
- /**
- * Check if the compiled class file is older than the source file
- */
- private boolean isOutDated() {
- if ( this.lastModificationTest > 0 ) {
- return false;
+ 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());
+
+ final List<CompilerMessage> errors = result.getErrors();
+ if ( errors != null && errors.size() > 0 ) {
+ throw CompilerException.create(errors);
}
- final long sourceLastModified = this.ioProvider.lastModified(this.sourcePath);
+ if ( result.didCompile() || this.theServlet == null ) {
+ destroy();
- final long targetLastModified = this.ioProvider.lastModified('/' + this.className.replace('.', '/') + ".class");
- if (targetLastModified < 0) {
- return true;
+ this.servletClass = result.loadCompiledClass(this.className);
+ final Servlet servlet = (Servlet) servletClass.newInstance();
+ servlet.init(config);
+
+ theServlet = servlet;
+
}
-
- return targetLastModified < sourceLastModified;
- }
-
- private boolean compile() throws Exception {
- if (this.isOutDated()) {
- final CompilationUnit unit = new CompilationUnit(this.sourcePath, className, ioProvider);
- this.ioProvider.getCompiler().compile(new CompileUnit[] {unit}, unit, unit, unit, ioProvider.getOptions());
-
- final List<CompilerError> errors = unit.getErrors();
- if ( errors != null && errors.size() > 0 ) {
- throw CompilerException.create(errors);
- }
- return true;
- }
- return false;
}
protected final static class CompilerException extends ServletException {
- public static CompilerException create(List<CompilerError> errors) {
+ public static CompilerException create(List<CompilerMessage> errors) {
final StringBuilder buffer = new StringBuilder();
buffer.append("Compilation errors:\n");
- for(final CompilerError e : errors) {
+ for(final CompilerMessage e : errors) {
buffer.append(e.getFile());
buffer.append(", line ");
- buffer.append(e.getStartLine());
+ buffer.append(e.getLine());
buffer.append(", column ");
- buffer.append(e.getStartColumn());
+ buffer.append(e.getColumn());
buffer.append(" : " );
buffer.append(e.getMessage());
buffer.append("\n");
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 836ac2e..fdba2e7 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
@@ -19,7 +19,6 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
@@ -30,7 +29,6 @@
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.classloader.ClassLoaderWriter;
import org.apache.sling.commons.compiler.JavaCompiler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,18 +43,11 @@
private ThreadLocal<ResourceResolver> requestResourceResolver;
- private final ClassLoaderWriter classLoaderWriter;
-
private final JavaCompiler compiler;
private final CompilerOptions options;
/**
- * Classloader
- */
- private final ClassLoader classLoader;
-
- /**
* Servlet cache.
*/
private final ServletCache servletCache = new ServletCache();
@@ -64,14 +55,10 @@
/**
* Constructor.
*/
- SlingIOProvider(final ClassLoaderWriter classLoaderWriter,
- final JavaCompiler compiler,
- final ClassLoader classLoader,
+ SlingIOProvider(final JavaCompiler compiler,
final CompilerOptions options) {
this.requestResourceResolver = new ThreadLocal<ResourceResolver>();
- this.classLoaderWriter = classLoaderWriter;
this.compiler = compiler;
- this.classLoader = classLoader;
this.options = options;
}
@@ -93,10 +80,6 @@
return this.compiler;
}
- public ClassLoader getClassLoader() {
- return this.classLoader;
- }
-
public CompilerOptions getOptions() {
return this.options;
}
@@ -113,12 +96,12 @@
public InputStream getInputStream(String fileName)
throws FileNotFoundException, IOException {
try {
- Resource resource = getResourceInternal(fileName);
+ final Resource resource = getResourceInternal(fileName);
if (resource == null) {
throw new FileNotFoundException("Cannot find " + fileName);
}
- InputStream stream = resource.adaptTo(InputStream.class);
+ final InputStream stream = resource.adaptTo(InputStream.class);
if (stream == null) {
throw new FileNotFoundException("Cannot find " + fileName);
}
@@ -138,14 +121,11 @@
* returned.
*/
public long lastModified(String fileName) {
- if ( fileName.endsWith(".class") ) {
- return this.classLoaderWriter.getLastModified(fileName);
- }
try {
- Resource resource = getResourceInternal(fileName);
+ final Resource resource = getResourceInternal(fileName);
if (resource != null) {
- ResourceMetadata meta = resource.getResourceMetadata();
- long modTime = meta.getModificationTime();
+ final ResourceMetadata meta = resource.getResourceMetadata();
+ final long modTime = meta.getModificationTime();
return (modTime > 0) ? modTime : 0;
}
@@ -157,13 +137,6 @@
return -1;
}
- /**
- * Returns an output stream to write to the repository.
- */
- public OutputStream getOutputStream(String fileName) {
- return this.classLoaderWriter.getOutputStream(fileName);
- }
-
public URL getURL(String path) throws MalformedURLException {
try {
final Resource resource = getResourceInternal(path);