Fix the issue #Felix-427.
Nullable object are now created with a dynamic proxy (instead of a bytecode generation).
Avoid useless object creation in the instance manager.
Change the composition creation to use Class introspection instead of Class visit (class is already loaded to compute service dependencies).

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@600287 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java
index d87ecdd..7754ef5 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java
@@ -119,7 +119,9 @@
 

         setState(INVALID);

         

-        m_handler.stop();

+        if (m_handler != null) {

+            m_handler.stop();

+        }

         

         // Stop all the handlers

         for (int i = m_handlers.length - 1; i > -1; i--) {

@@ -128,8 +130,10 @@
         }

 

         m_state = STOPPED;

-        for (int i = 0; i < m_instanceListeners.size(); i++) {

-            ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, STOPPED);

+        if (m_instanceListeners != null) {

+            for (int i = 0; i < m_instanceListeners.size(); i++) {

+                ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, STOPPED);

+            }

         }

     }

     

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 f38e867..b310ece 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
@@ -55,7 +55,7 @@
     /**
      * Handler list.
      */
-    protected HandlerManager[] m_handlers = new HandlerManager[0];
+    protected HandlerManager[] m_handlers = null;
 
     /**
      * Component state (STOPPED at the beginning).
@@ -65,7 +65,7 @@
     /**
      * Instance State Listener List.
      */
-    protected List m_instanceListeners = new ArrayList();
+    protected List m_instanceListeners = null;
     
     /**
      * Parent factory (ComponentFactory).
@@ -85,7 +85,7 @@
     /**
      * Map [method identifier, handler list] storing handlers interested by the method.
      */
-    private Map m_methodRegistration = new HashMap();
+    private Map m_methodRegistration;
 
     /**
      * Manipulated class.
@@ -95,7 +95,7 @@
     /**
      * Instances of the components.
      */
-    private Object[] m_pojoObjects = new Object[0];
+    private Object[] m_pojoObjects = null;
 
    /**
     * Is the component instance state changing?
@@ -154,11 +154,13 @@
         int componentState = getState();
         InstanceDescription instanceDescription = new InstanceDescription(m_name, componentState, getContext().getBundle().getBundleId(), m_factory.getComponentDescription());
 
-        String[] objects = new String[getPojoObjects().length];
-        for (int i = 0; i < getPojoObjects().length; i++) {
-            objects[i] = "" + getPojoObjects()[i];
+        if (m_pojoObjects != null) {
+            String[] objects = new String[m_pojoObjects.length];
+            for (int i = 0; i < m_pojoObjects.length; i++) {
+                objects[i] = m_pojoObjects[i].toString();
+            }
+            instanceDescription.setCreatedObjects(objects);
         }
-        instanceDescription.setCreatedObjects(objects);
 
         Handler[] handlers = getRegistredHandlers();
         for (int i = 0; i < handlers.length; i++) {
@@ -234,11 +236,13 @@
             m_handlers[i].stop();
         }
         
-        m_pojoObjects = new Object[0];
+        m_pojoObjects = null;
 
         m_state = STOPPED;
-        for (int i = 0; i < m_instanceListeners.size(); i++) {
-            ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, STOPPED);
+        if (m_instanceListeners != null) {
+            for (int i = 0; i < m_instanceListeners.size(); i++) {
+                ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, STOPPED);
+            }
         }
     }
     
@@ -253,8 +257,11 @@
         
         m_state = DISPOSED;
         
-        for (int i = 0; i < m_instanceListeners.size(); i++) {
-            ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, DISPOSED);
+        if (m_instanceListeners != null) {
+            for (int i = 0; i < m_instanceListeners.size(); i++) {
+                ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, DISPOSED);
+            }
+            m_instanceListeners = null;
         }
         
         m_factory.disposed(this);
@@ -269,7 +276,6 @@
         m_methodRegistration = new HashMap();
         m_clazz = null;
         m_inTransition = false;
-        m_instanceListeners.clear();
     }
     
     /**
@@ -280,9 +286,11 @@
         if (m_state > STOPPED) {
             stop();
         }
-        
-        for (int i = 0; i < m_instanceListeners.size(); i++) {
-            ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, DISPOSED);
+        if (m_instanceListeners != null) {
+            for (int i = 0; i < m_instanceListeners.size(); i++) {
+                ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, DISPOSED);
+            }
+            m_instanceListeners = null;
         }
 
         // Cleaning
@@ -298,7 +306,7 @@
         m_methodRegistration = new HashMap();
         m_clazz = null;
         m_inTransition = false;
-        m_instanceListeners.clear();
+        
     }
     
     /**
@@ -331,8 +339,10 @@
                 }
             }
             
-            for (int i = 0; i < m_instanceListeners.size(); i++) {
-                ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, state);
+            if (m_instanceListeners != null) {
+                for (int i = 0; i < m_instanceListeners.size(); i++) {
+                    ((InstanceStateListener) m_instanceListeners.get(i)).stateChanged(this, state);
+                }
             }
         }
         
@@ -367,6 +377,9 @@
      * @see org.apache.felix.ipojo.ComponentInstance#addInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
      */
     public void addInstanceStateListener(InstanceStateListener listener) {
+        if (m_instanceListeners == null) {
+            m_instanceListeners = new ArrayList();
+        }
         synchronized (m_instanceListeners) {
             m_instanceListeners.add(listener);
         }
@@ -378,8 +391,13 @@
      * @see org.apache.felix.ipojo.ComponentInstance#removeInstanceStateListener(org.apache.felix.ipojo.InstanceStateListener)
      */
     public void removeInstanceStateListener(InstanceStateListener listener) {
-        synchronized (m_instanceListeners) {
-            m_instanceListeners.remove(listener);
+        if (m_instanceListeners != null) {
+            synchronized (m_instanceListeners) {
+                m_instanceListeners.remove(listener);
+                if (m_instanceListeners.size() == 0) {
+                    m_instanceListeners = null;
+                }
+            }
         }
     }
 
@@ -410,13 +428,7 @@
      * @param o : the instance to add
      */
     private synchronized void addInstance(Object o) {
-        for (int i = 0; (m_pojoObjects != null) && (i < m_pojoObjects.length); i++) {
-            if (m_pojoObjects[i] == o) {
-                return;
-            }
-        }
-
-        if (m_pojoObjects.length > 0) {
+        if (m_pojoObjects != null) {
             Object[] newInstances = new Object[m_pojoObjects.length + 1];
             System.arraycopy(m_pojoObjects, 0, newInstances, 0, m_pojoObjects.length);
             newInstances[m_pojoObjects.length] = o;
@@ -451,7 +463,7 @@
 
         if (idx >= 0) {
             if ((m_pojoObjects.length - 1) == 0) {
-                m_pojoObjects = new Object[0];
+                m_pojoObjects = null;
             } else {
                 Object[] newInstances = new Object[m_pojoObjects.length - 1];
                 System.arraycopy(m_pojoObjects, 0, newInstances, 0, idx);
@@ -531,7 +543,7 @@
      * @return the instance of the component instance to use for singleton component
      */
     public synchronized Object getPojoObject() {
-        if (m_pojoObjects.length == 0) {
+        if (m_pojoObjects == null) {
             createPojoObject();
         }
         return m_pojoObjects[0];
@@ -574,100 +586,30 @@
             }
         }
         for (int i = 0; methods != null && i < methods.length; i++) {
-            if (m_methodRegistration.get(methods[i].getMethodIdentifier()) == null) {
+            if (m_methodRegistration == null) { 
+                m_methodRegistration = new HashMap();
                 m_methodRegistration.put(methods[i].getMethodIdentifier(), new PrimitiveHandler[] { h });
-            } else {
+            } else { 
                 PrimitiveHandler[] list = (PrimitiveHandler[]) m_methodRegistration.get(methods[i].getMethodIdentifier());
-                for (int j = 0; j < list.length; j++) {
-                    if (list[j] == h) {
-                        return;
+                if (list == null) {
+                    m_methodRegistration.put(methods[i].getMethodIdentifier(), new PrimitiveHandler[] { h });
+                } else {
+                    for (int j = 0; j < list.length; j++) {
+                        if (list[j] == h) {
+                            return;
+                        }
                     }
+                    PrimitiveHandler[] newList = new PrimitiveHandler[list.length + 1];
+                    System.arraycopy(list, 0, newList, 0, list.length);
+                    newList[list.length] = h;
+                    m_methodRegistration.put(methods[i].getMethodIdentifier(), newList);
                 }
-                PrimitiveHandler[] newList = new PrimitiveHandler[list.length + 1];
-                System.arraycopy(list, 0, newList, 0, list.length);
-                newList[list.length] = h;
-                m_methodRegistration.put(methods[i].getMethodIdentifier(), newList);
             }
         }
         
     }
 
     /**
-     * Unregister an handler for the field list. The handler will not be
-     * notified of field access but is always register on the instance manager.
-     * 
-     * @param h : the handler to unregister.
-     * @param fields : the field metadata list
-     * @param methods : the method metadata list
-     */
-    public void unregister(PrimitiveHandler h, FieldMetadata[] fields, MethodMetadata[] methods) {
-        for (int i = 0; i < fields.length; i++) {
-            if (m_fieldRegistration.get(fields[i].getFieldName()) == null) {
-                break;
-            } else {
-                PrimitiveHandler[] list = (PrimitiveHandler[]) m_fieldRegistration.get(fields[i].getFieldName());
-                int idx = -1;
-                for (int j = 0; j < list.length; j++) {
-                    if (list[j] == h) {
-                        idx = j;
-                        break;
-                    }
-                }
-
-                if (idx >= 0) {
-                    if ((list.length - 1) == 0) {
-                        list = new PrimitiveHandler[0];
-                    } else {
-                        PrimitiveHandler[] newList = new PrimitiveHandler[list.length - 1];
-                        System.arraycopy(list, 0, newList, 0, idx);
-                        if (idx < newList.length) {
-                            System.arraycopy(list, idx + 1, newList, idx, newList.length - idx);
-                        }
-                        list = newList;
-                    }
-                    m_fieldRegistration.put(fields[i].getFieldName(), list);
-                }
-            }
-        }
-        for (int i = 0; i < methods.length; i++) {
-            if (m_methodRegistration.get(methods[i].getMethodIdentifier()) == null) {
-                break;
-            } else {
-                PrimitiveHandler[] list = (PrimitiveHandler[]) m_methodRegistration.get(methods[i].getMethodIdentifier());
-                int idx = -1;
-                for (int j = 0; j < list.length; j++) {
-                    if (list[j] == h) {
-                        idx = j;
-                        break;
-                    }
-                }
-
-                if (idx >= 0) {
-                    if ((list.length - 1) == 0) {
-                        list = new PrimitiveHandler[0];
-                    } else {
-                        PrimitiveHandler[] newList = new PrimitiveHandler[list.length - 1];
-                        System.arraycopy(list, 0, newList, 0, idx);
-                        if (idx < newList.length) {
-                            System.arraycopy(list, idx + 1, newList, idx, newList.length - idx);
-                        }
-                        list = newList;
-                    }
-                    m_methodRegistration.put(methods[i].getMethodIdentifier(), list);
-                }
-            }
-        }
-    }
-    
-    public Set getRegistredFields() {
-        return m_fieldRegistration.keySet();
-    }
-    
-    public Set getRegistredMethods() {
-        return m_methodRegistration.keySet();
-    }
-
-    /**
      * This method is called by the manipulated class each time that a GETFIELD
      * instruction is found. The method ask to each handler which value need to
      * be returned.
@@ -830,4 +772,30 @@
             return;
         }        
     }
+    
+    /**
+     * Get the list of registered fields.
+     * This method is invoked by the POJO itself.
+     * @return the set of registered fields.
+     */
+    public Set getRegistredFields() {
+        if (m_fieldRegistration != null) {
+            return m_fieldRegistration.keySet();
+        } else {
+            return null;
+        }
+    }
+    
+    /**
+     * Get the list of registered methods.
+     * This method is invoked by the POJO itself.
+     * @return the set of registered methods.
+     */
+    public Set getRegistredMethods() {
+        if (m_methodRegistration != null) {
+            return m_methodRegistration.keySet();
+        } else {
+            return null;
+        }
+    }
 }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java
index 5040d94..14bb1e8 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/InstanceDescription.java
@@ -149,7 +149,7 @@
     public void addInstance(InstanceDescription inst) {
         // Verify that the dependency description is not already in the array.
         for (int i = 0; i < m_containedInstances.length; i++) {
-            if (m_containedInstances[i] == inst) {
+            if (m_containedInstances[i].getName().equals(inst.getName())) {
                 return; // NOTHING TO DO, the description is already in the array
             }
         }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
index c1cb213..da54207 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/CompositionMetadata.java
@@ -19,7 +19,6 @@
 package org.apache.felix.ipojo.composite.service.provides;
 
 import java.io.IOException;
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -166,7 +165,7 @@
 
     /**
      * Build the delegation mapping.
-     * @throws CompositionException : occurs when the mapping cannot be infers correctly
+     * @throws CompositionException : occurs when the mapping cannot be inferred correctly
      */
     protected void buildMapping() throws CompositionException {
         buildAvailableMappingList();
@@ -214,14 +213,14 @@
                         field.setUseful(true);
                         method.setDelegation(field);
                         // Test optional
-                        if (field.isOptional() && !method.getExceptions().contains("java/lang/UnsupportedOperationException")) {
-                            m_handler.log(Logger.WARNING, "The method " + method.getMethodName() + " could not be provided correctly : the specification " + field.getSpecification().getName() + " is optional");
+                        if (field.isOptional() && !method.throwsUnsupportedOperationException()) {
+                            m_handler.log(Logger.WARNING, "The method " + method.getMethod().getName() + " could not be provided correctly : the specification " + field.getSpecification().getName() + " is optional");
                         }
                     }
                 }
             }
             if (!found) {
-                throw new CompositionException("Inconsistent composition - the method " + method.getMethodName() + " could not be delegated");
+                throw new CompositionException("Inconsistent composition - the method " + method.getMethod() + " could not be delegated");
             }
         }
     }
@@ -231,9 +230,14 @@
      * @return the byte[] of the POJO.
      */
     protected byte[] buildPOJO() {
-        String resource = m_specification.getName().replace('.', '/') + ".class";
-        URL url = getBundleContext().getBundle().getResource(resource);
-        byte[] pojo = POJOWriter.dump(url, m_specification.getName(), m_name, getFieldList(), getMethodList());
+        Class clazz = null;
+        try {
+            clazz = getBundleContext().getBundle().loadClass(m_specification.getName());
+        } catch (ClassNotFoundException e1) {
+            //TODO
+            e1.printStackTrace();
+        }
+        byte[] pojo = POJOWriter.dump(clazz, m_name, getFieldList(), getMethodList());
         Manipulator m = new Manipulator();
         try {
             byte[] ff = m.manipulate(pojo);
@@ -242,7 +246,7 @@
         } catch (IOException e) {
             e.printStackTrace();
         }
-        return new byte[0];
+        return null;
     }
 
     /**
@@ -257,7 +261,7 @@
         elem.addAttribute(className);
         elem.addAttribute(factory);
         
-        // Add architcture for debug
+        // Add architecture for debug
         elem.addAttribute(new Attribute("architecture", "true"));
 
         // Provides
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java
index 97fddd9..5e209ae 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/MethodMetadata.java
@@ -18,10 +18,7 @@
  */
 package org.apache.felix.ipojo.composite.service.provides;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.felix.ipojo.handlers.dependency.nullable.MethodSignature;
+import java.lang.reflect.Method;
 
 /**
  * Information on Method for the composition.
@@ -40,24 +37,9 @@
     public static final int ALL_POLICY = 2;
 
     /**
-     * Method Name.
+     * Method Object.
      */
-    private String m_methodName;
-
-    /**
-     * Internal Descriptor.
-     */
-    private String m_descriptor;
-
-    /**
-     * List of arguments. 
-     */
-    private List/* <String> */m_arguments = new ArrayList/* <String> */();
-
-    /**
-     * List of exceptions.
-     */
-    private List/* <String> */m_exceptions = new ArrayList/* <String> */();
+    private Method m_method;
     
     /**
      * Delegation field.
@@ -71,40 +53,14 @@
 
     /**
      * Constructor.
-     * @param name : name of the method.
-     * @param desc : description of the method.
+     * @param method : method object.
      */
-    public MethodMetadata(String name, String desc) {
-        m_methodName = name;
-        m_descriptor = desc;
+    public MethodMetadata(Method method) {
+        m_method = method;
     }
 
-    /**
-     * Add an argument.
-     * @param type : type of the argument.
-     */
-    public void addArgument(String type) {
-        m_arguments.add(type);
-    }
-
-    /**
-     * Add an exception.
-     * @param exception : name of the exception.
-     */
-    public void addException(String exception) {
-        m_exceptions.add(exception);
-    }
-
-    public List/* <String> */getArguments() {
-        return m_arguments;
-    }
-
-    public List/* <String> */getExceptions() {
-        return m_exceptions;
-    }
-
-    public String getMethodName() {
-        return m_methodName;
+    public Method getMethod() {
+        return m_method;
     }
 
     public void setDelegation(FieldMetadata dm) {
@@ -121,13 +77,22 @@
      * @return true if the two method are equals
      */
     public boolean equals(MethodMetadata mm) {
-        // Test if the name are the same, #args and #exception are the same.
-        if (!mm.getMethodName().equals(m_methodName) || mm.getArguments().size() != m_arguments.size()) {
+        Method met = mm.getMethod();
+        return equals(met);
+    }
+
+    /**
+     * Equals method for Method object.
+     * @param met : the method object to compare.
+     * @return true if the given method signature is equals to the current method metadata.
+     */
+    public boolean equals(Method met) {
+        if (! met.getName().equals(m_method.getName()) || met.getParameterTypes().length != m_method.getParameterTypes().length) {
             return false;
         }
 
-        for (int i = 0; i < m_arguments.size(); i++) {
-            if (!m_arguments.get(i).equals(mm.getArguments().get(i))) {
+        for (int i = 0; i < m_method.getParameterTypes().length; i++) {
+            if (!m_method.getParameterTypes()[i].getName().equals(met.getParameterTypes()[i].getName())) {
                 return false;
             }
         }
@@ -135,23 +100,6 @@
         return true;
     }
 
-    /**
-     * Equals method for Method Signature.
-     * @param ms : the method signature to compare.
-     * @return true if the given method signature is equals to the current method metadata.
-     */
-    public boolean equals(MethodSignature ms) {
-        // the method is equals to the method signature if the name and the desc are similar.
-        if (!m_methodName.equals(ms.getName())) {
-            return false;
-        }
-        if (!m_descriptor.equals(ms.getDesc())) {
-            return false;
-        }
-        
-        return true;
-    }
-
     public int getPolicy() {
         return m_policy;
     }
@@ -163,6 +111,17 @@
         m_policy = ALL_POLICY;
     }
     
-    public String getDescription() { return m_descriptor; }
+    /**
+     * Check if the method can throw UnsupportedOperationException.
+     * @return true if the method has declared the UnsupportedOperationException.
+     */
+    boolean throwsUnsupportedOperationException() {
+        for (int i = 0; i < m_method.getExceptionTypes().length; i++) {
+            if (m_method.getExceptionTypes()[i].getName().equals(UnsupportedOperationException.class.getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
 
 }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java
index c9e4400..b8fcab7 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/POJOWriter.java
@@ -18,14 +18,9 @@
  */

 package org.apache.felix.ipojo.composite.service.provides;

 

-import java.io.IOException;

-import java.io.InputStream;

-import java.net.URL;

+import java.lang.reflect.Method;

 import java.util.List;

 

-import org.apache.felix.ipojo.handlers.dependency.nullable.MethodSignature;

-import org.apache.felix.ipojo.handlers.dependency.nullable.MethodSignatureVisitor;

-import org.objectweb.asm.ClassReader;

 import org.objectweb.asm.ClassWriter;

 import org.objectweb.asm.Label;

 import org.objectweb.asm.MethodVisitor;

@@ -76,72 +71,53 @@
 

     /**

      * Return the proxy 'classname' for the contract 'contractname' by delegating on available service.

-     * @param url URL of the needed contract

-     * @param contractName : The interface to implement

+     * @param clazz : Specification class

      * @param className : The class name to create

      * @param fields : the list of fields on which delegate

      * @param methods : the list of method on which delegate

      * @return byte[] : the build class

      */

-    public static byte[] dump(URL url, String contractName, String className, List fields, List methods) {

+    public static byte[] dump(Class clazz, String className, List fields, List methods) {

+        Method[] itfmethods = clazz.getMethods();

 

-        ClassReader cr = null;

-        InputStream is = null;

-        byte[] b = null;

-        try {

-            is = url.openStream();

-            cr = new ClassReader(is);

-            MethodSignatureVisitor msv = new MethodSignatureVisitor();

-            cr.accept(msv, ClassReader.SKIP_FRAMES);

-            is.close();

+        // Create the class

+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);

+        className = className.replace('.', '/');

+        createClass(cw, className, clazz.getName());

 

-            MethodSignature[] methodsSign = msv.getMethods();

+        // Inject fields inside the POJO

+        injectFields(cw, fields);

 

-            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);

+        // Inject a constructor <INIT>()V

+        MethodVisitor cst = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);

+        cst.visitVarInsn(ALOAD, 0);

+        cst.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");

+        cst.visitInsn(RETURN);

+        cst.visitMaxs(0, 0);

+        cst.visitEnd();

 

-            // Create the class

-            className = className.replace('.', '/');

-            createClass(cw, className, contractName);

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

+            Method method = itfmethods[i];

 

-            // Inject fields inside the POJO

-            injectFields(cw, fields);

-

-            // Inject a constructor <INIT>()V

-            MethodVisitor cst = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);

-            cst.visitVarInsn(ALOAD, 0);

-            cst.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");

-            cst.visitInsn(RETURN);

-            cst.visitMaxs(0, 0);

-            cst.visitEnd();

-

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

-                MethodSignature method = methodsSign[i];

-

-                // Get the field for this method

-                // 1) find the MethodMetadata

-                FieldMetadata delegator = null; // field to delegate

-                MethodMetadata methodDelegator = null; // field to delegate

-                for (int j = 0; j < methods.size(); j++) {

-                    MethodMetadata methodMeta = (MethodMetadata) methods.get(j);

-                    if (methodMeta.equals(method)) {

-                        delegator = methodMeta.getDelegation();

-                        methodDelegator = methodMeta;

-                    }

+            // Get the field for this method

+            // 1) find the MethodMetadata

+            FieldMetadata delegator = null; // field to delegate

+            MethodMetadata methodDelegator = null; // field to delegate

+            for (int j = 0; j < methods.size(); j++) {

+                MethodMetadata methodMeta = (MethodMetadata) methods.get(j);

+                if (methodMeta.equals(method)) {

+                    delegator = methodMeta.getDelegation();

+                    methodDelegator = methodMeta;

                 }

-

-                generateOneMethod(cw, className, methodDelegator, method, delegator);

-

             }

 

-            // End process

-            cw.visitEnd();

-            b = cw.toByteArray();

+            generateOneMethod(cw, className, methodDelegator, method, delegator);

 

-        } catch (IOException e) {

-            e.printStackTrace();

         }

 

-        return b;

+        // End process

+        cw.visitEnd();

+        return cw.toByteArray();

     }

 

     /**

@@ -152,13 +128,15 @@
      * @param sign : method signature to generate

      * @param delegator : the field on which delegate

      */

-    private static void generateOneMethod(ClassWriter cw, String className, MethodMetadata method, MethodSignature sign, FieldMetadata delegator) {

-        String desc = sign.getDesc();

+    private static void generateOneMethod(ClassWriter cw, String className, MethodMetadata method, Method sign, FieldMetadata delegator) {

+        String desc = Type.getMethodDescriptor(sign);

         String name = sign.getName();

-        String signa = sign.getSignature();

-        String[] exc = sign.getException();

+        String[] exc = new String[sign.getExceptionTypes().length];

+        for (int i = 0; i < sign.getExceptionTypes().length; i++) {

+            exc[i] = Type.getType(sign.getExceptionTypes()[i]).getInternalName();

+        }

 

-        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, name, desc, signa, exc);

+        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, name, desc, null, exc);

 

         if (delegator.isOptional()) {

             if (!delegator.isAggregate()) {

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
index e0e1b8d..6ccf87b 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/provides/SpecificationMetadata.java
@@ -18,18 +18,11 @@
  */
 package org.apache.felix.ipojo.composite.service.provides;
 
-import java.io.IOException;
-import java.io.InputStream;
 import java.lang.reflect.Method;
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.felix.ipojo.handlers.dependency.nullable.MethodSignature;
-import org.apache.felix.ipojo.handlers.dependency.nullable.MethodSignatureVisitor;
 import org.apache.felix.ipojo.util.Logger;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.Type;
 import org.osgi.framework.BundleContext;
 
 /**
@@ -86,39 +79,18 @@
         m_handler = psd;
     
         // Populate methods :
-        URL url = bc.getBundle().getResource(name.replace('.', '/') + ".class");
-        InputStream is = null;
-        ClassReader cr = null;
-        MethodSignatureVisitor msv = null;
         try {
-            is = url.openStream();
-            cr = new ClassReader(is);
-            msv = new MethodSignatureVisitor();
-            cr.accept(msv, ClassReader.SKIP_FRAMES);
-            is.close();
-        } catch (IOException e) {
+            Class clazz = bc.getBundle().loadClass(name);
+            Method[] methods = clazz.getMethods();
+            for (int i = 0; i < methods.length; i++) {
+                MethodMetadata method = new MethodMetadata(methods[i]);
+                m_methods.add(method);
+            }
+        } catch (ClassNotFoundException e) {
             m_handler.log(Logger.ERROR, "Cannot open " + name + " : " + e.getMessage());
             return;
         }
     
-        MethodSignature[] containsMethods = msv.getMethods();
-        for (int i = 0; i < containsMethods.length; i++) {
-            MethodSignature met = containsMethods[i];
-            String desc = met.getDesc();
-            MethodMetadata method = new MethodMetadata(met.getName(), desc);
-    
-            Type[] args = Type.getArgumentTypes(desc);
-            String[] exceptionClasses = met.getException();
-            for (int j = 0; j < args.length; j++) {
-                method.addArgument(args[j].getClassName());
-            }
-            for (int j = 0; j < exceptionClasses.length; j++) {
-                method.addException(exceptionClasses[j]);
-            }
-    
-            addMethod(method);
-        }
-    
         m_isAggregate = isAggregate;
         m_isOptional = isOptional;
     }
@@ -137,18 +109,8 @@
         m_name = c.getName();
         Method[] methods = c.getMethods();
         for (int i = 0; i < methods.length; i++) {
-            String desc = Type.getMethodDescriptor(methods[i]);
-            MethodMetadata method = new MethodMetadata(methods[i].getName(), desc);
-            Type[] args = Type.getArgumentTypes(desc);
-            Class[] exceptionClasses = methods[i].getExceptionTypes();
-            for (int j = 0; j < args.length; j++) {
-                method.addArgument(args[j].getClassName());
-            }
-            for (int j = 0; j < exceptionClasses.length; j++) {
-                method.addException(exceptionClasses[j].getName());
-            }
-    
-            addMethod(method);
+            MethodMetadata method = new MethodMetadata(methods[i]);    
+            m_methods.add(method);
         }
         m_isInterface = false;
     }
@@ -162,14 +124,6 @@
     }
 
     /**
-     * Add a method metadata to the current specification.
-     * @param mm : the method metadata to add.
-     */
-    public void addMethod(MethodMetadata mm) {
-        m_methods.add(mm);
-    }
-
-    /**
      * Get a method by its name.
      * @param name : method name
      * @return the method metadata contained in the current specification with the given name. Null if the method is not found.
@@ -177,7 +131,7 @@
     public MethodMetadata getMethodByName(String name) {
         for (int i = 0; i < m_methods.size(); i++) {
             MethodMetadata met = (MethodMetadata) m_methods.get(i);
-            if (met.getMethodName().equals(name)) {
+            if (met.getMethod().getName().equals(name)) {
                 return met;
             }
         }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
index 3acc54f..026a349 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
@@ -20,6 +20,7 @@
 
 import java.lang.reflect.Array;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Proxy;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -27,6 +28,7 @@
 import org.apache.felix.ipojo.ComponentInstance;
 import org.apache.felix.ipojo.IPojoContext;
 import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.Nullable;
 import org.apache.felix.ipojo.PolicyServiceContext;
 import org.apache.felix.ipojo.ServiceContext;
 import org.apache.felix.ipojo.composite.CompositeServiceContext;
@@ -40,7 +42,6 @@
 
 /**
  * Represent a service dependency of the component instance.
- * 
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class Dependency implements TrackerCustomizer {
@@ -175,9 +176,14 @@
     private boolean m_activated = false;
     
     /**
-     * Biding Policy.
+     * Binding Policy.
      */
     private int m_bindingPolicy;
+    
+    /**
+     * Nullable object.
+     */
+    private Object m_nullable;
 
     /**
      * Dependency constructor. After the creation the dependency is not started.
@@ -191,12 +197,29 @@
      * @param id : id of the dependency, may be null
      * @param policy : resolution policy
      * @param bindingPolicy : binding policy
+     * @param di : default-implementation class
      */
-    public Dependency(DependencyHandler dh, String field, String spec, String filter, boolean isOptional, boolean isAggregate, String id, int policy, int bindingPolicy) {
+    public Dependency(DependencyHandler dh, String field, String spec, String filter, boolean isOptional, boolean isAggregate, String id, int policy, int bindingPolicy, String di) {
         m_handler = dh;
         m_field = field;
         m_specification = spec;
         m_isOptional = isOptional;
+        if (m_isOptional) {
+            if (di != null) {
+                try {
+                    Class c = getHandler().getInstanceManager().getContext().getBundle().loadClass(di);
+                    m_nullable = c.newInstance();
+                } catch (IllegalAccessException e) {
+                    m_handler.log(Logger.ERROR, "Cannot load the default-implementation " + di + " : " + e.getMessage());
+                } catch (InstantiationException e) {
+                    m_handler.log(Logger.ERROR, "Cannot load the default-implementation " + di + " : " + e.getMessage());
+                } catch (ClassNotFoundException e) {
+                    m_handler.log(Logger.ERROR, "Cannot load the default-implementation " + di + " : " + e.getMessage());
+                }
+            } else {
+                m_nullable = Proxy.newProxyInstance(getHandler().getInstanceManager().getClazz().getClassLoader(), new Class[] {m_clazz, Nullable.class}, new NullableObject());
+            }
+        }
         m_strFilter = filter;
         m_isAggregate = isAggregate;
         if (m_id == null) {
@@ -319,14 +342,11 @@
                 }
             } else {
                 if (m_references.size() == 0) {
-                    Object nullable = m_handler.getNullableObject(this);
-
-                    if (nullable == null) {
-                        m_handler.log(Logger.WARNING, "[" + m_handler.getInstanceManager().getClassName() + "] Cannot load the nullable class to return a dependency object for " + m_field + " -> " + m_specification);
+                    if (m_nullable == null) {
+                        m_handler.log(Logger.WARNING, "[" + m_handler.getInstanceManager().getInstanceName() + "] The dependency is not optional, however no service object can be injected in " + m_field + " -> " + m_specification);
                         return null;
                     }
-
-                    m_usage.getObjects().add(nullable);
+                    m_usage.getObjects().add(m_nullable);
                 } else {
                     ServiceReference ref = (ServiceReference) m_references.get(0);
                     m_usage.getReferences().add(ref); // Get the first one
@@ -348,7 +368,7 @@
      * @param ref : reference to send (if accepted) to the method
      */
     private void callUnbindMethod(ServiceReference ref) {
-        if (m_handler.getInstanceManager().getState() > InstanceManager.STOPPED && m_handler.getInstanceManager().getPojoObjects().length > 0) {
+        if (m_handler.getInstanceManager().getState() > InstanceManager.STOPPED && m_handler.getInstanceManager().getPojoObjects() != null) {
             for (int i = 0; i < m_callbacks.length; i++) {
                 if (m_callbacks[i].getMethodType() == DependencyCallback.UNBIND) {
                     try {
@@ -447,7 +467,7 @@
     private void callBindMethod(ServiceReference ref) {
         // call bind method :
         // if (m_handler.getInstanceManager().getState() == InstanceManager.VALID) {
-        if (m_handler.getInstanceManager().getState() > InstanceManager.STOPPED && m_handler.getInstanceManager().getPojoObjects().length > 0) {
+        if (m_handler.getInstanceManager().getState() > InstanceManager.STOPPED && m_handler.getInstanceManager().getPojoObjects() != null) {
             for (int i = 0; i < m_callbacks.length; i++) {
                 if (m_callbacks[i].getMethodType() == DependencyCallback.BIND) {
                     try {
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 130f17c..433f0b1 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
@@ -18,19 +18,15 @@
  */
 package org.apache.felix.ipojo.handlers.dependency;
 
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.Dictionary;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.felix.ipojo.ComponentInstance;
 import org.apache.felix.ipojo.ConfigurationException;
 import org.apache.felix.ipojo.PolicyServiceContext;
 import org.apache.felix.ipojo.PrimitiveHandler;
 import org.apache.felix.ipojo.architecture.HandlerDescription;
-import org.apache.felix.ipojo.handlers.dependency.nullable.NullableObjectWriter;
 import org.apache.felix.ipojo.metadata.Element;
 import org.apache.felix.ipojo.parser.FieldMetadata;
 import org.apache.felix.ipojo.parser.ManipulationMetadata;
@@ -50,11 +46,6 @@
     private Dependency[] m_dependencies = new Dependency[0];
 
     /**
-     * Map of dependency - nullable objects for optional dependencies.
-     */
-    private Map m_nullableObjects;
-
-    /**
      * State of the handler.
      * Lifecycle controller.
      */
@@ -216,7 +207,6 @@
      */
     public void configure(Element componentMetadata, Dictionary configuration) throws ConfigurationException {
         m_dependencies = new Dependency[0];
-        m_nullableObjects = new HashMap();
 
         ManipulationMetadata manipulation = new ManipulationMetadata(componentMetadata);
         List fl = new ArrayList();
@@ -234,6 +224,7 @@
             String filter = deps[i].getAttribute("filter");
             String opt = deps[i].getAttribute("optional");
             boolean optional = opt != null && opt.equalsIgnoreCase("true");
+            String di = deps[i].getAttribute("default-implementation");
             
             String agg = deps[i].getAttribute("aggregate");
             boolean aggregate = agg != null && agg.equalsIgnoreCase("true");
@@ -270,7 +261,7 @@
                 }
             }
             
-            Dependency dep = new Dependency(this, field, serviceSpecification, filter, optional, aggregate, id, scopePolicy, bindingPolicy);
+            Dependency dep = new Dependency(this, field, serviceSpecification, filter, optional, aggregate, id, scopePolicy, bindingPolicy, di);
 
             // Look for dependency callback :
             for (int j = 0; j < (deps[i].getElements("Callback", "")).length; j++) {
@@ -297,13 +288,6 @@
                     fl.add(manipulation.getField(dep.getField()));
                 }
             }
-            
-            if (optional) {
-                String defaultImpl = deps[i].getAttribute("default-implementation");
-                if (defaultImpl != null) {
-                    m_nullableObjects.put(dep, defaultImpl);
-                }
-            }
         }
 
         if (deps.length > 0) {
@@ -314,62 +298,6 @@
     }
 
     /**
-     * Create a nullable class for the given dependency.
-     * @param dep : the service dependency
-     */
-    private void createNullableObject(Dependency  dep) {
-        String spec = dep.getSpecification();
-        String className = spec + "Nullable";
-        String resource = spec.replace('.', '/') + ".class";
-        URL url = getInstanceManager().getContext().getBundle().getResource(resource);
-
-        byte[] b = NullableObjectWriter.dump(url, spec);
-        Class c = getInstanceManager().getFactory().defineClass(className, b, null);
-        try {
-            Object o = c.newInstance();
-            m_nullableObjects.put(dep, o);
-        } catch (InstantiationException e) {
-            log(Logger.ERROR, "The nullable object for " + dep.getSpecification() + " cannot be instantiate : " + e.getMessage());
-            getInstanceManager().setState(ComponentInstance.INVALID); 
-        } catch (IllegalAccessException e) {
-            log(Logger.ERROR, "The nullable object for " + dep.getSpecification() + " cannot be instantiate : " + e.getMessage());
-            getInstanceManager().setState(ComponentInstance.INVALID);
-        }
-    }
-
-    /**
-     * Return the nullable class corresponding to the given name.
-     * @param dep the dependency which require the nullable class.
-     * @return the class corresponding to the name, or null if the class does not exist.
-     */
-    protected Object getNullableObject(Dependency dep) {
-        Object obj = m_nullableObjects.get(dep);
-        if (obj == null) { return null; } // Should not happen
-        if (obj instanceof String) { 
-            try {
-                Class c = getInstanceManager().getContext().getBundle().loadClass((String) obj);
-                obj = c.newInstance();
-                m_nullableObjects.put(dep, obj);
-                return obj;
-            } catch (ClassNotFoundException e) {
-                // A default-implementation class cannot be loaded
-                log(Logger.ERROR, "The default-implementation class " + obj + " cannot be loaded : " + e.getMessage());
-                getInstanceManager().setState(ComponentInstance.INVALID);
-                return null;
-            } catch (InstantiationException e) {
-                log(Logger.ERROR, "The default-implementation class " + obj + " cannot be instantiated : " + e.getMessage());
-                getInstanceManager().setState(ComponentInstance.INVALID);
-            } catch (IllegalAccessException e) {
-                log(Logger.ERROR, "The default-implementation class " + obj + " cannot be instantiated : " + e.getMessage());
-                getInstanceManager().setState(ComponentInstance.INVALID);
-            }
-            return null;
-        } else {
-            return obj;
-        }
-    }
-
-    /**
      * GetterCallback Method.
      * @param fieldName : the field name.
      * @param value : the value passed to the field (by the previous handler).
@@ -423,12 +351,9 @@
      * @see org.apache.felix.ipojo.Handler#start()
      */
     public void start() {
-        // Start the dependencies, for optional dependencies create Nullable class
+        // Start the dependencies
         for (int i = 0; i < m_dependencies.length; i++) {
             Dependency dep = m_dependencies[i];
-            if (dep.isOptional() && !dep.isAggregate() && ! m_nullableObjects.containsKey(dep)) {
-                createNullableObject(dep);
-            }
             dep.start();
         }
         // Check the state
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java
new file mode 100644
index 0000000..e0e4900
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/NullableObject.java
@@ -0,0 +1,93 @@
+/* 

+ * 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.handlers.dependency;

+

+import java.lang.reflect.InvocationHandler;

+import java.lang.reflect.Method;

+

+/**

+ * Default nullable object.

+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

+ */

+public class NullableObject implements InvocationHandler {

+    

+    /**

+     * Default boolean value.

+     */

+    private static final Boolean DEFAULT_BOOLEAN = Boolean.FALSE;

+    /**

+     * Default byte value.

+     */

+    private static final Byte DEFAULT_BYTE = new Byte((byte) 0);

+    

+    /**

+     * Default short value.

+     */

+    private static final Short DEFAULT_SHORT = new Short((short) 0);

+    

+    /**

+     * Default integer value.

+     */

+    private static final Integer DEFAULT_INT = new Integer(0);

+    

+    /**

+     * Default long value.

+     */

+    private static final Long DEFAULT_LONG = new Long(0);

+    

+    /**

+     * Default float value.

+     */

+    private static final Float DEFAULT_FLOAT = new Float(0.0f);

+    

+    /**

+     * Default double value.

+     */

+    private static final Double DEFAULT_DOUBLE = new Double(0.0);

+    

+    /**

+     * Invokes a method on this null object. The method will return a default

+     * value without doing anything.

+     * @param proxy : proxy object

+     * @param method : invoked method

+     * @param args : arguments.

+     * @return the returned value.

+     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])

+     */

+    public Object invoke(Object proxy, Method method, Object[] args) {

+        Class returnType = method.getReturnType();

+        if (returnType.equals(Boolean.TYPE)) {

+            return DEFAULT_BOOLEAN;

+        } else if (returnType.equals(Byte.TYPE)) {

+            return DEFAULT_BYTE;

+        } else if (returnType.equals(Short.TYPE)) {

+            return DEFAULT_SHORT;

+        } else if (returnType.equals(Integer.TYPE)) {

+            return DEFAULT_INT;

+        } else if (returnType.equals(Long.TYPE)) {

+            return DEFAULT_LONG;

+        } else if (returnType.equals(Float.TYPE)) {

+            return DEFAULT_FLOAT;

+        } else if (returnType.equals(Double.TYPE)) {

+            return DEFAULT_DOUBLE;

+        } else {

+            return null;

+        }

+    }

+}

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/nullable/MethodSignature.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/nullable/MethodSignature.java
deleted file mode 100644
index d1937a5..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/nullable/MethodSignature.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/* 
- * 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.handlers.dependency.nullable;
-
-/**
- * Reprensent of method description.
- * The goal of this class, is to be able to generate a proxy class, or a nullable class from an interface.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class MethodSignature {
-
-    /**
-     * Nmae of the method.
-     */
-    private String m_name;
-
-    /**
-     * Descriptor of the method.
-     */
-    private String m_desc;
-
-    /**
-     * Signature of the method.
-     */
-    private String m_signature;
-
-    /**
-     * Exception thored by the method.
-     */
-    private String[] m_exception = new String[0];
-
-    /**
-     * MethodSignature constructor.
-     * Describe a method.
-     * @param name : name of the method
-     * @param desc : descriptor of the method
-     * @param sign : signature of the method
-     * @param exc : exception throwed by the method
-     */
-    public MethodSignature(String name, String desc, String sign, String[] exc) {
-        m_name = name;
-        m_desc = desc;
-        m_signature = sign;
-        if (exc != null) { m_exception = exc; }
-    }
-
-    /**
-     * Get the method description.
-     * @return the description of the method.
-     */
-    public String getDesc() {
-        return m_desc;
-    }
-
-    /**
-     * Get the list of declared exception.
-     * @return the String array of exception throwed by the method.
-     */
-    public String[] getException() {
-        return m_exception;
-    }
-
-    /**
-     * Get the method name.
-     * @return the name of the method.
-     */
-    public String getName() {
-        return m_name;
-    }
-
-    /**
-     * Get the method signature.
-     * @return the signature of the method.
-     */
-    public String getSignature() {
-        return m_signature;
-    }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/nullable/MethodSignatureVisitor.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/nullable/MethodSignatureVisitor.java
deleted file mode 100644
index 7079e34..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/nullable/MethodSignatureVisitor.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/* 
- * 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.handlers.dependency.nullable;
-
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-
-/** This class implement a class visitor. It store all method signature of
- * the visited interface. Then it returns these class signatures for the proxy
- * generation or the nullable class.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class MethodSignatureVisitor implements ClassVisitor, Opcodes {
-
-    /**
-     * Array of method signature.
-     */
-    private MethodSignature[] m_methods;
-
-
-    /**
-     * Constructor.
-     */
-    public MethodSignatureVisitor() { }
-
-    /**
-     * Visit a method, store the information about the method.
-     * @see org.objectweb.asm.ClassVisitor#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
-     * @param access : Access modifier
-     * @param name : name of the visited method
-     * @param signature : singature of the visited element (null if not generic)
-     * @param desc : descriptor of the method
-     * @param exceptions : execption clause
-     * @return always null (not code visitor needed)
-     */
-    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
-        //Store method signature for each visited method
-        m_methods = addMethod(m_methods, new MethodSignature(name, desc, signature, exceptions));
-        return null;
-    }
-
-    /**
-     * Get the method signatures list.
-     * @return the method signature array.
-     */
-    public MethodSignature[] getMethods() {
-        return m_methods;
-    }
-
-    /**
-     * Return the new array of Method Signature by adding the given list and the given element.
-     * @param list : the current array
-     * @param method : the element to add
-     * @return the new array
-     */
-    public static MethodSignature[] addMethod(MethodSignature[] list, MethodSignature method) {
-        if (list != null) {
-            MethodSignature[] newList = new MethodSignature[list.length + 1];
-            System.arraycopy(list, 0, newList, 0, list.length);
-            newList[list.length] = method;
-            return newList;
-        } else {
-            list = new MethodSignature[] {method};
-            return list;
-        }
-
-    }
-
-    /**
-     * Visit a method.
-     * @see org.objectweb.asm.ClassVisitor#visit(int, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
-     * @param arg0 : version
-     * @param arg1 : access
-     * @param arg2 : name
-     * @param arg3 : signature
-     * @param arg4 : superName
-     * @param arg5 : interfaces 
-     */
-    public void visit(int arg0, int arg1, String arg2, String arg3, String arg4, String[] arg5) { }
-
-    /**
-     * Visit sources.
-     * @see org.objectweb.asm.ClassVisitor#visitSource(java.lang.String, java.lang.String)
-     * @param arg0 : source
-     * @param arg1 : debug
-     */
-    public void visitSource(String arg0, String arg1) { }
-
-    /**
-     * Visit an outer class.
-     * @see org.objectweb.asm.ClassVisitor#visitOuterClass(java.lang.String, java.lang.String, java.lang.String)
-     * @param arg0 : owner
-     * @param arg1 : name
-     * @param arg2 : desc
-     */
-    public void visitOuterClass(String arg0, String arg1, String arg2) { }
-
-    /**
-     * Visit an annotation.
-     * @see org.objectweb.asm.ClassVisitor#visitAnnotation(java.lang.String, boolean)
-     * @param arg0 : desc
-     * @param arg1 : visible
-     * @return annotationvisitor
-     */
-    public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) { return null; }
-
-    /**
-     * Visit an attribute.
-     * @see org.objectweb.asm.ClassVisitor#visitAttribute(org.objectweb.asm.Attribute)
-     * @param arg0 : Attribute
-     */
-    public void visitAttribute(Attribute arg0) { }
-
-    /**
-     * Visit an inner class.
-     * @see org.objectweb.asm.ClassVisitor#visitInnerClass(java.lang.String, java.lang.String, java.lang.String, int)
-     * @param arg0 : name
-     * @param arg1 : outerclass
-     * @param arg2 : innerclass
-     * @param arg3 : access
-     */
-    public void visitInnerClass(String arg0, String arg1, String arg2, int arg3) { }
-
-    /**
-     * Visit a field.
-     * @see org.objectweb.asm.ClassVisitor#visitField(int, java.lang.String, java.lang.String, java.lang.String, java.lang.Object)
-     * @param arg0 : access
-     * @param arg1 : name
-     * @param arg2 : desc
-     * @param arg3 : signature
-     * @param arg4 : value
-     * @return the field visitor
-     */
-    public FieldVisitor visitField(int arg0, String arg1, String arg2, String arg3, Object arg4) { return null; }
-
-    /**
-     * End of the visit.
-     * @see org.objectweb.asm.ClassVisitor#visitEnd()
-     */
-    public void visitEnd() { }
-
-
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/nullable/NullableObjectWriter.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/nullable/NullableObjectWriter.java
deleted file mode 100644
index 9bc4b18..0000000
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/nullable/NullableObjectWriter.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/* 
- * 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.handlers.dependency.nullable;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-/**
- * Create the proxy class.
- * 
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class NullableObjectWriter implements Opcodes {
-
-    /**
-     * Return the proxy classname for the contract contractname on the service
-     * object soc.
-     * 
-     * @param url URL of the needed contract
-     * @param contractName String
-     * @return byte[]
-     */
-    public static byte[] dump(URL url, String contractName) {
-
-        ClassReader cr = null;
-        InputStream is = null;
-        byte[] b = null;
-        try {
-            is = url.openStream();
-            cr = new ClassReader(is);
-            MethodSignatureVisitor msv = new MethodSignatureVisitor();
-            cr.accept(msv, ClassReader.SKIP_FRAMES);
-            is.close();
-
-            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
-
-            // String[] segment = contractName.split("[.]");
-            // String className = "org/apache/felix/ipojo/" +
-            // segment[segment.length - 1] + "Nullable";
-            String className = contractName.replace('.', '/') + "Nullable";
-
-            // Create the class
-            cw.visit(V1_2, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", new String[] { contractName.replace('.', '/'),
-                "org/apache/felix/ipojo/Nullable" });
-
-            // Inject a constructor <INIT>()V
-            MethodVisitor cst = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
-            cst.visitVarInsn(ALOAD, 0);
-            cst.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
-            cst.visitInsn(RETURN);
-            cst.visitMaxs(0, 0);
-            cst.visitEnd();
-
-            // Methods Generation :
-            MethodSignature[] methods = msv.getMethods();
-
-            for (int i = 0; i < methods.length; ++i) {
-                MethodSignature method = methods[i];
-                String desc = method.getDesc();
-                String name = method.getName();
-                String sign = method.getSignature();
-                String[] exc = method.getException();
-
-                MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, name, desc, sign, exc);
-
-                Type returnType = Type.getReturnType(desc);
-                // Primitive type :
-                switch (returnType.getSort()) {
-                    case Type.BOOLEAN:
-                    case Type.INT:
-                    case Type.BYTE:
-                    case Type.CHAR:
-                    case Type.SHORT:
-                        // Integer or Boolean : return 0 ( false)
-                        mv.visitInsn(ICONST_0);
-                        mv.visitInsn(IRETURN);
-                        break;
-                    case Type.LONG:
-                        mv.visitInsn(LCONST_0);
-                        mv.visitInsn(LRETURN);
-                        break;
-                    case Type.DOUBLE:
-                        // Double : return 0.0
-                        mv.visitInsn(DCONST_0);
-                        mv.visitInsn(DRETURN);
-                        break;
-                    case Type.FLOAT:
-                        // Double : return 0.0
-                        mv.visitInsn(FCONST_0);
-                        mv.visitInsn(FRETURN);
-                        break;
-                    case Type.ARRAY:
-                    case Type.OBJECT:
-                        // Return always null for array and object
-                        mv.visitInsn(ACONST_NULL);
-                        mv.visitInsn(ARETURN);
-                        break;
-                    case Type.VOID:
-                        mv.visitInsn(RETURN);
-                        break;
-                    default:
-                        System.err.println("Type not yet managed : " + returnType);
-                        break;
-                }
-                mv.visitMaxs(0, 0);
-                mv.visitEnd();
-            }
-
-            // End process
-            cw.visitEnd();
-            b = cw.toByteArray();
-
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        return b;
-    }
-}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallbackHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallbackHandler.java
index ebb9497..7b153ef 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallbackHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/lifecycle/callback/LifecycleCallbackHandler.java
@@ -153,7 +153,7 @@
         }
         
         // Manage immediate component
-        if (m_immediate && transition == LifecycleCallback.VALIDATE && getInstanceManager().getPojoObjects().length == 0) {
+        if (m_immediate && transition == LifecycleCallback.VALIDATE && getInstanceManager().getPojoObjects() == null) {
             getInstanceManager().getPojoObject();
         }
 
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
index 0a2bfea..ee1248a 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
@@ -216,15 +216,9 @@
      */
     protected synchronized void registerService() {
         if (m_serviceRegistration == null) {
-            String spec = "";
-            for (int i = 0; i < m_serviceSpecification.length; i++) {
-                spec = spec + m_serviceSpecification[i] + ", ";
-            }
             // Build the service properties list
             Properties serviceProperties = getServiceProperties();
-           
             m_serviceRegistration = m_handler.getInstanceManager().getContext().registerService(m_serviceSpecification, this, serviceProperties);
-           
         }
     }
 
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 02450d3..f19373c 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
@@ -288,7 +288,7 @@
             // Two cases :
             // - if instances already exists : call on each instances
             // - if no instance exists : create an instance
-            if (m_manager.getPojoObjects().length == 0) {
+            if (m_manager.getPojoObjects() == null) {
                 return m_methodObj.invoke(m_manager.getPojoObject(), arg);
             } else {
                 Object r = null;
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
index 16c7f61..b026c17 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
@@ -79,8 +79,10 @@
         if (access == ACC_PRIVATE && name.equals("_cm")

                 && desc.equals("Lorg/apache/felix/ipojo/InstanceManager;")) {

             m_isAlreadyManipulated = true;

-        }

-

+        } else if (name.startsWith("class$")) { // Does not add class$* field generated by 'x.class'

+            return null;

+        } 

+        

         Type type = Type.getType(desc);

         if (type.getSort() == Type.ARRAY) {

             if (type.getInternalName().startsWith("L")) {

diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java
index f58cc6b..41ca684 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/PojoAdapter.java
@@ -326,6 +326,9 @@
         mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getRegistredFields", "()Ljava/util/Set;");

         mv.visitVarInsn(ASTORE, 2);

 

+        mv.visitVarInsn(ALOAD, 2);

+        Label endif = new Label();

+        mv.visitJumpInsn(IFNULL, endif);

         Iterator it = m_fields.iterator();

         while (it.hasNext()) {

             String field = (String) it.next();

@@ -339,11 +342,16 @@
             mv.visitFieldInsn(PUTFIELD, m_owner, "_F" + field, "Z");

             mv.visitLabel(l3);

         }

-

+        mv.visitLabel(endif);

+        

         mv.visitVarInsn(ALOAD, 0);

         mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/InstanceManager;");

         mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", "getRegistredMethods", "()Ljava/util/Set;");

         mv.visitVarInsn(ASTORE, 2);

+        

+        mv.visitVarInsn(ALOAD, 2);

+        Label endif2 = new Label();

+        mv.visitJumpInsn(IFNULL, endif2);

 

         for (int i = 0; i < m_methods.size(); i++) {

             String methodId = (String) m_methods.get(i);

@@ -357,6 +365,8 @@
             mv.visitFieldInsn(PUTFIELD, m_owner, "_M" + methodId, "Z");

             mv.visitLabel(l3);

         }

+        

+        mv.visitLabel(endif2);

 

         mv.visitInsn(RETURN);