* Fix issue Felix-803:
  The core xml schema accepted the 'interface' attribute in service dependencies. This attribute were replaced by 'specification' to be consistent with other service dependencies.
  The 'interface' attribute is now prohibited.

* Fix issue Felix-805:
  Instances were not created when the targeted factory becomes valid later.

* Add a mechanism to avoid that setter methods are called twice if two threads try to invoke the callback with the same value.


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@711559 13f79535-47bb-0310-9956-ffa450edef68
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 2f25cde..988b1f0 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
@@ -72,22 +72,26 @@
      * @param bundle the bundle id declaring the instance
      */
     synchronized void addInstance(Dictionary instance, long bundle) {
+        m_logger.log(Logger.DEBUG, "New instance to managed, looking for " + instance.get("component"));
         ManagedInstance managed = new ManagedInstance(instance, bundle);
         for (int i = 0; i < m_factories.size(); i++) {
             IPojoFactory factory = (IPojoFactory) m_factories.get(i);
-            if (factory.getState() == Factory.VALID && managed.match(factory)) {
-                managed.create(factory);
-                List list = (List) m_attached.get(factory);
-                if (list == null) {
-                    list = new ArrayList();
-                    list.add(managed);
-                    m_attached.put(factory, list);
-                    // Subscribe to the factory state change
-                    factory.addFactoryStateListener(this);
-                } else {
-                    list.add(managed);
+            if (managed.matchName(factory)) {
+                // Subscribe to the factory state change
+                m_logger.log(Logger.DEBUG, "Listen factory " + factory.getName() + " events");
+                factory.addFactoryStateListener(this);
+                if (factory.getState() == Factory.VALID && managed.match(factory)) {
+                    managed.create(factory);
+                    List list = (List) m_attached.get(factory);
+                    if (list == null) {
+                        list = new ArrayList();
+                        list.add(managed);
+                        m_attached.put(factory, list);  
+                    } else {
+                        list.add(managed);
+                    }
+                    return;
                 }
-                return;
             }
         }
         // If there is no matching factory, add the instance to the idle list
@@ -144,13 +148,14 @@
      */
     public synchronized void addFactory(IPojoFactory factory) {
         List createdInstances = new ArrayList(1);
+        m_logger.log(Logger.DEBUG, "Add the factory " + factory.getName());
         m_factories.add(factory);
         for (int i = 0; i < m_idle.size(); i++) {
             ManagedInstance managed = (ManagedInstance) m_idle.get(i);
-            if (managed.match(factory)) {
+            if (managed.matchName(factory)) {
                 // We have to subscribe to the factory.
                 factory.addFactoryStateListener(this);
-                if (factory.getState() == Factory.VALID) {
+                if (factory.getState() == Factory.VALID && managed.match(factory)) {
                     managed.create(factory);
                     List list = (List) m_attached.get(factory);
                     if (list == null) {
@@ -229,8 +234,10 @@
      */
     public void stateChanged(Factory factory, int newState) {
         if (newState == Factory.VALID) {
+            m_logger.log(Logger.DEBUG, "A factory is becoming valid : " + factory.getName());
             onValidation((IPojoFactory) factory);
         } else {
+            m_logger.log(Logger.DEBUG, "A factory is bocoming invalid : " + factory.getName());
             onInvalidation((IPojoFactory) factory);
         }
     }
@@ -286,6 +293,19 @@
         ComponentInstance getInstance() {
             return m_instance;
         }
+        
+        
+        /**
+         * Checks if the required factory name match with the given factory.
+         * This methods checks only the name, and not the configuration.
+         * @param factory the factory to test
+         * @return <code>true</code> if the factory name matches, <code>false</code>
+         * otherwise.
+         */
+        public boolean matchName(IPojoFactory factory) {
+            String component = (String) m_configuration.get("component");
+            return factory.getName().equals(component) || factory.getClassName().equalsIgnoreCase(component);
+        }
 
         /**
          * Checks if the given factory match with the factory 
@@ -298,8 +318,7 @@
          */
         public boolean match(IPojoFactory factory) {
             // Test factory name (and classname)
-            String component = (String) m_configuration.get("component");
-            if (factory.getName().equals(component) || factory.getClassName().equalsIgnoreCase(component)) {
+            if (matchName(factory)) {
                 // Test factory accessibility
                 if (factory.m_isPublic || factory.getBundleContext().getBundle().getBundleId() == m_bundleId) {
                     // Test the configuration validity.
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
index 68fed56..ea44b1e 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
@@ -123,13 +123,17 @@
      * @param msg the message to log
      */
     private void dispatch(int level, String msg) {
-        
-        ServiceReference ref = m_context.getServiceReference(LogService.class.getName());
         LogService log = null;
-        if (ref != null) {
-            log = (LogService) m_context.getService(ref);
+        ServiceReference ref = null;
+        try {
+            ref = m_context.getServiceReference(LogService.class.getName());
+            if (ref != null) {
+                log = (LogService) m_context.getService(ref);
+            }
+        } catch (IllegalStateException e) {
+            // Handle the case where the iPOJO bundle is stopping
         }
-        
+
         String message = null;
         switch (level) {
             case DEBUG:
@@ -182,11 +186,15 @@
      * @param exception the exception attached to the message
      */
     private void dispatch(int level, String msg, Throwable exception) {
-        
-        ServiceReference ref = m_context.getServiceReference(LogService.class.getName());
         LogService log = null;
-        if (ref != null) {
-            log = (LogService) m_context.getService(ref);
+        ServiceReference ref = null;
+        try {
+            ref = m_context.getServiceReference(LogService.class.getName());
+            if (ref != null) {
+                log = (LogService) m_context.getService(ref);
+            }
+        } catch (IllegalStateException e) {
+            // Handle the case where the iPOJO bundle is stopping
         }
         
         String message = null;
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
index 643f41a..a022d71 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
@@ -454,11 +454,10 @@
         try {

             if (instance == null) {

                 m_method.call(new Object[] { m_value });

-                m_invoked = true;

             } else {

                 m_method.call(instance, new Object[] { m_value });

-                m_invoked = true;

             }

+            m_invoked = true;

         } catch (NoSuchMethodException e) {

             m_handler.error("The method " + m_method + " does not exist in the implementation class " + m_manager.getClassName());

             m_manager.stop();

diff --git a/ipojo/core/src/main/resources/core.xsd b/ipojo/core/src/main/resources/core.xsd
index c89b193..9cdbfcf 100644
--- a/ipojo/core/src/main/resources/core.xsd
+++ b/ipojo/core/src/main/resources/core.xsd
@@ -218,12 +218,12 @@
 				</xs:sequence>
 				
 				<xs:attribute name="interface" type="xs:string"
-				    use="optional">
+				    use="prohibited">
                     <xs:annotation>
-                    	<xs:documentation>The interface describing the required service type. This attribute is needed only when using aggregate dependencies with field injection and when the type of this field is a list, vector, collection and set. This attribute is deprecated.</xs:documentation>
+                    	<xs:documentation>The interface describing the required service type. This attribute is needed only when using aggregate dependencies with field injection and when the type of this field is a list, vector, collection and set. This attribute is deprecated, use 'specification'.</xs:documentation>
                     </xs:annotation>
 				</xs:attribute>
-
+				
 				<xs:attribute name="field" type="xs:string"
 					use="optional">
                     <xs:annotation>