Remove an assignation in the manipulator to avoid unexpected references.
Add start level mechanism in handlers to decide configure, start and stop order.
Fix a synchronization problems in the Tracker.
Prepare the code for the two new binding policies (static & dynamic-priority)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@582607 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 f4fa940..02a907a 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
@@ -22,6 +22,7 @@
 import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -110,9 +111,9 @@
     protected Tracker m_tracker;
     
     /**
-     * Component Type Name.
+     * Is the factory public (expose as a service). 
      */
-    protected String m_typeName = null;
+    protected boolean m_isPublic;
 
     /**
      * Class loader to delegate loading.
@@ -164,18 +165,14 @@
             return;
         }
         
-        // Get the name
-        if (cm.containsAttribute("name")) {
-            m_typeName = cm.getAttribute("name");
-        }
-
-        if (m_typeName != null) {
-            m_logger = new Logger(m_context, m_typeName, Logger.WARNING);
-        } else {
-            m_logger = new Logger(m_context, m_componentClassName, Logger.WARNING);
+        computeFactoryName();        
+        m_logger = new Logger(m_context, m_factoryName, Logger.WARNING);
+        
+        m_isPublic = true;
+        if (cm.containsAttribute("factory") && cm.getAttribute("factory").equals("false")) {
+            m_isPublic = false;
         }
         
-        computeFactoryName();
         computeRequiredHandlers();
         
     }
@@ -203,13 +200,26 @@
         for (int i = 0; i < m_handlerIdentifiers.size(); i++) {
             HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
             if (hi.m_reference == null && match(hi, reference)) {
+                int oldP = hi.getPriority();
                 hi.setReference(reference);
-                computeFactoryState();
+                // If the priority has changed, sort the list.
+                if (oldP != hi.getPriority()) {
+                    Collections.sort(m_handlerIdentifiers);
+                }
                 return true;
             }
         }
         return false;
     }
+    
+    /**
+     * A matching service has been added to the tracker, we can no compute the factory state.
+     * @param reference : added reference.
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
+     */
+    public void addedService(ServiceReference reference) {
+        computeFactoryState();
+    }
 
     /**
      * Check method : allow a factory to check if given element are correct.
@@ -238,7 +248,7 @@
      * @throws org.apache.felix.ipojo.ConfigurationException : occurs when the instance or type configuration are not correct.
      * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
      */
-    public synchronized ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
+    public ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
         return createComponentInstance(configuration, null);
     }
     
@@ -254,7 +264,7 @@
      * @throws org.apache.felix.ipojo.ConfigurationException : when the instance configuration failed.
      * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
      */
-    public ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
+    public synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {
         if (m_state == INVALID) {
             throw new MissingHandlerException(getMissingHandlers());
         }
@@ -296,11 +306,13 @@
             HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);
             handlers.add(getHandlerInstance(hi, serviceContext));
         }
+        
         InstanceManager instance = new InstanceManager(this, context, (HandlerManager[]) handlers.toArray(new HandlerManager[0]));
         instance.configure(m_componentMetadata, configuration);
 
         m_componentInstances.put(n, instance);
         instance.start();
+
         return instance;
     }
 
@@ -383,13 +395,7 @@
      * @see org.apache.felix.ipojo.Factory#getName()
      */
     public String getName() {
-        if (m_factoryName != null) {
-            return m_factoryName;
-        } else if (m_typeName != null) {
-            return m_typeName;
-        } else {
-            return m_componentClassName;
-        }
+        return m_factoryName;
     }
 
     /**
@@ -543,12 +549,10 @@
         
         computeFactoryState();
 
-        if (m_factoryName == null) {
-            return;
+        if (m_isPublic) {        
+            // Exposition of the factory service
+            m_sr = m_context.registerService(new String[] { Factory.class.getName(), ManagedServiceFactory.class.getName() }, this, getProperties());
         }
-        
-        // Exposition of the factory service
-        m_sr = m_context.registerService(new String[] { Factory.class.getName(), ManagedServiceFactory.class.getName() }, this, getProperties());
     }
 
     /**
@@ -681,36 +685,12 @@
      * Compute the factory name.
      */
     protected void computeFactoryName() {
-        if (m_componentMetadata.containsAttribute("factory")) {
-            // DEPRECATED BLOCK
-            if (m_componentMetadata.getAttribute("factory").equalsIgnoreCase("no")) {
-                m_logger.log(Logger.WARNING, "'factory=no' is deprecated, Please use 'factory=false' instead of 'factory='no'");
-                m_factoryName = null;
-                return;
-            }
-            // END OF DEPRECATED BLOCK
-            if (m_componentMetadata.getAttribute("factory").equalsIgnoreCase("false")) {
-                m_factoryName = null;
-                return;
-            }
-            if (m_componentMetadata.getAttribute("factory").equalsIgnoreCase("true")) {
-                if (m_typeName == null) { //m_typeName is necessary set for composite.
-                    m_factoryName = m_componentMetadata.getAttribute("className");
-                } else {
-                    m_factoryName = m_typeName;
-                }
-                return;
-            }
-            // factory is set with the factory name
+        if (m_componentMetadata.containsAttribute("name")) {
+            m_factoryName = m_componentMetadata.getAttribute("name");
+        } else if (m_componentMetadata.containsAttribute("factory") && ! m_componentMetadata.getAttribute("factory").equalsIgnoreCase("false")) {
             m_factoryName = m_componentMetadata.getAttribute("factory");
-            return;
         } else {
-            if (m_typeName == null) { //m_typeName is necessary set for composite.
-                m_factoryName = m_componentMetadata.getAttribute("className");
-            } else {
-                m_factoryName = m_typeName;
-            }
-            return;
+            m_factoryName = m_componentMetadata.getAttribute("className");
         }
     }
     
@@ -835,10 +815,6 @@
         return m_componentClassName;
     }
 
-    protected String getComponentTypeName() {
-        return m_typeName;
-    }
-
     /**
      * Compute factory properties.
      * @return the properties.
@@ -850,9 +826,6 @@
        
         props.put("factory.name", m_factoryName);
         props.put(Constants.SERVICE_PID, m_factoryName); // Service PID is required for the integration in the configuration admin.
-        if (m_typeName != null) {
-            props.put("component.type", m_typeName);
-        }
         
         if (m_componentDesc != null) {
             props.put("component.providedServiceSpecifications", m_componentDesc.getprovidedServiceSpecification());
@@ -908,11 +881,11 @@
     /**
      * Structure storing required handlers.
      */
-    class HandlerIdentifier {
+    class HandlerIdentifier implements Comparable {
         /**
          * Factory to create this handler.
          */
-        private Factory m_factory;
+        private HandlerFactory m_factory;
         
         /**
          * Handler name.
@@ -920,6 +893,11 @@
         private String m_name;
         
         /**
+         * Handler start level.
+         */
+        private int m_level = Integer.MAX_VALUE;
+        
+        /**
          * Handler namespace.
          */
         private String m_namespace;
@@ -958,12 +936,12 @@
          * The object is get when used for the first time.
          * @return the factory object.
          */
-        public Factory getFactory() {
+        public HandlerFactory getFactory() {
             if (m_reference == null) {
                 return null;
             }
             if (m_factory == null) {
-                m_factory = (Factory) m_tracker.getService(getReference());
+                m_factory = (HandlerFactory) m_tracker.getService(getReference());
             }
             return m_factory;
         }
@@ -992,17 +970,53 @@
             return m_reference;
         }
         
+        public int getPriority() {
+            return m_level;
+        }
+        
         /**
          * Set the service reference.
          * If the new service reference is null, it unget the used factory (if already get).
          * @param ref : new service reference.
          */
         public void setReference(ServiceReference ref) {
+            // First release the previous reference
             if (m_reference != null) {
                 m_tracker.ungetService(m_reference);
                 m_factory = null;
+                m_level = Integer.MAX_VALUE; // Reset the reference to 
             }
+            
             m_reference = ref;
+            // If the given reference is not null, set the priority.
+            if (m_reference != null) {
+                Integer p = (Integer) m_reference.getProperty(Handler.HANDLER_LEVEL_PROPERTY);
+                if (p != null) {
+                    m_level = p.intValue();
+                }
+            }
+            
+        }
+
+        /**
+         * Start level Comparison.
+         * This method is used to sort the handler array.
+         * @param o : object on which compare.
+         * @return -1, 0, +1 according to the comparison of their start level.
+         * @see java.lang.Comparable#compareTo(java.lang.Object)
+         */
+        public int compareTo(Object o) {
+            if (o instanceof HandlerIdentifier) {
+                HandlerIdentifier hi = (HandlerIdentifier) o;
+                if (this.m_level == hi.m_level) {
+                    return 0;
+                } else if (this.m_level < hi.m_level) {
+                    return -1;
+                } else {
+                    return +1;
+                }
+            }
+            return 0;
         }
     }
 
@@ -1036,7 +1050,6 @@
 
         /**
          * 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)
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeFactory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeFactory.java
index 2b6bdf5..e7dc233 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeFactory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeFactory.java
@@ -67,7 +67,7 @@
     public boolean check(Element cm) {

      // Get the name

         if (cm.containsAttribute("name")) {

-            m_typeName = cm.getAttribute("name");

+            m_factoryName = cm.getAttribute("name");

             return true;

         } else {

             System.err.println("A composite needs a name");

@@ -165,10 +165,10 @@
         computeFactoryState();

         

         // Check if the factory should be exposed

-        if (m_factoryName == null) { return; }

-        

-        // Exposition of the factory service

-        m_sr = m_context.registerService(new String[] { Factory.class.getName() }, this, getProperties());

+        if (m_isPublic) {

+            // Exposition of the factory service

+            m_sr = m_context.registerService(new String[] { Factory.class.getName() }, this, getProperties());

+        }

     }

     

     

@@ -191,7 +191,6 @@
         props.put("factory.state", "" + m_state);

         

         props.put("factory.name", m_factoryName);

-        props.put("component.type", m_typeName);

         

         return props;

     }

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeManager.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeManager.java
index 8658764..69eb78f 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeManager.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/CompositeManager.java
@@ -147,7 +147,7 @@
 
         // Cleaning
         m_state = DISPOSED;
-        for (int i = 0; i < m_handlers.length; i++) {
+        for (int i = m_handlers.length - 1; i > -1; i--) {
             m_handlers[i].dispose();
         }
         m_handlers = new HandlerManager[0];
@@ -310,11 +310,18 @@
      */
     public void setState(int state) {
         if (m_state != state) {
-
-            // The state changed call the handler stateChange method
-            m_state = state;
-            for (int i = m_handlers.length - 1; i > -1; i--) {
-                m_handlers[i].getHandler().stateChanged(state);
+            if (state > m_state) {
+                // The state increases (Stopped = > IV, IV => V) => invoke handlers from the higher priority to the lower
+                m_state = state;
+                for (int i = 0; i < m_handlers.length; i++) {
+                    m_handlers[i].getHandler().stateChanged(state);
+                }
+            } else {
+                // The state decreases (V => IV, IV = > Stopped, Stopped => Disposed)
+                m_state = state;
+                for (int i = m_handlers.length - 1; i > -1; i--) {
+                    m_handlers[i].getHandler().stateChanged(state);
+                }
             }
             
             for (int i = 0; i < m_instanceListeners.size(); i++) {
@@ -419,7 +426,7 @@
         // Cleaning
         m_state = DISPOSED;
         
-        for (int i = 0; i < m_handlers.length; i++) {
+        for (int i = m_handlers.length - 1; i > -1; i--) {
             m_handlers[i].dispose();
         }
         m_handlers = new HandlerManager[0];
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java
index 762bd3a..4293a98 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/Handler.java
@@ -46,6 +46,11 @@
      * Handler type property. 
      */
     public static final String HANDLER_TYPE_PROPERTY = "handler.type";
+
+    /**
+     * Handler priority.
+     */
+    public static final String HANDLER_LEVEL_PROPERTY = "handler.level";
     
     /**
      * Log method.
@@ -86,7 +91,7 @@
      */
     public final boolean isValid() {
         if (this instanceof Pojo) {
-            return getInstance().getState() == ComponentInstance.VALID;
+            return ((Pojo) this).getComponentInstance().getState() == ComponentInstance.VALID;
         } else {
             log(Logger.ERROR, "The handler is not a POJO : " + this.getClass().getName());
             return false;
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java
index 80f8aa0..6acf1a9 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerFactory.java
@@ -57,6 +57,13 @@
     private String m_namespace = IPojoConfiguration.IPOJO_NAMESPACE;

 

     /**

+     * Get the handler start level.

+     * Lower level are priority are configured and started before higher level, and are stopped after.

+     * 

+     */

+    private int m_level = Integer.MAX_VALUE;

+

+    /**

      * Create a composite factory.

      * @param bc : bundle context

      * @param cm : metadata of the component to create

@@ -66,7 +73,7 @@
         

         // Get the name

         if (cm.containsAttribute("name")) {

-            m_typeName = cm.getAttribute("name").toLowerCase();

+            m_factoryName = cm.getAttribute("name").toLowerCase();

         } else {

             System.err.println("An Handler needs a name");

             return;

@@ -77,6 +84,10 @@
             m_type = cm.getAttribute("type");

         }

         

+        if (cm.containsAttribute("level")) {

+            m_level = new Integer(cm.getAttribute("level")).intValue();

+        }

+        

         // Get the namespace

         if (cm.containsAttribute("namespace")) {

             m_namespace = cm.getAttribute("namespace").toLowerCase();

@@ -94,6 +105,10 @@
     public String getType() {

         return m_type;

     }

+    

+    public int getStartLevel() {

+        return m_level;

+    }

 

     /**

      * Start all the instance managers.

@@ -119,9 +134,6 @@
                 

         computeFactoryState();

         

-        // Check if the factory should be exposed

-        if (m_factoryName == null) { return; }

-        

         // Exposition of the factory service

         m_sr = m_context.registerService(new String[] { Factory.class.getName()}, this, getProperties());

     }

@@ -164,9 +176,12 @@
     protected Properties getProperties() {

         final Properties props = super.getProperties();

 

-        props.put(Handler.HANDLER_NAME_PROPERTY, m_typeName);

+        props.put(Handler.HANDLER_NAME_PROPERTY, m_factoryName);

         props.put(Handler.HANDLER_NAMESPACE_PROPERTY, m_namespace);

         props.put(Handler.HANDLER_TYPE_PROPERTY, m_type);

+        if (m_level != Integer.MAX_VALUE) {

+            props.put(Handler.HANDLER_LEVEL_PROPERTY, new Integer(m_level));

+        }

         

         return props;

     }

@@ -183,7 +198,7 @@
      * @throws org.apache.felix.ipojo.ConfigurationException : when the instance configuration failed.

      * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)

      */

-    public ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {

+    public synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, org.apache.felix.ipojo.ConfigurationException {

         if (m_state == INVALID) {

             throw new MissingHandlerException(getMissingHandlers());

         }

@@ -225,7 +240,8 @@
             HandlerIdentifier hi = (HandlerIdentifier) m_handlerIdentifiers.get(i);

             handlers.add(getHandlerInstance(hi, serviceContext));

         }

-        HandlerManager instance = new HandlerManager(this, context, (HandlerManager[]) handlers.toArray(new HandlerManager[0]));

+        

+        HandlerManager instance = new HandlerManager(this, context, (HandlerManager[]) handlers.toArray(new HandlerManager[handlers.size()]));

         instance.configure(m_componentMetadata, configuration);

 

         m_componentInstances.put(in, instance);

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
index 5f8edcc..f4b37c8 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
@@ -272,6 +272,14 @@
         }
         return used;
     }
+    
+    /**
+     * A matching service has been added to the tracker.
+     * Nothing to do, as all action are computed in the adding method.
+     * @param ref : added reference.
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
+     */
+    public void addedService(ServiceReference ref) { }
 
     /**
      * A used factory is modified.
@@ -279,9 +287,7 @@
      * @param obj : factory object.
      * @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
      */
-    public void modifiedService(ServiceReference ref, Object obj) {
-        // Nothing to do.
-    }
+    public void modifiedService(ServiceReference ref, Object obj) { }
 
     /**
      * A used factory disappears.
@@ -291,10 +297,14 @@
      * @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
      */
     public void removedService(ServiceReference ref, Object obj) {
-        Factory fact = (Factory) obj;
+        String name = (String) ref.getProperty("factory.name");
+        if (name == null) { return; }
         for (int i = 0; i < m_configurations.length; i++) {
-            if (m_configurations[i].getInstance() != null && m_configurations[i].getFactory().equals(fact.getName())) {
-                m_configurations[i].setInstance(null);
+            if (m_configurations[i].getFactory() != null && m_configurations[i].getFactory().equals(name)) {
+                if (m_configurations[i].getInstance() != null) {
+                    m_configurations[i].getInstance().dispose();
+                    m_configurations[i].setInstance(null);
+                }
                 m_configurations[i].setFactory(null);
             }
         }
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 ab1d6ab..6a59d0f 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
@@ -151,7 +151,7 @@
 
         String[] objects = new String[getPojoObjects().length];
         for (int i = 0; i < getPojoObjects().length; i++) {
-            objects[i] = getPojoObjects()[i].toString();
+            objects[i] = "" + getPojoObjects()[i];
         }
         instanceDescription.setCreatedObjects(objects);
 
@@ -194,9 +194,9 @@
      * Start the instance manager.
      */
     public synchronized void start() {
-        if (m_state != STOPPED) {
+        if (m_state != STOPPED) { // Instance already started
             return;
-        } // Instance already started
+        } 
         
         for (int i = 0; i < m_handlers.length; i++) {
             m_handlers[i].addInstanceStateListener(this);
@@ -204,6 +204,7 @@
         }
         
         for (int i = 0; i < m_handlers.length; i++) {
+            
             if (m_handlers[i].getState() != VALID) {
                 setState(INVALID);
                 return;
@@ -253,7 +254,7 @@
         
         m_factory.disposed(this);
         
-        for (int i = 0; i < m_handlers.length; i++) {
+        for (int i = m_handlers.length - 1; i > -1; i--) {
             m_handlers[i].dispose();
         }
         
@@ -300,7 +301,7 @@
      * the second call is stored and executed after the first one is finished.
      * @param state : the new state
      */
-    public void setState(int state) {
+    public synchronized void setState(int state) {
         if (m_inTransition) {
             m_stateQueue.add(new Integer(state)); 
             return;
@@ -309,10 +310,18 @@
         if (m_state != state) {
             m_inTransition = true;
 
-            // The state changed call the handler stateChange method
-            m_state = state;
-            for (int i = m_handlers.length - 1; i > -1; i--) {
-                m_handlers[i].getHandler().stateChanged(state);
+            if (state > m_state) {
+                // The state increases (Stopped = > IV, IV => V) => invoke handlers from the higher priority to the lower
+                m_state = state;
+                for (int i = 0; i < m_handlers.length; i++) {
+                    m_handlers[i].getHandler().stateChanged(state);
+                }
+            } else {
+                // The state decreases (V => IV, IV = > Stopped, Stopped => Disposed)
+                m_state = state;
+                for (int i = m_handlers.length - 1; i > -1; i--) {
+                    m_handlers[i].getHandler().stateChanged(state);
+                }
             }
             
             for (int i = 0; i < m_instanceListeners.size(); i++) {
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/CompositeServiceContext.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/CompositeServiceContext.java
index 1819862..d3449d6 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/CompositeServiceContext.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/CompositeServiceContext.java
@@ -439,11 +439,19 @@
      */
     public boolean addingService(ServiceReference reference) {
         if (!containsRef(reference)) {
-            importFactory(reference);
             return true;
         }
         return false;
     }
+    
+    /**
+     * A matching reference has been added. The import factory can now be imported.
+     * @param reference : the added reference.
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
+     */
+    public void addedService(ServiceReference reference) {
+        importFactory(reference);
+    }
 
     /**
      * An imported factory is modified.
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceExporter.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceExporter.java
index efb7fa1..52347c5 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceExporter.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceExporter.java
@@ -232,6 +232,15 @@
      * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
      */
     public boolean addingService(ServiceReference reference) {
+        return true;
+    }
+    
+    /**
+     * A service has been added in the tracker. Can now thest the validity of the exporter.
+     * @param reference : the new reference.
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
+     */
+    public void addedService(ServiceReference reference) {
         Record rec = new Record();
         rec.m_ref = reference;
         m_records.add(rec);
@@ -245,8 +254,6 @@
             m_isValid = true;
             m_handler.validating(this);
         }
-        
-        return true;
     }
 
     /**
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceImporter.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceImporter.java
index c16f0e4..9118fd2 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceImporter.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/importer/ServiceImporter.java
@@ -305,13 +305,24 @@
      * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
      */
     public boolean addingService(ServiceReference reference) {
-        // Else add it to the record list
+        for (int i = 0; i < m_records.size(); i++) {
+            Record rec = (Record) m_records.get(i);
+            if (rec.m_ref == reference) {
+                return false; // Already contained
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * The given service reference was added inside the tracker list.
+     * Register the internal service.
+     * @param reference : added reference
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
+     */
+    public void addedService(ServiceReference reference) {
         Record rec = new Record();
         rec.m_ref = reference;
-        if (m_records.contains(rec)) {
-            return false;
-        }
-        
         m_records.add(rec);
         // Publishing ?
         if (m_records.size() == 1 || m_aggregate) { // If the service is the first one, or if it is a multiple imports
@@ -323,7 +334,6 @@
             m_isValid = true;
             m_handler.validating(this);
         }
-        return true;
     }
 
     /**
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java
index c292eae..a738675 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/composite/service/instantiator/SvcInstance.java
@@ -227,12 +227,12 @@
     }
 
     /**
-     * Does the service instance match with the given factory.
-     * 
+     * Does the service instance match with the given factory ?
      * @param fact : the factory to test.
      * @return true if the factory match, false otherwise.
      */
     private boolean match(Factory fact) {
+        //TODO : use the service reference instead of the factory object to avoid to get the factory.
         // Check if the factory can provide the specification
         Element[] provides = fact.getDescription().getElements("provides");
         for (int i = 0; i < provides.length; i++) {
@@ -316,23 +316,6 @@
     public boolean addingService(ServiceReference reference) {
         Factory fact = (Factory) m_tracker.getService(reference);
         if (match(fact)) {
-            if (m_isAggregate) { // Create an instance for the new factory
-                m_usedRef.put(reference, createInstance(fact));
-                if (!m_isValid) {
-                    m_isValid = true;
-                    m_handler.validate();
-                }
-            } else {
-                if (!isAnInstanceCreated()) {
-                    m_usedRef.put(reference, createInstance(fact));
-                } else {
-                    m_usedRef.put(reference, null); // Store the reference
-                }
-                if (!m_isValid) {
-                    m_isValid = true;
-                    m_handler.validate();
-                }
-            }
             m_tracker.ungetService(reference);
             return true;
         } else {
@@ -341,6 +324,33 @@
         }
         
     }
+    
+    /**
+     * A matching service reference has been added in the tracker. 
+     * @param reference : added reference.
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
+     */
+    public void addedService(ServiceReference reference) {
+        Factory fact = (Factory) m_tracker.getService(reference);
+        if (m_isAggregate) { // Create an instance for the new factory
+            m_usedRef.put(reference, createInstance(fact));
+            if (!m_isValid) {
+                m_isValid = true;
+                m_handler.validate();
+            }
+        } else {
+            if (!isAnInstanceCreated()) {
+                m_usedRef.put(reference, createInstance(fact));
+            } else {
+                m_usedRef.put(reference, null); // Store the reference
+            }
+            if (!m_isValid) {
+                m_isValid = true;
+                m_handler.validate();
+            }
+        }
+        m_tracker.ungetService(reference);
+    }
 
     /**
      * A used factory was modified.
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 7638049..9c890b2 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
@@ -172,6 +172,8 @@
         if (policy != -1) {
             m_policy = policy;
         }
+        // TODO : Add binding policy too
+        
         // Fix the policy according to the level
         if ((m_policy == PolicyServiceContext.LOCAL_AND_GLOBAL || m_policy == PolicyServiceContext.LOCAL) && ! ((((IPojoContext) m_handler.getInstanceManager().getContext()).getServiceContext()) instanceof CompositeServiceContext)) {
             // We are not in a composite : BOTH | STRICT => GLOBAL
@@ -254,15 +256,6 @@
         return set;
     }
 
-//    /**
-//     * A dependency is satisfied if it is optional or there is useful references.
-//     * 
-//     * @return true is the dependency is satisfied
-//     */
-//    protected boolean isSatisfied() {
-//        return m_isOptional || m_tracker.size() != 0;
-//    }
-
     /**
      * This method is called by the replaced code in the component
      * implementation class. Construct the service object list is necessary.
@@ -270,7 +263,9 @@
      * @return null or a service object or a list of service object according to
      * the dependency.
      */
-    protected Object get() {
+    Object get() {
+        //TODO in static policy, the set of used service is frozen.
+        
         // Initialize the thread local object is not already touched.
         if (m_usage.getObjects().isEmpty()) {
             if (isAggregate()) {
@@ -282,7 +277,7 @@
                     }
                 }
             } else {
-                if (m_tracker.size() == 0) {
+                if (m_tracker.getServiceReferences() == null) {
                     // Load the nullable class
                     String className = m_specification + "Nullable";
                     Class nullableClazz = m_handler.getNullableClass(className);
@@ -326,7 +321,7 @@
         }
 
         if (m_isAggregate) { // Multiple dependency
-            return (Object[]) m_usage.getObjects().toArray((Object[]) Array.newInstance(m_clazz, 0));
+            return (Object[]) m_usage.getObjects().toArray((Object[]) Array.newInstance(m_clazz, m_usage.getObjects().size()));
         } else {
             return m_usage.getObjects().get(0);
         }
@@ -365,7 +360,7 @@
      * @param ref : service reference
      * @return the service object
      */
-    private Object getService(ServiceReference ref) {
+    private synchronized Object getService(ServiceReference ref) {
         if (!m_usedReferences.contains(ref)) {
             m_usedReferences.add(ref);
         }
@@ -377,41 +372,34 @@
      * @param ref : service reference to unget
      */
     private void ungetService(ServiceReference ref) {
-        m_serviceContext.ungetService(ref);
+        m_tracker.ungetService(ref);
     }
 
     /**
      * Call the bind method.
      * @param instance : instance on which calling the bind method.
      */
-    protected void callBindMethod(Object instance) {
+    protected synchronized void callBindMethod(Object instance) {
         if (m_tracker == null) { return; }
         // Check optional case : nullable object case : do not call bind on nullable object
-        if (m_isOptional && m_tracker.size() == 0) {
-            return;
-        }
+        if (m_isOptional && m_tracker.getServiceReferences() == null) { return; }
 
         if (m_isAggregate) {
-            synchronized (m_tracker) {
-                ServiceReference[] refs = m_tracker.getServiceReferences();
-                for (int i = 0; i < refs.length; i++) {
-                    for (int j = 0; j < m_callbacks.length; j++) {
-                        if (m_callbacks[j].getMethodType() == DependencyCallback.BIND) {
-                            try {
-                                m_callbacks[j].callOnInstance(instance, refs[i], getService(refs[i]));
-                            } catch (NoSuchMethodException e) {
-                                m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " does not exist in the class "
-                                                + m_handler.getInstanceManager().getClassName());
-                                return;
-                            } catch (IllegalAccessException e) {
-                                m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " is not accessible in the class "
-                                                + m_handler.getInstanceManager().getClassName());
-                                return;
-                            } catch (InvocationTargetException e) {
-                                m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName()
-                                                + "thorws an exception : " + e.getMessage());
-                                return;
-                            }
+            ServiceReference[] refs = m_tracker.getServiceReferences();
+            for (int i = 0; refs != null && i < refs.length; i++) {
+                for (int j = 0; j < m_callbacks.length; j++) {
+                    if (m_callbacks[j].getMethodType() == DependencyCallback.BIND) {
+                        try {
+                            m_callbacks[j].callOnInstance(instance, refs[i], getService(refs[i]));
+                        } catch (NoSuchMethodException e) {
+                            m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
+                            return;
+                        } catch (IllegalAccessException e) {
+                            m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
+                            return;
+                        } catch (InvocationTargetException e) {
+                            m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName() + "thorws an exception : " + e.getMessage());
+                            return;
                         }
                     }
                 }
@@ -421,18 +409,17 @@
                 if (m_callbacks[j].getMethodType() == DependencyCallback.BIND) {
                     try {
                         ServiceReference ref = m_tracker.getServiceReference();
-                        m_callbacks[j].callOnInstance(instance, ref, getService(ref));
+                        if (ref != null) {
+                            m_callbacks[j].callOnInstance(instance, ref, getService(ref));
+                        }
                     } catch (NoSuchMethodException e) {
-                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " does not exist in the class "
-                                        + m_handler.getInstanceManager().getClassName());
+                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
                         return;
                     } catch (IllegalAccessException e) {
-                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " is not accessible in the class "
-                                        + m_handler.getInstanceManager().getClassName());
+                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
                         return;
                     } catch (InvocationTargetException e) {
-                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName()
-                                        + "throws an exception : " + e.getMessage());
+                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[j].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName() + "throws an exception : " + e.getMessage());
                         return;
                     }
                 }
@@ -446,23 +433,21 @@
      */
     private void callBindMethod(ServiceReference ref) {
         // call bind method :
-       // if (m_handler.getInstanceManager().getState() == InstanceManager.VALID) {
+        // if (m_handler.getInstanceManager().getState() == InstanceManager.VALID) {
         if (m_handler.getInstanceManager().getState() > InstanceManager.STOPPED && m_handler.getInstanceManager().getPojoObjects().length > 0) {
             for (int i = 0; i < m_callbacks.length; i++) {
                 if (m_callbacks[i].getMethodType() == DependencyCallback.BIND) {
                     try {
                         m_callbacks[i].call(ref, getService(ref));
+                        ungetService(ref);
                     } catch (NoSuchMethodException e) {
-                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " does not exist in the class "
-                                        + m_handler.getInstanceManager().getClassName());
+                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " does not exist in the class " + m_handler.getInstanceManager().getClassName());
                         return;
                     } catch (IllegalAccessException e) {
-                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " is not accessible in the class "
-                                        + m_handler.getInstanceManager().getClassName());
+                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " is not accessible in the class " + m_handler.getInstanceManager().getClassName());
                         return;
                     } catch (InvocationTargetException e) {
-                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName()
-                                        + "throws an exception : " + e.getMessage());
+                        m_handler.log(Logger.ERROR, "The method " + m_callbacks[i].getMethodName() + " in the class " + m_handler.getInstanceManager().getClassName() + "throws an exception : " + e.getMessage());
                         return;
                     }
                 }
@@ -501,7 +486,7 @@
             m_handler.log(Logger.ERROR, "[" + m_handler.getInstanceManager().getClassName() + "] A filter is malformed : " + filter + " - " + e1.getMessage());
             return;
         }
-        
+        //TODO : Add binding (dynamic priority against normal) policy, i.e. comparator.  
         m_tracker = new Tracker(m_serviceContext, m_filter, this);
         m_tracker.open();
         if (m_tracker.size() == 0 && !m_isOptional) {
@@ -516,18 +501,12 @@
      */
     public void stop() {
         if (m_tracker != null) {
-            m_tracker.close();
+            m_tracker.close(); // Will unget all used reference.
             m_tracker = null;
         }
-        
         m_handler.log(Logger.INFO, "[" + m_handler.getInstanceManager().getInstanceName() + "] Stop a dependency on : " + m_specification + " with " + m_strFilter + " (" + m_handler.getInstanceManager() + ")");
         m_state = UNRESOLVED;
 
-        // Unget all services references
-        for (int i = 0; i < m_usedReferences.size(); i++) {
-            ungetService((ServiceReference) m_usedReferences.get(i));
-        }
-
         m_usedReferences.clear();
         m_clazz = null;
     }
@@ -615,17 +594,27 @@
     * @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
     */
     public boolean addingService(ServiceReference ref) {
+        //TODO : according to the policy, do not add the new reference. Indeed in static policy is references are already used, new ones are ignored
         if (m_filter.match(ref)) {
-            m_state = RESOLVED;
-            if (m_isAggregate || m_tracker.size() == 0) {
-                callBindMethod(ref);
-            }
-            
-            m_handler.checkContext();
             return true;
         }
         return false;
     }
+    
+    /**
+     * A new service reference has been added in the tracker.
+     * Call the bind method if needed, and check the dependency context.
+     * @param reference : added reference.
+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
+     */
+    public void addedService(ServiceReference reference) {
+        m_state = RESOLVED;
+        if (m_isAggregate || m_tracker.getServiceReferences() != null) {
+            callBindMethod(reference);
+        }
+        
+        m_handler.checkContext();
+    }
 
     /**
      * A used service is modified.
@@ -650,10 +639,11 @@
             ungetService(ref);
             m_usedReferences.remove(ref);
             hasChanged = true;
+            //TODO in static policy, invalidate the instance, and close the tracking
         }
 
         // Is the state valid or invalid, the reference is already removed
-        if (m_tracker.size() == 0 && !m_isOptional) {
+        if (m_tracker.getServiceReferences() == null && !m_isOptional) {
             m_state = UNRESOLVED;
         } else {
             m_state = RESOLVED;
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 926b3ec..c7db95e 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
@@ -465,13 +465,13 @@
      * @return true if all dependencies are resolved.
      */
     private boolean validateComponentDependencies() {
-        boolean valide = true;
+        boolean valid = true;
         for (int i = 0; i < m_dependencies.length; i++) {
             Dependency dep = m_dependencies[i];
-            valide = valide & dep.getState() == Dependency.RESOLVED;
-            if (!valide) { return false; }
+            valid = valid & dep.getState() == Dependency.RESOLVED;
+            if (!valid) { return false; }
         }
-        return valide;
+        return valid;
     }
 
     /**
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 2f30e71..1962ae7 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
@@ -229,8 +229,9 @@
             }
             // 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/handlers/providedservice/ProvidedServiceHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
index 4ed2549..b66f917 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
@@ -414,8 +414,7 @@
 
     /**
      * Add properties to all provided services.
-     * 
-     * @param dict : dictionary fo properties to add
+     * @param dict : dictionary of properties to add
      */
     public void addProperties(Dictionary dict) {
         for (int i = 0; i < m_providedServices.length; i++) {
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Tracker.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Tracker.java
index 0c84d2e..b7e146e 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Tracker.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Tracker.java
@@ -34,10 +34,10 @@
 import org.osgi.framework.ServiceReference;

 

 /**

-* Utility class close to the OSGi Service Tracker.

-* 

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

-*/

+ * Utility class close to the OSGi Service Tracker.

+ * This class is used when tracking dynamic services is required.

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

+ */

 public class Tracker implements TrackerCustomizer {

 

     /**

@@ -219,7 +219,7 @@
         m_tracked.close();

         ServiceReference[] references = getServiceReferences();

         Tracked outgoing = m_tracked;

-        m_tracked = null;

+

         try {

             m_context.removeServiceListener(outgoing);

         } catch (IllegalStateException e) {

@@ -231,6 +231,7 @@
                 outgoing.untrack(references[i]);

             }

         }

+        m_tracked = null;

 

     }

 

@@ -250,6 +251,15 @@
     }

 

     /**

+     * Default implementation of the TrackerCustomizer.addedService method.  

+     * @param reference added reference.

+     * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)

+     */

+    public void addedService(ServiceReference reference) {

+

+    }

+

+    /**

      * Default implementation of the TrackerCustomizer.modifiedService method.

      * <p>

      * This method is only called when this Tracker object has been constructed with a null TrackerCustomizer argument. The default implementation does nothing.

@@ -323,12 +333,12 @@
             return references;

         }

     }

-    

+

     /**

      * Get the list of stored service reference.

      * @return the list containing used service reference

      */

-    public List/*<ServiceReference>*/ getServiceReferencesList() {

+    public List/*<ServiceReference>*/getServiceReferencesList() {

         Tracked tracked = this.m_tracked; // use local var since we are not synchronized

         if (tracked == null) { // if Tracker is not open

             return null;

@@ -379,7 +389,7 @@
         }

         Object object = null;

         synchronized (tracked) {

-            object =  tracked.get(reference);

+            object = tracked.get(reference);

             if (object != null) { // The object was already get.

                 return object;

             } else if (tracked.containsKey(reference)) { // Not already get

@@ -387,11 +397,11 @@
                 tracked.put(reference, object);

                 return object;

             }

+            // Not already tracked.

+            return m_context.getService(reference);

         }

-        // Not already tracked.

-        return m_context.getService(reference);

     }

-    

+

     /**

      * Unget the given service reference.

      * @param reference : service reference to unget.

@@ -405,7 +415,9 @@
         synchronized (tracked) {

             object = tracked.get(reference);

         }

-        if (object != null) { m_context.ungetService(reference); }

+        if (object != null) {

+            m_context.ungetService(reference);

+        }

     }

 

     /**

@@ -423,7 +435,7 @@
             if (references != null) {

                 length = references.length;

             } else {

-                return null; 

+                return null;

             }

             Object[] objects = new Object[length];

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

@@ -482,36 +494,37 @@
          * UID.

          */

         static final long serialVersionUID = -7420065199791006079L;

-    

+

         /**

          * List of ServiceReferences in the process of being added. This is used to deal with nesting of ServiceEvents. Since ServiceEvents are synchronously delivered, ServiceEvents can be nested. For example, when processing the adding of a service

          * and the customizer causes the service to be unregistered, notification to the nested call to untrack that the service was unregistered can be made to the track method. Since the ArrayList implementation is not synchronized, all access to

          * this list must be protected by the same synchronized object for thread safety.

          */

         private List m_adding;

-    

+

         /**

          * true if the tracked object is closed. This field is volatile because it is set by one thread and read by another.

          */

         private volatile boolean m_closed;

-    

+

         /**

          * Initial list of ServiceReferences for the tracker. This is used to correctly process the initial services which could become unregistered before they are tracked. This is necessary since the initial set of tracked services are not

          * "announced" by ServiceEvents and therefore the ServiceEvent for unregistration could be delivered before we track the service. A service must not be in both the initial and adding lists at the same time. A service must be moved from the

          * initial list to the adding list "atomically" before we begin tracking it. Since the LinkedList implementation is not synchronized, all access to this list must be protected by the same synchronized object for thread safety.

          */

         private List m_initial;

-    

+

         /**

          * Tracked constructor.

          */

         protected Tracked() {

+            //TODO : set the comparator according to the binding policy.

             super(new ReferenceComparator());

             m_closed = false;

             m_adding = new ArrayList(6);

             m_initial = new LinkedList();

         }

-    

+

         /**

          * Set initial list of services into tracker before ServiceEvents begin to be received. This method must be called from Tracker.open while synchronized on this object in the same synchronized block as the addServiceListener call.

          * @param references The initial list of services to be tracked.

@@ -523,7 +536,7 @@
                 m_initial.add(references[i]);

             }

         }

-    

+

         /**

          * Track the initial list of services. This is called after ServiceEvents can begin to be received. This method must be called from Tracker.open while not synchronized on this object after the addServiceListener call.

          */

@@ -534,7 +547,7 @@
                     if (m_initial.size() == 0) { //  if there are no more inital services

                         return; // we are done

                     }

-    

+

                     // move the first service from the initial list to the adding list within this synchronized block.

                     reference = (ServiceReference) ((LinkedList) m_initial).removeFirst();

                     if (this.containsKey(reference)) { //Check if the reference is already tracked.

@@ -550,14 +563,14 @@
                 trackAdding(reference); // Begin tracking it. We call trackAdding since we have already put the reference in the adding list.

             }

         }

-    

+

         /**

          * Called by the owning Tracker object when it is closed.

          */

         protected void close() {

             m_closed = true;

         }

-    

+

         /**

          * ServiceListener method for the Tracker class. This method must NOT be synchronized to avoid deadlock potential.

          * @param event ServiceEvent object from the framework.

@@ -566,7 +579,7 @@
             //Check if we had a delayed call (which could happen when we close).

             if (m_closed) { return; }

             ServiceReference reference = event.getServiceReference();

-    

+

             switch (event.getType()) {

                 case ServiceEvent.REGISTERED:

                 case ServiceEvent.MODIFIED:

@@ -587,7 +600,7 @@
                     break;

             }

         }

-    

+

         /**

          * Begin to track the referenced service.

          * @param reference Reference to a service to be tracked.

@@ -615,10 +628,10 @@
                 }

                 m_adding.add(reference); // mark this service is being added

             }

-    

+

             trackAdding(reference); // call trackAdding now that we have put the reference in the adding list

         }

-    

+

         /**

          * Common logic to add a service to the tracker used by track and trackInitialServices. The specified reference must have been placed in the adding list before calling this method.

          * @param reference Reference to a service to be tracked.

@@ -626,6 +639,7 @@
         private void trackAdding(ServiceReference reference) {

             boolean mustBeTracked = false;

             boolean becameUntracked = false;

+            boolean mustCallAdded = false;

             //Call customizer outside of synchronized region

             try {

                 mustBeTracked = m_customizer.addingService(reference);

@@ -634,23 +648,30 @@
                     if (m_adding.remove(reference)) { // if the service was not untracked during the customizer callback

                         if (mustBeTracked) {

                             this.put(reference, null);

-                            modified();

+                            modified(); 

+                            mustCallAdded = true;

                             notifyAll(); // notify any waiters in waitForService

                         }

                     } else {

                         becameUntracked = true;

+                        // If already get during the customizer callback

+                        ungetService(reference);

+                        modified();

                     }

                 }

             }

-            /*

-             * The service became untracked during the customizer callback.

-             */

+

+            // Call customizer outside of synchronized region

             if (becameUntracked) {

-                /* Call customizer outside of synchronized region */

+                // The service became untracked during the customizer callback.

                 m_customizer.removedService(reference, null);

+            } else {

+                if (mustCallAdded) {

+                    m_customizer.addedService(reference);

+                }

             }

         }

-    

+

         /**

          * Discontinue tracking the referenced service.

          * @param reference Reference to the tracked service.

@@ -661,15 +682,15 @@
                 if (m_initial.remove(reference)) { // if this service is already in the list of initial references to process

                     return; // we have removed it from the list and it will not be processed

                 }

-    

+

                 if (m_adding.remove(reference)) { // if the service is in the process of being added

                     return; // in case the service is untracked while in the process of adding

                 }

-                

+

                 boolean isTraked = this.containsKey(reference); // Check if we was tracking the reference 

                 object = this.remove(reference); // must remove from tracker before calling customizer callback

-                 

-                if (! isTraked) { return; }

+

+                if (!isTraked) { return; }

                 modified();

             }

             // Call customizer outside of synchronized region

@@ -685,11 +706,11 @@
             m_cachedReference = null; /* clear cached value */

             m_cachedService = null; /* clear cached value */

         }

-        

+

     }

 

     /**

-     *Service Reference Comparator.

+     * Service Reference Comparator.

      */

     private class ReferenceComparator implements Comparator {

 

@@ -701,27 +722,29 @@
          * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)

          */

         public int compare(Object ref1, Object ref2) {

-            if (ref1.equals(ref2)) {

-                return 0;

-            }

-            

-            if (ref1 instanceof ServiceReference && ref2 instanceof ServiceReference) {                

+            if (ref1.equals(ref2)) { return 0; }

+

+            if (ref1 instanceof ServiceReference && ref2 instanceof ServiceReference) {

                 Object property1 = ((ServiceReference) ref1).getProperty(Constants.SERVICE_RANKING);

                 Object property2 = ((ServiceReference) ref2).getProperty(Constants.SERVICE_RANKING);

-                

+

                 int rank1 = 0;

                 int rank2 = 0;

-                if (property1 instanceof Integer) { rank1 = ((Integer) property1).intValue(); }

-                if (property2 instanceof Integer) { rank2 = ((Integer) property2).intValue(); }

-                

+                if (property1 instanceof Integer) {

+                    rank1 = ((Integer) property1).intValue();

+                }

+                if (property2 instanceof Integer) {

+                    rank2 = ((Integer) property2).intValue();

+                }

+

                 if (rank1 == rank2) {

                     // Check service.id

                     Object sid1 = ((ServiceReference) ref1).getProperty(Constants.SERVICE_ID);

                     Object sid2 = ((ServiceReference) ref2).getProperty(Constants.SERVICE_ID);

-                    

+

                     long rankId1 = ((Long) sid1).longValue();

                     long rankId2 = ((Long) sid2).longValue();

-                    

+

                     if (rankId1 == rankId2) {

                         return 0;

                     } else if (rankId1 < rankId2) {

@@ -729,13 +752,13 @@
                     } else {

                         return 1;

                     }

-                    

+

                 } else if (rank1 > rank2) {

                     return 1;

                 } else {

                     return -1;

                 }

-                

+

             } else {

                 return 0;

             }

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/TrackerCustomizer.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/TrackerCustomizer.java
index 4e731d1..3312d85 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/TrackerCustomizer.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/TrackerCustomizer.java
@@ -34,6 +34,13 @@
      * @return The service object to be tracked for the ServiceReference object or null if the ServiceReference object should not be tracked.

      */

     boolean addingService(ServiceReference reference);

+    

+    /**

+     * A service tracked by the Tracker object has been added in the list.

+     * This method is called when a service has been added in the managed list (after addingService) and if the service has not disappeared before during the callback.

+     * @param reference the added reference.

+     */

+    void addedService(ServiceReference reference);

 

     /**

      * A service tracked by the Tracker object has been modified.

diff --git a/ipojo/core/src/main/resources/metadata.xml b/ipojo/core/src/main/resources/metadata.xml
index 6b16ad9..1095057 100644
--- a/ipojo/core/src/main/resources/metadata.xml
+++ b/ipojo/core/src/main/resources/metadata.xml
@@ -1,12 +1,12 @@
 <ipojo>

 <!-- Primitives handler -->

 <handler classname="org.apache.felix.ipojo.handlers.lifecycle.controller.ControllerHandler" name="controller"/>

-<handler classname="org.apache.felix.ipojo.handlers.lifecycle.callback.LifecycleCallbackHandler" name="callback"/>

-<handler classname="org.apache.felix.ipojo.handlers.dependency.DependencyHandler" name="requires">

+<handler classname="org.apache.felix.ipojo.handlers.lifecycle.callback.LifecycleCallbackHandler" name="callback" level="1"/>

+<handler classname="org.apache.felix.ipojo.handlers.dependency.DependencyHandler" name="requires" level="0">

 	<controller field="m_state"/>

 </handler>

-<handler classname="org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandler" name="provides"/>

-<handler classname="org.apache.felix.ipojo.handlers.configuration.ConfigurationHandler" name="properties"/>

+<handler classname="org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandler" name="provides" level="3"/>

+<handler classname="org.apache.felix.ipojo.handlers.configuration.ConfigurationHandler" name="properties" level="1"/>

 <handler classname="org.apache.felix.ipojo.handlers.architecture.ArchitectureHandler" name="architecture">

 	<provides>

 		<property field="m_name" name="instance.name" value=""/>

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 51db771..e3b6628 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
@@ -113,16 +113,16 @@
         String internalType = desc.substring(1);

         internalType = internalType.substring(0, internalType.length() - 2);

 

-        mv.visitVarInsn(ALOAD, 0);

-        mv.visitVarInsn(ALOAD, 1);

-        mv.visitFieldInsn(PUTFIELD, m_owner, name, internalType);

-

         Label l1 = new Label();

         mv.visitLabel(l1);

         mv.visitVarInsn(ALOAD, 0);

         mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");

         Label l2 = new Label();

         mv.visitJumpInsn(IFNE, l2);

+        //TODO move in

+        mv.visitVarInsn(ALOAD, 0);

+        mv.visitVarInsn(ALOAD, 1);

+        mv.visitFieldInsn(PUTFIELD, m_owner, name, internalType);

         mv.visitInsn(RETURN);

         mv.visitLabel(l2);

 

@@ -548,9 +548,6 @@
                 String internalName = ManipulationProperty.PRIMITIVE_BOXING_INFORMATION[type.getSort()][0];

                 String boxingType = ManipulationProperty.PRIMITIVE_BOXING_INFORMATION[type.getSort()][1];

 

-                mv.visitVarInsn(ALOAD, 0);

-                mv.visitVarInsn(type.getOpcode(ILOAD), 1);

-                mv.visitFieldInsn(PUTFIELD, m_owner, name, internalName);

                 Label l1 = new Label();

                 mv.visitLabel(l1);

 

@@ -558,6 +555,10 @@
                 mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");

                 Label l22 = new Label();

                 mv.visitJumpInsn(IFNE, l22);

+                //TODO move in

+                mv.visitVarInsn(ALOAD, 0);

+                mv.visitVarInsn(type.getOpcode(ILOAD), 1);

+                mv.visitFieldInsn(PUTFIELD, m_owner, name, internalName);

                 mv.visitInsn(RETURN);

                 mv.visitLabel(l22);

 

@@ -585,9 +586,6 @@
                 internalName = ManipulationProperty.PRIMITIVE_BOXING_INFORMATION[type.getSort()][0];

                 boxingType = ManipulationProperty.PRIMITIVE_BOXING_INFORMATION[type.getSort()][1];

 

-                mv.visitVarInsn(ALOAD, 0);

-                mv.visitVarInsn(type.getOpcode(ILOAD), 1);

-                mv.visitFieldInsn(PUTFIELD, m_owner, name, internalName);

                 l1 = new Label();

                 mv.visitLabel(l1);

 

@@ -595,6 +593,10 @@
                 mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");

                 Label l23 = new Label();

                 mv.visitJumpInsn(IFNE, l23);

+                //TODO move in

+                mv.visitVarInsn(ALOAD, 0);

+                mv.visitVarInsn(type.getOpcode(ILOAD), 1);

+                mv.visitFieldInsn(PUTFIELD, m_owner, name, internalName);

                 mv.visitInsn(RETURN);

                 mv.visitLabel(l23);

 

@@ -619,13 +621,13 @@
 

             case Type.OBJECT:

                 mv.visitVarInsn(ALOAD, 0);

-                mv.visitVarInsn(ALOAD, 1);

-                mv.visitFieldInsn(PUTFIELD, m_owner, name, "L" + type.getInternalName() + ";");

-

-                mv.visitVarInsn(ALOAD, 0);

                 mv.visitFieldInsn(GETFIELD, m_owner, "_F" + name, "Z");

                 Label l24 = new Label();

                 mv.visitJumpInsn(IFNE, l24);

+                //TODO move in

+                mv.visitVarInsn(ALOAD, 0);

+                mv.visitVarInsn(ALOAD, 1);

+                mv.visitFieldInsn(PUTFIELD, m_owner, name, "L" + type.getInternalName() + ";");

                 mv.visitInsn(RETURN);

                 mv.visitLabel(l24);