Instances can now customize their requirement filters (both on primitive and composite components)
Remove equals method invocation form the generated bytecode (use '==' instead)
Allow dependency callbacks to invoke parent classes methods.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@581147 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
index 6982b32..527d195 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
@@ -19,7 +19,6 @@
 package org.apache.felix.ipojo;
 
 import java.net.URL;
-import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Dictionary;
@@ -113,11 +112,6 @@
      * Component Type Name.
      */
     protected String m_typeName = null;
-
-    /**
-     * Class loader to delegate loading.
-     */
-    private FactoryClassloader m_classLoader = null;
     
     /**
      * Component Implementation class.
@@ -303,21 +297,6 @@
         instance.start();
         return instance;
     }
-
-    /**
-     * Define a class.
-     * @param name : qualified name of the class
-     * @param b : byte array of the class
-     * @param domain : protection domain of the class
-     * @return the defined class object
-     * @throws Exception : an exception occur during the definition
-     */
-    public Class defineClass(String name, byte[] b, ProtectionDomain domain) throws Exception {
-        if (m_classLoader == null) {
-            m_classLoader = new FactoryClassloader();
-        }
-        return m_classLoader.defineClass(name, b, domain);
-    }
     
     /**
      * Delete an instance.
@@ -437,20 +416,22 @@
      * Load a class.
      * @param className : name of the class to load
      * @return the resulting Class object
+     * @throws ClassNotFoundException 
      * @throws ClassNotFoundException : happen when the class is not found
      */
     public Class loadClass(String className) throws ClassNotFoundException {
-        if (m_clazz != null && className.equals(m_componentClassName)) {
-            // Used the factory classloader to load the component implementation
-            // class
-            if (m_classLoader == null) {
-                m_classLoader = new FactoryClassloader();
-            }
-            try {
-                return m_classLoader.defineClass(m_componentClassName, m_clazz, null);
-            } catch (Exception e) {
-                throw new ClassNotFoundException("[Bundle " + m_context.getBundle().getBundleId() + "] Cannot define the class : " + className, e);
-            }
+        if (m_clazz != null) {
+            // Used the factory classloader to load the component implementation class
+            ClassLoader cl = new ClassLoader() {
+                public Class loadClass(String name) throws ClassNotFoundException {
+                    if (name.equals(m_componentClassName)) {
+                        return defineClass(name, m_clazz, 0, m_clazz.length, null);
+                    } else {
+                        return m_context.getBundle().loadClass(name);
+                    }
+                }
+            };
+            return cl.loadClass(m_componentClassName);
         }
         return m_context.getBundle().loadClass(className);
     }
@@ -585,7 +566,6 @@
         
         m_tracker = null;
         m_componentDesc = null;
-        m_classLoader = null;
         m_clazz = null;
         m_state = INVALID;
     }
@@ -1005,55 +985,21 @@
         }
     }
 
-    /**
-     * FactoryClassloader.
-     */
-    private class FactoryClassloader extends ClassLoader {
-
-        /**
-         * Map of defined classes [Name, Class Object].
-         */
-        private Map m_definedClasses = new HashMap();
-
-        /**
-         * 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 {
-            if (m_definedClasses.containsKey(name)) {
-                return (Class) m_definedClasses.get(name);
-            }
-            final Class c = super.defineClass(name, b, 0, b.length, domain);
-            m_definedClasses.put(name, c);
-            return c;
-        }
-
-        /**
-         * Return the URL of the asked resource.
-         * 
-         * @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_context.getBundle().getResource(arg);
-        }
-
-        /**
-         * 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 Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
-            return m_context.getBundle().loadClass(name);
-        }
-    }
+//    /**
+//     * FactoryClassloader.
+//     */
+//    private class FactoryClassloader extends ClassLoader {
+//        /**
+//         * 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);
+//        }
+//    }
 }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
index 6c756e3..aeb4c0f 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
@@ -71,7 +71,7 @@
      * @param event : the bundle event.

      * @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent)

      */

-    public void bundleChanged(BundleEvent event) {

+    public synchronized void bundleChanged(BundleEvent event) {

         if (event.getBundle().getBundleId() == m_bundleId) {

             return;

         }

@@ -147,7 +147,7 @@
         start(bundle, parser.getInstances());

     }

 

-    /** 

+    /**

      * iPOJO Starting method.

      * @param bc : iPOJO bundle context.

      * @throws Exception : the start method failed.

@@ -158,22 +158,20 @@
         m_bundleId = bc.getBundle().getBundleId();

         m_components = new Hashtable();

         m_creators = new Hashtable();

-        

+

         // Begin by initializing core handlers

         startManagementFor(bc.getBundle());

-        

-        synchronized (m_components) {

-            synchronized (m_creators) {

-                for (int i = 0; i < bc.getBundles().length; i++) {

-                    if (bc.getBundles()[i].getState() == Bundle.ACTIVE) {

-                        startManagementFor(bc.getBundles()[i]);

-                    }

+

+        synchronized (this) {

+            // listen to any changes in bundles.

+            m_context.addBundleListener(this);

+            // compute already started bundles.

+            for (int i = 0; i < bc.getBundles().length; i++) {

+                if (bc.getBundles()[i].getState() == Bundle.ACTIVE) {

+                    startManagementFor(bc.getBundles()[i]);

                 }

             }

         }

-

-        // listen to any changes in bundles

-        m_context.addBundleListener(this);

     }

 

     /**

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
index 982aacc..ab1d6ab 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
@@ -389,14 +389,6 @@
     }
 
     /**
-     * Is the implementation class loaded?
-     * @return true if the class is loaded
-     */
-    private boolean isLoaded() {
-        return m_clazz != null;
-    }
-
-    /**
      * Add an instance to the created instance list.
      * @param o : the instance to add
      */
@@ -462,7 +454,7 @@
      */
     public Object createPojoObject() {
 
-        if (!isLoaded()) {
+        if (m_clazz == null) {
             load();
         }
         Object instance = null;
@@ -528,7 +520,7 @@
      * @return the manipulated class
      */
     public Class getClazz() {
-        if (!isLoaded()) {
+        if (m_clazz == null) {
             load();
         }
         return m_clazz;
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ImportHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ImportHandler.java
index 04c5da1..c9b26bf 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ImportHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ImportHandler.java
@@ -75,6 +75,12 @@
         m_scope = getCompositeManager().getServiceContext();
 
         Element[] imp = metadata.getElements("requires");
+        
+        // Get instance filters
+        Dictionary filtersConfiguration = null;
+        if (conf.get("requires.filters") != null) {
+            filtersConfiguration = (Dictionary) conf.get("requires.filters");
+        }
 
         for (int i = 0; i < imp.length; i++) {
             boolean optional = false;
@@ -111,6 +117,12 @@
                         scopePolicy = PolicyServiceContext.LOCAL_AND_GLOBAL;
                     }                
                 }
+                
+                // Configure instance filter if available
+                if (filtersConfiguration != null && id != null && filtersConfiguration.get(id) != null) {
+                    filter = (String) filtersConfiguration.get(id);
+                }
+                
                 ServiceImporter si = new ServiceImporter(specification, filter, aggregate, optional, m_context, m_scope, scopePolicy, id, this);
                 m_importers.add(si);
             } else { // Malformed import
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
index 56a64b9..e573d4a 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/ProvidedServiceHandler.java
@@ -22,6 +22,7 @@
 import java.util.ArrayList;
 import java.util.Dictionary;
 import java.util.List;
+import java.util.Properties;
 
 import org.apache.felix.ipojo.ComponentInstance;
 import org.apache.felix.ipojo.CompositeHandler;
@@ -219,7 +220,7 @@
      */
     private void checkServiceSpecification(ProvidedService ps) throws CompositionException {
         try {
-            Class spec = getCompositeManager().getFactory().loadClass(ps.getSpecification());
+            Class spec = m_context.getBundle().loadClass(ps.getSpecification());
             Field specField = spec.getField("specification");
             Object o = specField.get(null);
             if (o instanceof String) {
@@ -313,7 +314,7 @@
                 }
                 // Add the required handler 
                 try {
-                    ci.init(getCompositeManager(), new Element("composite", ""), null);
+                    ci.init(getCompositeManager(), new Element("composite", ""), new Properties());
                 } catch (ConfigurationException e) {
                     log(Logger.ERROR, "Internal error : cannot configure the Import Handler : " + e.getMessage());
                     throw new CompositionException("Internal error : cannot configure the Import Handler : " + e.getMessage());
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java
index 70540cd..ef62ef7 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyCallback.java
@@ -19,9 +19,10 @@
 package org.apache.felix.ipojo.handlers.dependency;
 
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 
-import org.apache.felix.ipojo.InstanceManager;
 import org.apache.felix.ipojo.util.Callback;
+import org.apache.felix.ipojo.util.Logger;
 import org.osgi.framework.ServiceReference;
 
 /**
@@ -30,7 +31,7 @@
  * 
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class DependencyCallback {
+public class DependencyCallback extends Callback {
 
     /**
      * Bind method (called when a service arrives).
@@ -57,16 +58,11 @@
      * Callback method name.
      */
     private String m_method;
-
+    
     /**
-     * Is the callback a static callback.
+     * Service Dependency. 
      */
-    private Callback m_callback;
-
-    /**
-     * The instance manager.
-     */
-    private InstanceManager m_manager;
+    private Dependency m_dependency;
 
     /**
      * Constructor.
@@ -77,9 +73,10 @@
      * method
      */
     public DependencyCallback(Dependency dep, String method, int methodType) {
+        super(method, (String[]) null, false, dep.getDependencyHandler().getInstanceManager());
         m_methodType = methodType;
+        m_dependency = dep;
         m_method = method;
-        m_manager = dep.getDependencyHandler().getInstanceManager();
     }
 
 
@@ -93,15 +90,87 @@
     
     /**
      * Set the argument type (Empty or the class name).
-     * @param arg : the type name or EMPTY
+     * @param arg : the array of argument types.
      */
     public void setArgument(String[] arg) {
         m_argument = arg;
-        m_callback = new Callback(m_method, arg, false, m_manager);        
     }
     
-    public String[] getArgument() {
-        return m_argument;
+    /**
+     * Search the method object in the POJO by analyzing present method.
+     * If not found in the pojo it tests the parent classes.
+     * The name of the method and the argument type are checked.
+     */
+    protected void searchMethod() {
+        if (m_argument != null) {
+            Method[] methods = m_dependency.getDependencyHandler().getInstanceManager().getClazz().getDeclaredMethods();
+            for (int i = 0; m_methodObj == null && i < methods.length; i++) {
+                // First check the method name
+                if (methods[i].getName().equals(m_method)) {
+                    // Check arguments
+                    Class[] clazzes = methods[i].getParameterTypes();
+                    if (clazzes.length == m_argument.length) { // Test size to avoid useless loop
+                        boolean ok = true;
+                        for (int j = 0; ok && j < m_argument.length; j++) {
+                            if (!m_argument[j].equals(clazzes[j].getName())) {
+                                ok = false;
+                            }
+                        }
+                        if (ok) {
+                            m_methodObj = methods[i]; // It is the looked method.
+                        }
+                    }
+
+                }
+            }
+        }
+        
+        if (m_methodObj == null) { //look at parent classes
+            Method[] methods = m_dependency.getDependencyHandler().getInstanceManager().getClazz().getMethods();
+            for (int i = 0; m_methodObj == null && i < methods.length; i++) {
+                // First check the method name
+                if (methods[i].getName().equals(m_method)) {
+                    // Check arguments
+                    Class[] clazzes = methods[i].getParameterTypes();
+                    switch(clazzes.length) {
+                        case 0 : 
+                            // Callback with no arguments.
+                            m_methodObj = methods[i];
+                            m_argument = new String[0];
+                            break;
+                        case 1 :
+                            if (clazzes[0].getName().equals(ServiceReference.class.getName())) {
+                                // Callback with a service reference.
+                                m_methodObj = methods[i];
+                                m_argument = new String[] {ServiceReference.class.getName()};
+                                break;
+                            }
+                            if (clazzes[0].getName().equals(m_dependency.getSpecification())) {
+                                // Callback with the service object.
+                                m_methodObj = methods[i];
+                                m_argument = new String[] {m_dependency.getSpecification()};
+                                break;
+                            }
+                        case 2 : 
+                            if (clazzes[0].getName().equals(m_dependency.getSpecification())  && clazzes[1].getName().equals(ServiceReference.class.getName())) {
+                                // Callback with two arguments.
+                                m_methodObj = methods[i];
+                                m_argument = new String[] {m_dependency.getSpecification(), ServiceReference.class.getName()};
+                            }
+                            break;
+                        default :
+                            break;
+                    }
+                }
+            }
+        }
+        
+        if (m_methodObj == null) {
+            m_dependency.getDependencyHandler().log(Logger.ERROR, "The method " + m_method + " cannot be called : method not found");
+            return;
+        } else {
+            m_methodObj.setAccessible(true);
+        }
     }
 
     /**
@@ -114,19 +183,22 @@
      * @throws IllegalAccessException : The method can not be invoked
      */
     protected void call(ServiceReference ref, Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        if (m_methodObj == null) {
+            searchMethod();
+        }
         switch (m_argument.length) {
             case 0 :
-                m_callback.call(new Object[0]);
+                call(new Object[0]);
                 break;
             case 1 : 
                 if (m_argument[0].equals(ServiceReference.class.getName())) {
-                    m_callback.call(new Object[] {ref});
+                    call(new Object[] {ref});
                 } else {
-                    m_callback.call(new Object[] {obj});
+                    call(new Object[] {obj});
                 }
                 break;
             case 2 :
-                m_callback.call(new Object[] {obj, ref});
+                call(new Object[] {obj, ref});
                 break;
             default : 
                 break;
@@ -145,19 +217,22 @@
      * @throws InvocationTargetException
      */
     protected void callOnInstance(Object instance, ServiceReference ref, Object obj) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        if (m_methodObj == null) {
+            searchMethod();
+        }
         switch (m_argument.length) {
             case 0 :
-                m_callback.call(instance, new Object[0]);
+                call(instance, new Object[0]);
                 break;
             case 1 : 
                 if (m_argument[0].equals(ServiceReference.class.getName())) {
-                    m_callback.call(instance, new Object[] {ref});
+                    call(instance, new Object[] {ref});
                 } else {
-                    m_callback.call(instance, new Object[] {obj});
+                    call(instance, new Object[] {obj});
                 }
                 break;
             case 2 :
-                m_callback.call(instance, new Object[] {obj, ref});
+                call(instance, new Object[] {obj, ref});
                 break;
             default : 
                 break;
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
index 7b7c839..95e58d7 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
@@ -146,45 +146,45 @@
 
         for (int i = 0; i < callbacks.length; i++) {
             MethodMetadata[] mets = manipulation.getMethods(callbacks[i].getMethodName());
-            if (mets.length == 0) {
-                log(Logger.ERROR, "A requirement callback " + callbacks[i].getMethodName() + " does not exist in the implementation");
-                throw new ConfigurationException("Requirement Callback : A requirement callback " + callbacks[i].getMethodName() + " does not exist in the implementation", getInstanceManager().getFactory().getName());
-            }
-            if (mets[0].getMethodArguments().length > 2) {
-                log(Logger.ERROR, "A requirement callback " + callbacks[i].getMethodName() + " must have 0 or 1 or 2 arguments");
-                throw new ConfigurationException("Requirement Callback : A requirement callback " + callbacks[i].getMethodName() + " must have 0 or 1 or 2 arguments", getInstanceManager().getFactory().getName());
-            }
-            callbacks[i].setArgument(mets[0].getMethodArguments());
-            if (mets[0].getMethodArguments().length == 1) {
-                if (!mets[0].getMethodArguments()[0].equals(ServiceReference.class.getName())) {
-                    if (dep.getSpecification() == null) {
-                        dep.setSpecification(mets[0].getMethodArguments()[0]);
-                    }
-                    if (!dep.getSpecification().equals(mets[0].getMethodArguments()[0])) {
-                        log(Logger.WARNING, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] The field type [" + mets[0].getMethodArguments()[0] + "] and the needed service interface [" + dep.getSpecification()
-                                + "] are not the same");
-                        dep.setSpecification(mets[0].getMethodArguments()[0]);
-                    }
-                }
-            } else if (mets[0].getMethodArguments().length == 2) {
-                // Check that the second arguments is a service reference
-                if (!mets[0].getMethodArguments()[1].equals(ServiceReference.class.getName())) {
-                    String message = "The requirement callback " + callbacks[i].getMethodName() + " must have a ServiceReference as the second arguments";
-                    log(Logger.ERROR, message);
-                    throw new ConfigurationException(message, getInstanceManager().getFactory().getName());
-                }
-                if (dep.getSpecification() == null) {
-                    dep.setSpecification(mets[0].getMethodArguments()[0]);
-                } else {
-                    if (!dep.getSpecification().equals(mets[0].getMethodArguments()[0])) {
-                        log(Logger.WARNING, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] The field type [" + mets[0].getMethodArguments()[0] + "] and the needed service interface [" + dep.getSpecification()
-                                + "] are not the same");
-                        dep.setSpecification(mets[0].getMethodArguments()[0]);
-                    }
+            if (mets.length != 0) {
+                if (mets[0].getMethodArguments().length > 2) {
+                    log(Logger.ERROR, "A requirement callback " + callbacks[i].getMethodName() + " must have 0 or 1 or 2 arguments");
+                    throw new ConfigurationException("Requirement Callback : A requirement callback " + callbacks[i].getMethodName() + " must have 0 or 1 or 2 arguments", getInstanceManager().getFactory().getName());
                 }
                 
+                callbacks[i].setArgument(mets[0].getMethodArguments());
+                if (mets[0].getMethodArguments().length == 1) {
+                    if (!mets[0].getMethodArguments()[0].equals(ServiceReference.class.getName())) {
+                        if (dep.getSpecification() == null) {
+                            dep.setSpecification(mets[0].getMethodArguments()[0]);
+                        }
+                        if (!dep.getSpecification().equals(mets[0].getMethodArguments()[0])) {
+                            log(Logger.WARNING, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] The field type [" + mets[0].getMethodArguments()[0] + "] and the needed service interface [" + dep.getSpecification()
+                                    + "] are not the same");
+                            dep.setSpecification(mets[0].getMethodArguments()[0]);
+                        }
+                    }
+                } else if (mets[0].getMethodArguments().length == 2) {
+                    // Check that the second arguments is a service reference
+                    if (!mets[0].getMethodArguments()[1].equals(ServiceReference.class.getName())) {
+                        String message = "The requirement callback " + callbacks[i].getMethodName() + " must have a ServiceReference as the second arguments";
+                        log(Logger.ERROR, message);
+                        throw new ConfigurationException(message, getInstanceManager().getFactory().getName());
+                    }
+                    if (dep.getSpecification() == null) {
+                        dep.setSpecification(mets[0].getMethodArguments()[0]);
+                    } else {
+                        if (!dep.getSpecification().equals(mets[0].getMethodArguments()[0])) {
+                            log(Logger.WARNING, "[DependencyHandler on " + getInstanceManager().getInstanceName() + "] The field type [" + mets[0].getMethodArguments()[0] + "] and the needed service interface [" + dep.getSpecification()
+                                    + "] are not the same");
+                            dep.setSpecification(mets[0].getMethodArguments()[0]);
+                        }
+                    }
+                }
+            } else {
+                log(Logger.INFO, "A requirement callback " + callbacks[i].getMethodName() + " does not exist in the implementation, try the super classes");
             }
-            
+
         }
 
         if (field != null) {
@@ -240,6 +240,12 @@
         }
         // END OF DEPRECATED BLOCK
 
+        // Get instance filters.
+        Dictionary filtersConfiguration = null;
+        if (configuration.get("requires.filters") != null) {
+            filtersConfiguration = (Dictionary) configuration.get("requires.filters");
+        }
+        
         for (int i = 0; i < deps.length; i++) {
             // Create the dependency metadata
             String field = null;
@@ -279,6 +285,11 @@
                 }
             }
 
+            // Get instance filter if available
+            if (filtersConfiguration != null && id != null && filtersConfiguration.get(id) != null) {
+                filter = (String) filtersConfiguration.get(id);
+            }
+            
             Dependency dep = new Dependency(this, field, serviceSpecification, filter, optional, aggregate, id, scopePolicy);
 
             // Look for dependency callback :
@@ -328,15 +339,24 @@
         // dep.getMetadata().getServiceSpecification().split("[.]");
         // String className = "org/apache/felix/ipojo/" + segment[segment.length
         // - 1] + "Nullable";
-        String className = dep.getSpecification() + "Nullable";
+        final String className = dep.getSpecification() + "Nullable";
         String resource = dep.getSpecification().replace('.', '/') + ".class";
         URL url = getInstanceManager().getContext().getBundle().getResource(resource);
 
         try {
-            byte[] b = NullableObjectWriter.dump(url, dep.getSpecification());
+            final byte[] b = NullableObjectWriter.dump(url, dep.getSpecification());
             Class c = null;
             try {
-                c = getInstanceManager().getFactory().defineClass(className, b, null);
+                ClassLoader cl = new ClassLoader() {
+                    public Class loadClass(String name) throws ClassNotFoundException {
+                        if (name.equals(className)) {
+                            return defineClass(name, b, 0, b.length, null);
+                        } else {
+                            return getInstanceManager().getContext().getBundle().loadClass(name);
+                        }
+                    }
+                };
+                c = cl.loadClass(className); 
             } catch (Exception e) {
                 log(Logger.ERROR, "Cannot define the nullable class : " + e.getMessage());
                 e.printStackTrace();
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Callback.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Callback.java
index 4f84322..a4daa34 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Callback.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Callback.java
@@ -30,6 +30,11 @@
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class Callback {
+    
+    /**
+     * Method object.
+     */
+    protected Method m_methodObj;
 
     /**
      * Name of the method to call.
@@ -47,11 +52,6 @@
     private InstanceManager m_manager;
     
     /**
-     * Method object.
-     */
-    private Method m_methodObj;
-    
-    /**
      * Argument classes.
      */
     private String[] m_args;
@@ -68,32 +68,34 @@
         m_method = method;
         m_isStatic = isStatic;
         m_manager = im;
-        m_args = new String[args.length];
-        for (int i = 0; i < args.length; i++) {
-            // Primitive Array 
-            if (args[i].endsWith("[]") && args[i].indexOf(".") == -1) {
-                String arr = "";
-                for (int j = 0; j < args[i].length(); j++) {
-                    if (args[i].charAt(j) == '[') { arr += '['; }
+        if (args != null) {
+            m_args = new String[args.length];
+            for (int i = 0; i < args.length; i++) {
+                // Primitive Array 
+                if (args[i].endsWith("[]") && args[i].indexOf(".") == -1) {
+                    String arr = "";
+                    for (int j = 0; j < args[i].length(); j++) {
+                        if (args[i].charAt(j) == '[') { arr += '['; }
+                    }
+                    int index = args[i].indexOf('[');
+                    m_args[i] = arr + getInternalPrimitiveType(args[i].substring(0, index));
                 }
-                int index = args[i].indexOf('[');
-                m_args[i] = arr + getInternalPrimitiveType(args[i].substring(0, index));
-            }
-            // Non-Primitive Array 
-            if (args[i].endsWith("[]") && args[i].indexOf(".") != -1) {
-                String arr = "";
-                for (int j = 0; j < args[i].length(); j++) {
-                    if (args[i].charAt(j) == '[') { arr += '['; }
+                // Non-Primitive Array 
+                if (args[i].endsWith("[]") && args[i].indexOf(".") != -1) {
+                    String arr = "";
+                    for (int j = 0; j < args[i].length(); j++) {
+                        if (args[i].charAt(j) == '[') { arr += '['; }
+                    }
+                    int index = args[i].indexOf('[');
+                    m_args[i] = arr + "L" + args[i].substring(0, index) + ";";
                 }
-                int index = args[i].indexOf('[');
-                m_args[i] = arr + "L" + args[i].substring(0, index) + ";";
+                // Simple type 
+                if (!args[i].endsWith("[]")) {
+                    m_args[i] = args[i];
+                }
             }
-            // Simple type 
-            if (!args[i].endsWith("[]")) {
-                m_args[i] = args[i];
-            }
-            
         }
+        
     }
     
     /**
@@ -188,7 +190,7 @@
      * Search the method object in the POJO by analyzing present method.
      * The name of the method and the argument type are checked.
      */
-    private void searchMethod() {
+    protected void searchMethod() {
         Method[] methods = m_manager.getClazz().getDeclaredMethods();
         for (int i = 0; m_methodObj == null && i < methods.length; i++) {
             // First check the method name
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/FieldAdapter.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/FieldAdapter.java
index 22ad2ad..51db771 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/FieldAdapter.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/FieldAdapter.java
@@ -185,17 +185,17 @@
         mv.visitJumpInsn(IFNULL, l4a);

         mv.visitVarInsn(ALOAD, 1);

         mv.visitVarInsn(ALOAD, 3);

-        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z");

-

         Label l5a = new Label();

-        mv.visitJumpInsn(IFNE, l5a);

-        mv.visitLabel(l4a);

-

+        mv.visitJumpInsn(IF_ACMPEQ, l5a); // Test equality on object.

+        

+        // Invoke the _set method

+        mv.visitLabel(l4a);        

         mv.visitVarInsn(ALOAD, 0);

         mv.visitVarInsn(ALOAD, 3);

         mv.visitMethodInsn(INVOKEVIRTUAL, m_owner, "_set" + name, "(" + internalType + ")V");

+        

+        // End of the method

         mv.visitLabel(l5a);

-

         mv.visitVarInsn(ALOAD, 3);

         mv.visitInsn(ARETURN);

 

@@ -504,17 +504,17 @@
                 mv.visitJumpInsn(IFNULL, l4b);

                 mv.visitVarInsn(ALOAD, 1);

                 mv.visitVarInsn(ALOAD, 3);

-                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z");

-

+                

                 Label l5b = new Label();

-                mv.visitJumpInsn(IFNE, l5b);

+                mv.visitJumpInsn(IF_ACMPEQ, l5b); // Test equality on object.

+                

                 mv.visitLabel(l4b);

-

                 mv.visitVarInsn(ALOAD, 0);

                 mv.visitVarInsn(ALOAD, 3);

                 mv.visitMethodInsn(INVOKEVIRTUAL, m_owner, "_set" + name, "(L" + type.getInternalName() + ";)V");

+                

+                // End of the getter method, return the object

                 mv.visitLabel(l5b);

-

                 mv.visitVarInsn(ALOAD, 3);

                 mv.visitInsn(ARETURN);