You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2014/05/06 17:01:03 UTC

svn commit: r1592768 - in /felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator: ManipulationEngine.java Pojoization.java util/Classpath.java util/IsolatedClassLoader.java

Author: clement
Date: Tue May  6 15:01:02 2014
New Revision: 1592768

URL: http://svn.apache.org/r1592768
Log:
Provides utility classes to create the classloader used by the manipulator to compute frames, and add a classloader parameter to the pojoization methods. (FELIX-4509).

Added:
    felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/Classpath.java
    felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/IsolatedClassLoader.java
Modified:
    felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/ManipulationEngine.java
    felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java

Modified: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/ManipulationEngine.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/ManipulationEngine.java?rev=1592768&r1=1592767&r2=1592768&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/ManipulationEngine.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/ManipulationEngine.java Tue May  6 15:01:02 2014
@@ -34,6 +34,10 @@ import java.util.List;
 public class ManipulationEngine {
 
     /**
+     * The classloader given to the manipulator to load classes.
+     */
+    private final ClassLoader m_classLoader;
+    /**
      * List of component types.
      */
     private List<ManipulationUnit> m_manipulationUnits = new ArrayList<ManipulationUnit>();
@@ -53,6 +57,10 @@ public class ManipulationEngine {
      */
     private ManipulationVisitor m_manipulationVisitor;
 
+    public ManipulationEngine(ClassLoader classLoader) {
+        m_classLoader = classLoader;
+    }
+
     /**
      * Add information related to a discovered component that will be manipulated.
      * @param component additional component
@@ -106,7 +114,7 @@ public class ManipulationEngine {
                 // Should always be the case
 
                 // Manipulation preparation
-                Manipulator manipulator = new Manipulator();
+                Manipulator manipulator = new Manipulator(m_classLoader);
                 try {
                     manipulator.prepare(bytecode);
                 } catch (IOException e) {

Modified: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java?rev=1592768&r1=1592767&r2=1592768&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java Tue May  6 15:01:02 2014
@@ -19,22 +19,11 @@
 
 package org.apache.felix.ipojo.manipulator;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-import java.util.jar.JarFile;
-
 import org.apache.felix.ipojo.manipulator.manifest.FileManifestProvider;
-import org.apache.felix.ipojo.manipulator.metadata.AnnotationMetadataProvider;
-import org.apache.felix.ipojo.manipulator.metadata.CompositeMetadataProvider;
-import org.apache.felix.ipojo.manipulator.metadata.EmptyMetadataProvider;
-import org.apache.felix.ipojo.manipulator.metadata.FileMetadataProvider;
-import org.apache.felix.ipojo.manipulator.metadata.StreamMetadataProvider;
+import org.apache.felix.ipojo.manipulator.metadata.*;
 import org.apache.felix.ipojo.manipulator.render.MetadataRenderer;
 import org.apache.felix.ipojo.manipulator.reporter.SystemReporter;
 import org.apache.felix.ipojo.manipulator.spi.ModuleProvider;
-import org.apache.felix.ipojo.manipulator.spi.provider.CoreModuleProvider;
 import org.apache.felix.ipojo.manipulator.spi.provider.ServiceLoaderModuleProvider;
 import org.apache.felix.ipojo.manipulator.store.DirectoryResourceStore;
 import org.apache.felix.ipojo.manipulator.store.JarFileResourceStore;
@@ -48,8 +37,15 @@ import org.apache.felix.ipojo.manipulato
 import org.apache.felix.ipojo.metadata.Element;
 import org.apache.felix.ipojo.xml.parser.SchemaResolver;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.jar.JarFile;
+
 /**
  * Pojoization allows creating an iPOJO bundle from a "normal" bundle.
+ *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class Pojoization {
@@ -123,16 +119,34 @@ public class Pojoization {
         return m_reporter.getWarnings();
     }
 
-
     /**
      * Manipulates an input bundle.
      * This method creates an iPOJO bundle based on the given metadata file.
      * The original and final bundles must be different.
-     * @param in the original bundle.
-     * @param out the final bundle.
+     * <p/>
+     * This method does not use the classloader parameter, and use the classloader having loaded the
+     * {@link org.apache.felix.ipojo.manipulator.Pojoization} class. It's definitely not recommended.
+     *
+     * @param in       the original bundle.
+     * @param out      the final bundle.
      * @param metadata the iPOJO metadata input stream.
+     * @deprecated
      */
     public void pojoization(File in, File out, InputStream metadata) {
+        pojoization(in, out, metadata, this.getClass().getClassLoader());
+    }
+
+    /**
+     * Manipulates an input bundle.
+     * This method creates an iPOJO bundle based on the given metadata file.
+     * The original and final bundles must be different.
+     *
+     * @param in       the original bundle.
+     * @param out      the final bundle.
+     * @param metadata the iPOJO metadata input stream.
+     * @param loader   the classloader used to compute the bytecode frames.
+     */
+    public void pojoization(File in, File out, InputStream metadata, ClassLoader loader) {
         StreamMetadataProvider provider = new StreamMetadataProvider(metadata, m_reporter);
         provider.setValidateUsingLocalSchemas(m_useLocalXSD);
 
@@ -156,7 +170,7 @@ public class Pojoization {
 
         ManipulationVisitor visitor = createDefaultVisitorChain(store);
 
-        pojoization(store, provider, visitor);
+        pojoization(store, provider, visitor, loader);
     }
 
     private ManipulationVisitor createDefaultVisitorChain(ResourceStore store) {
@@ -173,11 +187,30 @@ public class Pojoization {
      * Manipulates an input bundle.
      * This method creates an iPOJO bundle based on the given metadata file.
      * The original and final bundles must be different.
-     * @param in the original bundle.
-     * @param out the final bundle.
+     * <p/>
+     * This method does not use the classloader parameter, and use the classloader having loaded the
+     * {@link org.apache.felix.ipojo.manipulator.Pojoization} class. It's definitely not recommended.
+     *
+     * @param in           the original bundle.
+     * @param out          the final bundle.
      * @param metadataFile the iPOJO metadata file (XML).
+     * @deprecated
      */
     public void pojoization(File in, File out, File metadataFile) {
+        pojoization(in, out, metadataFile, this.getClass().getClassLoader());
+    }
+
+    /**
+     * Manipulates an input bundle.
+     * This method creates an iPOJO bundle based on the given metadata file.
+     * The original and final bundles must be different.
+     *
+     * @param in           the original bundle.
+     * @param out          the final bundle.
+     * @param metadataFile the iPOJO metadata file (XML).
+     * @param loader       the classloader used to compute the bytecode frames.
+     */
+    public void pojoization(File in, File out, File metadataFile, ClassLoader loader) {
         MetadataProvider provider = new EmptyMetadataProvider();
         if (metadataFile != null) {
             FileMetadataProvider fileMetadataProvider = new FileMetadataProvider(metadataFile, m_reporter);
@@ -205,18 +238,37 @@ public class Pojoization {
 
         ManipulationVisitor visitor = createDefaultVisitorChain(store);
 
-        pojoization(store, provider, visitor);
+        pojoization(store, provider, visitor, loader);
     }
 
     /**
      * Manipulates an expanded bundles.
      * Classes are in the specified directory.
      * this method allows to update a customized manifest.
-     * @param directory the directory containing classes
+     * <p/>
+     * This method does not use the classloader parameter, and use the classloader having loaded the
+     * {@link org.apache.felix.ipojo.manipulator.Pojoization} class. It's definitely not recommended.
+     *
+     * @param directory    the directory containing classes
      * @param metadataFile the metadata file
      * @param manifestFile the manifest file. <code>null</code> to use directory/META-INF/MANIFEST.mf
+     * @deprecated
      */
     public void directoryPojoization(File directory, File metadataFile, File manifestFile) {
+        directoryPojoization(directory, metadataFile, manifestFile, this.getClass().getClassLoader());
+    }
+
+    /**
+     * Manipulates an expanded bundles.
+     * Classes are in the specified directory.
+     * this method allows to update a customized manifest.
+     *
+     * @param directory    the directory containing classes
+     * @param metadataFile the metadata file
+     * @param manifestFile the manifest file. <code>null</code> to use directory/META-INF/MANIFEST.mf
+     * @param loader       the classloader used to compute the bytecode frames.
+     */
+    public void directoryPojoization(File directory, File metadataFile, File manifestFile, ClassLoader loader) {
         // Get the metadata.xml location if not null
         MetadataProvider provider = new EmptyMetadataProvider();
         if (metadataFile != null) {
@@ -278,15 +330,15 @@ public class Pojoization {
 
         ManipulationVisitor visitor = createDefaultVisitorChain(store);
 
-        pojoization(store, provider, visitor);
+        pojoization(store, provider, visitor, loader);
 
     }
 
     public void pojoization(final ResourceStore store,
                             final MetadataProvider metadata,
-                            final ManipulationVisitor visitor) {
+                            final ManipulationVisitor visitor, ClassLoader loader) {
 
-        ManipulationEngine engine = new ManipulationEngine();
+        ManipulationEngine engine = new ManipulationEngine(loader);
         engine.setResourceStore(store);
         engine.setReporter(m_reporter);
         engine.setManipulationVisitor(visitor);

Added: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/Classpath.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/Classpath.java?rev=1592768&view=auto
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/Classpath.java (added)
+++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/Classpath.java Tue May  6 15:01:02 2014
@@ -0,0 +1,180 @@
+/*
+ * 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.felix.ipojo.manipulator.util;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * An ordered list of classpath elements with set behaviour. A Classpath is immutable and thread safe.
+ * This class let retrieve an isolated classloader to load classes from a set of jars.
+ */
+public class Classpath implements Iterable<String> {
+
+    private final List<String> unmodifiableElements;
+
+    public static Classpath join(Classpath firstClasspath, Classpath secondClasspath) {
+        LinkedHashSet<String> accumulated = new LinkedHashSet<String>();
+        if (firstClasspath != null) firstClasspath.addTo(accumulated);
+        if (secondClasspath != null) secondClasspath.addTo(accumulated);
+        return new Classpath(accumulated);
+    }
+
+
+    private void addTo(Collection<String> c) {
+        c.addAll(unmodifiableElements);
+    }
+
+    private Classpath() {
+        this.unmodifiableElements = Collections.emptyList();
+    }
+
+
+    public Classpath(Classpath other, String additionalElement) {
+        ArrayList<String> elems = new ArrayList<String>(other.unmodifiableElements);
+        elems.add(additionalElement);
+        this.unmodifiableElements = Collections.unmodifiableList(elems);
+    }
+
+    public Classpath(Iterable<String> paths) {
+        List<String> newCp = new ArrayList<String>();
+        for (String element : paths) {
+            newCp.add(element);
+        }
+        this.unmodifiableElements = Collections.unmodifiableList(newCp);
+    }
+
+    public static Classpath emptyClasspath() {
+        return new Classpath();
+    }
+
+    public Classpath addClassPathElementUrl(String path) {
+        if (path == null) {
+            throw new IllegalArgumentException("Null is not a valid class path element url.");
+        }
+        return !unmodifiableElements.contains(path) ? new Classpath(this, path) : this;
+    }
+
+    public List<String> getClassPath() {
+        return unmodifiableElements;
+    }
+
+    public List<URL> getAsUrlList()
+            throws MalformedURLException {
+        List<URL> urls = new ArrayList<URL>();
+        for (String path : unmodifiableElements) {
+            File f = new File(path);
+            urls.add(f.toURI().toURL());
+        }
+        return urls;
+    }
+
+    public void writeToSystemProperty(String propertyName) {
+        StringBuilder sb = new StringBuilder();
+        for (String element : unmodifiableElements) {
+            sb.append(element).append(File.pathSeparatorChar);
+        }
+        System.setProperty(propertyName, sb.toString());
+    }
+
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        Classpath classpath = (Classpath) o;
+
+        return !(unmodifiableElements
+                != null ? !unmodifiableElements.equals(classpath.unmodifiableElements) : classpath.unmodifiableElements != null);
+
+    }
+
+    public ClassLoader createClassLoader(ClassLoader parent, boolean childDelegation)
+            throws RuntimeException {
+        try {
+            List urls = getAsUrlList();
+            IsolatedClassLoader classLoader = new IsolatedClassLoader(parent, childDelegation);
+            for (Object url1 : urls) {
+                URL url = (URL) url1;
+                classLoader.addURL(url);
+            }
+            return classLoader;
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("When creating classloader", e);
+        }
+    }
+
+    public ClassLoader createClassLoader()
+            throws RuntimeException {
+        try {
+            List urls = getAsUrlList();
+            IsolatedClassLoader classLoader = new IsolatedClassLoader();
+            for (Object url1 : urls) {
+                URL url = (URL) url1;
+                classLoader.addURL(url);
+            }
+            return classLoader;
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("When creating classloader", e);
+        }
+    }
+
+
+    public int hashCode() {
+        return unmodifiableElements != null ? unmodifiableElements.hashCode() : 0;
+    }
+
+    public String getLogMessage(String descriptor) {
+        StringBuilder result = new StringBuilder();
+        result.append(descriptor).append(" classpath:");
+        for (String element : unmodifiableElements) {
+            result.append("  ").append(element);
+        }
+        return result.toString();
+    }
+
+    public String getCompactLogMessage(String descriptor) {
+        StringBuilder result = new StringBuilder();
+        result.append(descriptor).append(" classpath:");
+        for (String element : unmodifiableElements) {
+            result.append("  ");
+            if (element != null) {
+                int pos = element.lastIndexOf(File.separatorChar);
+                if (pos >= 0) {
+                    result.append(element.substring(pos + 1));
+                } else {
+                    result.append(element);
+                }
+
+            } else {
+                result.append(element);
+            }
+        }
+        return result.toString();
+    }
+
+    public Iterator<String> iterator() {
+        return unmodifiableElements.iterator();
+    }
+}

Added: felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/IsolatedClassLoader.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/IsolatedClassLoader.java?rev=1592768&view=auto
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/IsolatedClassLoader.java (added)
+++ felix/trunk/ipojo/manipulator/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/util/IsolatedClassLoader.java Tue May  6 15:01:02 2014
@@ -0,0 +1,85 @@
+/*
+ * 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.felix.ipojo.manipulator.util;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A classloader used by the {@link org.apache.felix.ipojo.manipulator.util.Classpath}.
+ */
+public class IsolatedClassLoader
+        extends URLClassLoader {
+    private final ClassLoader parent = ClassLoader.getSystemClassLoader();
+
+    private final Set<URL> urls = new HashSet<URL>();
+
+    private boolean childDelegation = true;
+
+    private static final URL[] EMPTY_URL_ARRAY = new URL[0];
+
+    public IsolatedClassLoader(ClassLoader parent, boolean childDelegation) {
+        super(EMPTY_URL_ARRAY, parent);
+        this.childDelegation = childDelegation;
+    }
+
+    public IsolatedClassLoader() {
+        super(EMPTY_URL_ARRAY, ClassLoader.getSystemClassLoader());
+        this.childDelegation  = true;
+    }
+
+    public void addURL(URL url) {
+        // avoid duplicates
+        if (!urls.contains(url)) {
+            super.addURL(url);
+            urls.add(url);
+        }
+    }
+
+    public synchronized Class loadClass(String name)
+            throws ClassNotFoundException {
+        Class c;
+        if (childDelegation) {
+            c = findLoadedClass(name);
+
+            ClassNotFoundException ex = null;
+
+            if (c == null) {
+                try {
+                    c = findClass(name);
+                } catch (ClassNotFoundException e) {
+                    ex = e;
+                    if (parent != null) {
+                        c = parent.loadClass(name);
+                    }
+                }
+            }
+
+            if (c == null) {
+                throw ex;
+            }
+        } else {
+            c = super.loadClass(name);
+        }
+
+        return c;
+    }
+}