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 09:20:57 UTC

[sling-org-apache-sling-commons-compiler] 05/09: SLING-2447 : ClassLoaderWriter should provide class loader for loading written classes/resources

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 <cz...@apache.org>
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
"commits@sling.apache.org" <co...@sling.apache.org>.