This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.commons.compiler-2.0.4 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-compiler.git
commit 2e97b65052a61f938fe8e48ddea14cede3600a4e Author: Carsten Ziegeler <[email protected]> AuthorDate: Fri Mar 23 14:53:38 2012 +0000 SLING-2447 : ClassLoaderWriter should provide class loader for loading written classes/resources git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/commons/compiler@1304391 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 2 +- .../compiler/impl/CompilationResultImpl.java | 15 +- .../commons/compiler/impl/EclipseJavaCompiler.java | 64 ++------ .../commons/compiler/impl/IsolatedClassLoader.java | 162 +++++++++++++++++++++ .../commons/compiler/impl/CompilerJava5Test.java | 7 + 5 files changed, 188 insertions(+), 62 deletions(-) diff --git a/pom.xml b/pom.xml index b5752ee..1d68d32 100644 --- a/pom.xml +++ b/pom.xml @@ -94,7 +94,7 @@ <dependency> <groupId>org.apache.sling</groupId> <artifactId>org.apache.sling.commons.classloader</artifactId> - <version>1.1.0</version> + <version>1.2.5-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency> diff --git a/src/main/java/org/apache/sling/commons/compiler/impl/CompilationResultImpl.java b/src/main/java/org/apache/sling/commons/compiler/impl/CompilationResultImpl.java index 83baef6..5d878b2 100644 --- a/src/main/java/org/apache/sling/commons/compiler/impl/CompilationResultImpl.java +++ b/src/main/java/org/apache/sling/commons/compiler/impl/CompilationResultImpl.java @@ -19,6 +19,7 @@ package org.apache.sling.commons.compiler.impl; import java.util.ArrayList; import java.util.List; +import org.apache.sling.commons.classloader.ClassLoaderWriter; import org.apache.sling.commons.compiler.CompilationResult; import org.apache.sling.commons.compiler.CompilerMessage; @@ -35,25 +36,25 @@ public class CompilationResultImpl implements CompilationResult { private final boolean compilationRequired; - private final ClassLoader classLoader; + private final ClassLoaderWriter classLoaderWriter; public CompilationResultImpl(final String errorMessage) { this.ignoreWarnings = true; - this.classLoader = null; + this.classLoaderWriter = null; this.compilationRequired = false; this.onError(errorMessage, "<General>", 0, 0); } - public CompilationResultImpl(final ClassLoader classLoader) { + public CompilationResultImpl(final ClassLoaderWriter writer) { this.ignoreWarnings = true; - this.classLoader = classLoader; + this.classLoaderWriter = writer; this.compilationRequired = false; } public CompilationResultImpl(final boolean ignoreWarnings, - final ClassLoader classLoader) { + final ClassLoaderWriter writer) { this.ignoreWarnings = ignoreWarnings; - this.classLoader = classLoader; + this.classLoaderWriter = writer; this.compilationRequired = true; } @@ -79,7 +80,7 @@ public class CompilationResultImpl implements CompilationResult { if ( errors != null ) { throw new ClassNotFoundException(className); } - return this.classLoader.loadClass(className); + return this.classLoaderWriter.getClassLoader().loadClass(className); } /** diff --git a/src/main/java/org/apache/sling/commons/compiler/impl/EclipseJavaCompiler.java b/src/main/java/org/apache/sling/commons/compiler/impl/EclipseJavaCompiler.java index ddf9070..2d7b6d9 100644 --- a/src/main/java/org/apache/sling/commons/compiler/impl/EclipseJavaCompiler.java +++ b/src/main/java/org/apache/sling/commons/compiler/impl/EclipseJavaCompiler.java @@ -29,10 +29,8 @@ import java.util.Map; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferencePolicy; import org.apache.felix.scr.annotations.Service; import org.apache.sling.commons.classloader.ClassLoaderWriter; -import org.apache.sling.commons.classloader.DynamicClassLoaderManager; import org.apache.sling.commons.compiler.CompilationResult; import org.apache.sling.commons.compiler.CompilationUnit; import org.apache.sling.commons.compiler.JavaCompiler; @@ -65,14 +63,9 @@ public class EclipseJavaCompiler implements JavaCompiler { /** Logger instance */ private final Logger logger = LoggerFactory.getLogger(EclipseJavaCompiler.class); - @Reference(policy=ReferencePolicy.DYNAMIC) + @Reference private ClassLoaderWriter classLoaderWriter; - @Reference(policy=ReferencePolicy.DYNAMIC) - private DynamicClassLoaderManager dynamicClassLoaderManager; - - private ClassLoader classLoader; - /** the static problem factory */ private IProblemFactory problemFactory = new DefaultProblemFactory(Locale.getDefault()); @@ -80,52 +73,15 @@ public class EclipseJavaCompiler implements JavaCompiler { private final IErrorHandlingPolicy policy = DefaultErrorHandlingPolicies.proceedWithAllProblems(); /** - * Bind the class load provider. - * @param repositoryClassLoaderProvider the new provider - */ - protected void bindDynamicClassLoaderManager(final DynamicClassLoaderManager rclp) { - if ( this.classLoader != null ) { - this.ungetClassLoader(); - } - this.getClassLoader(rclp); - } - - /** - * Unbind the class loader provider. - * @param repositoryClassLoaderProvider the old provider - */ - protected void unbindDynamicClassLoaderManager(final DynamicClassLoaderManager rclp) { - if ( this.dynamicClassLoaderManager == rclp ) { - this.ungetClassLoader(); - } - } - - /** - * Get the commons dynamic class loader - */ - private void getClassLoader(final DynamicClassLoaderManager rclp) { - this.dynamicClassLoaderManager = rclp; - this.classLoader = rclp.getDynamicClassLoader(); - } - - /** - * Unget the commons dynamic class loader - */ - private void ungetClassLoader() { - this.classLoader = null; - this.dynamicClassLoaderManager = null; - } - - /** * Get the classloader for the compilation. */ - private ClassLoader getClassLoader(final Options options) { + private ClassLoader getClassLoader(final Options options, final ClassLoaderWriter classLoaderWriter) { final ClassLoader loader; if ( options.get(Options.KEY_CLASS_LOADER) != null ) { loader = (ClassLoader)options.get(Options.KEY_CLASS_LOADER); } else if ( options.get(Options.KEY_ADDITIONAL_CLASS_LOADER) != null ) { final ClassLoader additionalClassLoader = (ClassLoader)options.get(Options.KEY_ADDITIONAL_CLASS_LOADER); - loader = new ClassLoader(this.classLoader) { + loader = new ClassLoader(classLoaderWriter.getClassLoader()) { protected Class<?> findClass(String name) throws ClassNotFoundException { return additionalClassLoader.loadClass(name); @@ -136,7 +92,7 @@ public class EclipseJavaCompiler implements JavaCompiler { } }; } else { - loader = this.classLoader; + loader = classLoaderWriter.getClassLoader(); } return loader; } @@ -197,14 +153,14 @@ public class EclipseJavaCompiler implements JavaCompiler { final Options options = (compileOptions != null ? compileOptions : EMPTY_OPTIONS); // get classloader and classloader writer - final ClassLoader loader = this.getClassLoader(options); - if ( loader == null ) { - return new CompilationResultImpl("Class loader for compilation is not available."); - } final ClassLoaderWriter writer = this.getClassLoaderWriter(options); if ( writer == null ) { return new CompilationResultImpl("Class loader writer for compilation is not available."); } + final ClassLoader loader = this.getClassLoader(options, writer); + if ( loader == null ) { + return new CompilationResultImpl("Class loader for compilation is not available."); + } // check sources for compilation boolean needsCompilation = isForceCompilation(options); @@ -218,7 +174,7 @@ public class EclipseJavaCompiler implements JavaCompiler { } if ( !needsCompilation ) { logger.debug("All source files are recent - no compilation required."); - return new CompilationResultImpl(loader); + return new CompilationResultImpl(writer); } // delete old class files @@ -248,7 +204,7 @@ public class EclipseJavaCompiler implements JavaCompiler { logger.debug("Compiling with settings {}.", settings); // create the result - final CompilationResultImpl result = new CompilationResultImpl(isIgnoreWarnings(options), loader); + final CompilationResultImpl result = new CompilationResultImpl(isIgnoreWarnings(options), writer); // create the context final CompileContext context = new CompileContext(units, result, writer, loader); diff --git a/src/main/java/org/apache/sling/commons/compiler/impl/IsolatedClassLoader.java b/src/main/java/org/apache/sling/commons/compiler/impl/IsolatedClassLoader.java new file mode 100644 index 0000000..ace970a --- /dev/null +++ b/src/main/java/org/apache/sling/commons/compiler/impl/IsolatedClassLoader.java @@ -0,0 +1,162 @@ +/* + * 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.commons.compiler.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.AccessController; +import java.security.PrivilegedExceptionAction; +import java.security.SecureClassLoader; + +import org.apache.sling.commons.classloader.ClassLoaderWriter; + + +/** + * The <code>IsolatedClassLoader</code> class loads classes through + * the class loader writer + */ +public final class IsolatedClassLoader + extends SecureClassLoader { + + private final ClassLoaderWriter classLoaderWriter; + + public IsolatedClassLoader(final ClassLoader parent, + final ClassLoaderWriter classLoaderWriter) { + super(parent); + this.classLoaderWriter = classLoaderWriter; + } + + + //---------- Class loader overwrites ------------------------------------- + + /** + * Loads the class from this <code>ClassLoader</class>. If the + * class does not exist in this one, we check the parent. Please + * note that this is the exact opposite of the + * <code>ClassLoader</code> spec. We use it to work around + * inconsistent class loaders from third party vendors. + * + * @param name the name of the class + * @param resolve if <code>true</code> then resolve the class + * @return the resulting <code>Class</code> object + * @exception ClassNotFoundException if the class could not be found + */ + public final Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { + // First check if it's already loaded + Class<?> clazz = findLoadedClass(name); + + if (clazz == null) { + + try { + clazz = findClass(name); + } catch (final ClassNotFoundException cnfe) { + final ClassLoader parent = getParent(); + if (parent != null) { + // Ask to parent ClassLoader (can also throw a CNFE). + clazz = parent.loadClass(name); + } else { + // Propagate exception + throw cnfe; + } + } + } + + if (resolve) { + resolveClass(clazz); + } + + return clazz; + } + + /** + * Finds and loads the class with the specified name from the class path. + * + * @param name the name of the class + * @return the resulting class + * + * @throws ClassNotFoundException If the named class could not be found or + * if this class loader has already been destroyed. + */ + protected Class<?> findClass(final String name) throws ClassNotFoundException { + try { + return AccessController.doPrivileged( + new PrivilegedExceptionAction<Class<?>>() { + + public Class<?> run() throws ClassNotFoundException { + return findClassPrivileged(name); + } + }); + } catch (final java.security.PrivilegedActionException pae) { + throw (ClassNotFoundException) pae.getException(); + } + } + + /** + * Tries to find the class in the class path from within a + * <code>PrivilegedAction</code>. Throws <code>ClassNotFoundException</code> + * if no class can be found for the name. + * + * @param name the name of the class + * + * @return the resulting class + * + * @throws ClassNotFoundException if the class could not be found + * @throws NullPointerException If this class loader has already been + * destroyed. + */ + private Class<?> findClassPrivileged(final String name) throws ClassNotFoundException { + // prepare the name of the class + final String path = "/" + name.replace('.', '/') + ".class"; + InputStream is = null; + try { + is = this.classLoaderWriter.getInputStream(path); + final Class<?> c = defineClass(name, is); + if (c == null) { + throw new ClassNotFoundException(name); + } + return c; + } catch ( final ClassNotFoundException cnfe) { + throw cnfe; + } catch (final Throwable t) { + throw new ClassNotFoundException(name, t); + } + } + + /** + * Defines a class getting the bytes for the class from the resource + * + * @param name The fully qualified class name + * @param is The resource to obtain the class bytes from + * + * @throws IOException If a problem occurrs reading the class bytes from + * the resource. + * @throws ClassFormatError If the class bytes read from the resource are + * not a valid class. + */ + private Class<?> defineClass(final String name, final InputStream is) + throws IOException { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final byte[] buffer = new byte[2048]; + int l; + while ( ( l = is.read(buffer)) >= 0 ) { + baos.write(buffer, 0, l); + } + final byte[] data = baos.toByteArray(); + return defineClass(name, data, 0, data.length); + } +} diff --git a/src/test/java/org/apache/sling/commons/compiler/impl/CompilerJava5Test.java b/src/test/java/org/apache/sling/commons/compiler/impl/CompilerJava5Test.java index c409ca0..ac5f0b5 100644 --- a/src/test/java/org/apache/sling/commons/compiler/impl/CompilerJava5Test.java +++ b/src/test/java/org/apache/sling/commons/compiler/impl/CompilerJava5Test.java @@ -113,4 +113,11 @@ public class CompilerJava5Test extends TestCase public boolean rename(String oldPath, String newPath) { return false; } + + /** + * @see org.apache.sling.commons.classloader.ClassLoaderWriter#getClassLoader() + */ + public ClassLoader getClassLoader() { + return null; + } } -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
