Applied patch (FELIX-95).


git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@423869 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/Activator.java b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/Activator.java
index f87aaa7..70ba2af 100644
--- a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/Activator.java
+++ b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/Activator.java
@@ -80,7 +80,7 @@
      */
     public void addComponentFactory(Element cm) {
     	// Create the factory :
-    	ComponentManagerFactory factory = new ComponentManagerFactory(this, cm);
+    	ComponentManagerFactory factory = new ComponentManagerFactory(m_bundleContext, cm);
 
     	// If the factory array is not empty add the new factory at the end
         if (m_factories.length != 0) {
diff --git a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManager.java b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManager.java
index d979220..3a3feae 100644
--- a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManager.java
+++ b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManager.java
@@ -132,7 +132,6 @@
 				// It is not an internal handler, try to load it
 				try {
 					Class c = m_context.getBundle().loadClass(cm.getNamespaces()[i]);
-					//Class c = Class.forName(cm.getNamespaces()[i]);
 					Handler h = (Handler) c.newInstance();
 					h.configure(this, cm);
 				} catch (ClassNotFoundException e) {
@@ -241,8 +240,8 @@
 	 */
 	private void load() {
         try {
-        	m_clazz = m_factory.getBundleContext().getBundle().loadClass(m_metadata.getClassName());
-        } catch (Exception  e) {
+        	m_clazz = m_factory.loadClass(m_metadata.getClassName());
+        } catch (ClassNotFoundException  e) {
             Activator.getLogger().log(Level.SEVERE, "[" + m_metadata.getClassName() + "] Class not found during the loading phase : " + e.getMessage());
             return;
         }
diff --git a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManagerFactory.java b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManagerFactory.java
index 646db1d..bf8eade 100644
--- a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManagerFactory.java
+++ b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManagerFactory.java
@@ -16,6 +16,10 @@
  */
 package org.apache.felix.ipojo;
 
+import java.io.IOException;
+import java.net.URL;
+import java.security.ProtectionDomain;
+import java.util.Enumeration;
 import java.util.logging.Level;
 
 import org.apache.felix.ipojo.metadata.Element;
@@ -38,8 +42,77 @@
 	 */
 	private BundleContext m_bundleContext = null;
 
+	/**
+	 * Component class.
+	 */
+	private byte[] m_clazz = null;
+
+	/**
+	 * Component Class Name.
+	 */
+	private String m_componentClassName = null;
+
+	/**
+	 * Classloader to delegate loading.
+	 */
+	private FactoryClassloader m_classLoader = null;
+
 	//End field
 
+	/**
+	 * FactoryClassloader.
+	 */
+	private class FactoryClassloader extends ClassLoader {
+
+	    /**
+	     * load the class.
+	     * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
+	     * @param name : the name of the class
+	     * @param resolve : should be the class resolve now ?
+	     * @return : the loaded class
+	     * @throws ClassNotFoundException : the class to load is not found
+	     */
+	    protected synchronized Class loadClass(final String name,
+	            final boolean resolve) throws ClassNotFoundException {
+	       return m_bundleContext.getBundle().loadClass(name);
+	    }
+
+
+	    /**
+	     * Return the URL of the asked ressource.
+	     * @param arg : the name of the resource to find.
+	     * @return the URL of the resource.
+	     * @see java.lang.ClassLoader#getResource(java.lang.String)
+	     */
+	    public URL getResource(String arg) {
+	        return m_bundleContext.getBundle().getResource(arg);
+	    }
+
+	    /**
+	     * .
+	     * @param arg : resource to find
+	     * @return : the enumeration found
+	     * @throws IOException : if the lookup failed.
+	     * @see java.lang.ClassLoader#getResources(java.lang.String)
+	     */
+	    public Enumeration getRessources(String arg) throws IOException {
+	        return m_bundleContext.getBundle().getResources(arg);
+	    }
+
+	    /**
+	     * The defineClass method.
+	     * @param name : name of the class
+	     * @param b : the byte array of the class
+	     * @param domain : the protection domain
+	     * @return : the defined class.
+	     * @throws Exception : if a problem is detected during the loading
+	     */
+	    public Class defineClass(String name, byte[] b,
+	            ProtectionDomain domain) throws Exception {
+	    	return super.defineClass(name, b, 0, b.length, domain);
+	    }
+	}
+
 	// Field accessors
 
 	 /**
@@ -93,16 +166,6 @@
 	// End field accessors
 
 	/**
-	 * Constructor of a ComponentManagerFactory from a component metadata.
-	 * This contructor is use when the iPOJO Activator is used.
-	 * @param cm : Component Metadata for the component factory
-	 */
-	protected ComponentManagerFactory(Activator activator, Element cm) {
-		m_bundleContext = activator.getBundleContext();
-		createComponentManager(cm);
-	}
-
-	/**
 	 * Create a component manager factory and create a component manager with the given medatada.
 	 * @param bc : bundle context
 	 * @param cm : metadata of the component to create
@@ -110,6 +173,20 @@
 	public ComponentManagerFactory(BundleContext bc, Element cm) {
 		m_bundleContext = bc;
 		createComponentManager(cm);
+		m_componentClassName = cm.getAttribute("className");
+	}
+
+	/**
+	 * Create a component manager factory and create a component manager with the given medatada.
+	 * @param bc : bundle context
+	 * @param clazz : the component class
+	 * @param cm : metadata of the component
+	 */
+	public ComponentManagerFactory(BundleContext bc, byte[] clazz, Element cm) {
+		m_bundleContext = bc;
+		m_clazz = clazz;
+		m_componentClassName = cm.getAttribute("className");
+		createComponentManager(cm);
 	}
 
 	/**
@@ -156,4 +233,38 @@
 		}
 	}
 
+	/**
+	 * Load a class.
+	 * @param className : name of the class to load
+	 * @return the resulting Class object
+	 * @throws ClassNotFoundException : happen when the class is not found
+	 */
+	public Class loadClass(String className) throws ClassNotFoundException {
+		Activator.getLogger().log(Level.INFO, "[Bundle " + m_bundleContext.getBundle().getBundleId() + "] In load for : " + className);
+		if (m_clazz != null && className.equals(m_componentClassName)) {
+			if (m_classLoader == null) {
+				Activator.getLogger().log(Level.INFO, "[Bundle " + m_bundleContext.getBundle().getBundleId() + "] Create the FactoryClassLoader for : " + className);
+				m_classLoader = new FactoryClassloader();
+				}
+			try {
+				Class c = m_classLoader.defineClass(m_componentClassName, m_clazz, null);
+				Activator.getLogger().log(Level.INFO, "[Bundle " + m_bundleContext.getBundle().getBundleId() + "] Return " + c + " for " + className);
+				return c;
+			} catch (Exception e) {
+				Activator.getLogger().log(Level.SEVERE, "[Bundle " + m_bundleContext.getBundle().getBundleId() + "] Cannot define the class : " + className);
+				return null;
+			}
+		}
+		return m_bundleContext.getBundle().loadClass(className);
+	}
+
+	/**
+	 * Return the URL of a resource.
+	 * @param resName : resource name
+	 * @return the URL of the resource
+	 */
+	public URL getResource(String resName) {
+		return m_bundleContext.getBundle().getResource(resName);
+	}
+
 }