- Modify the level of the two messages displayed when iPOJO is starting.
- Add the possibility to disable the Nullable Pattern by adding nullable="false" in the service requirement attribute. So, iPOJO injects null instead of a Nullable object when no providers are available.
- Add tests on the Nullable deactivation.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@646835 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
index fd9ab38..47b754a 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/Extender.java
@@ -205,7 +205,7 @@
             }

             ManagedAbstractFactoryType mft = new ManagedAbstractFactoryType(clazz, type, bundle);

             m_factoryTypes.add(mft);

-            m_logger.log(Logger.WARNING, "New factory type available: " + type);

+            m_logger.log(Logger.INFO, "New factory type available: " + type);

 

             for (int j = m_unboundTypes.size() - 1; j >= 0; j--) {

                 UnboundComponentType unbound = (UnboundComponentType) m_unboundTypes.get(j);

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 9b3c0e3..274a092 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
@@ -87,6 +87,11 @@
      * Default-Implementation.
      */
     private String m_di;
+    
+    /**
+     * Is the Nullable pattern enable?
+     */
+    private boolean m_supportNullable;
 
     /**
      * Id of the dependency.
@@ -102,19 +107,22 @@
      * @param filter : LDAP filter of the dependency
      * @param isOptional : is the dependency an optional dependency ?
      * @param isAggregate : is the dependency an aggregate dependency
+     * @param nullable : describe if the nullable ability is enable or disable
      * @param identity : id of the dependency, may be null
      * @param context : bundle context (or service context) to use.
      * @param policy : resolution policy
      * @param cmp : comparator to sort references
      * @param defaultImplem : default-implementation class
      */
-    public Dependency(DependencyHandler handler, String field, Class spec, Filter filter, boolean isOptional, boolean isAggregate, String identity, BundleContext context, int policy, Comparator cmp, String defaultImplem) {
+    public Dependency(DependencyHandler handler, String field, Class spec, Filter filter, boolean isOptional, boolean isAggregate, boolean nullable, String identity, BundleContext context, int policy, Comparator cmp, String defaultImplem) {
         super(spec, isAggregate, isOptional, filter, cmp, policy, context, handler);
         m_handler = handler;
         if (field != null) {
             m_field = field;
             m_usage = new ServiceUsage();
         }
+        
+        m_supportNullable = nullable;
         m_di = defaultImplem;
 
         if (identity == null) {
@@ -277,12 +285,19 @@
     /**
      * Start the dependency.
      */
-    public void start() {        
+    public void start() {
         if (isOptional() && !isAggregate()) {
             if (m_di == null) {
-                // To load the proxy we use the POJO class loader. Indeed, this classloader imports iPOJO (so can access to Nullable) and has access to the service specification.
-                m_nullable = Proxy.newProxyInstance(getHandler().getInstanceManager().getClazz().getClassLoader(), new Class[] { getSpecification(), Nullable.class }, new NullableObject()); // NOPMD
+                // If nullable are supported, create the nullable object.
+                if (m_supportNullable) {
+                    // To load the proxy we use the POJO class loader. Indeed, this classloader imports iPOJO (so can access to Nullable) and has
+                    // access to the service specification.
+                    m_nullable =
+                            Proxy.newProxyInstance(getHandler().getInstanceManager().getClazz().getClassLoader(), new Class[] {
+                                    getSpecification(), Nullable.class }, new NullableObject()); // NOPMD
+                }
             } else {
+                // Create the default-implementation object.
                 try {
                     Class clazz = getHandler().getInstanceManager().getContext().getBundle().loadClass(m_di);
                     m_nullable = clazz.newInstance();
@@ -394,15 +409,14 @@
                         usage.m_objects[i] = getService(ref);
                     }
                 }
-            } else { // We are singular.
+            } else { // We are not aggregate.
                 // Use a reflective construction to avoid class cast exception. This method allow to set the component type.
                 usage.m_objects = (Object[]) Array.newInstance(getSpecification(), 1);
                 if (refs == null) {
-                    if (m_nullable == null) {
+                    if (m_nullable == null && m_supportNullable) {
                         m_handler.warn("[" + m_handler.getInstanceManager().getInstanceName() + "] The dependency is not optional, however no service object can be injected in " + m_field + " -> " + getSpecification().getName());
-                        return null;
                     }
-                    usage.m_objects[0] = m_nullable;
+                    usage.m_objects[0] = m_nullable; // Add null if the Nullable pattern is disable.
                 } else {
                     ServiceReference ref = getServiceReference();
                     usage.m_objects[0] = getService(ref);
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 5a0f4d8..fe50970 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
@@ -280,6 +280,9 @@
             String agg = deps[i].getAttribute("aggregate");
             boolean aggregate = agg != null && agg.equalsIgnoreCase("true");
             String identitity = deps[i].getAttribute("id");
+            
+            String nul = deps[i].getAttribute("nullable");
+            boolean nullable = nul == null || nul.equalsIgnoreCase("true");
 
             String scope = deps[i].getAttribute("scope");
             BundleContext context = getInstanceManager().getContext(); // Get the default bundle context.
@@ -321,7 +324,7 @@
 
             int policy = DependencyModel.getPolicy(deps[i]);
             Comparator cmp = DependencyModel.getComparator(deps[i], getInstanceManager().getGlobalContext());
-            Dependency dep = new Dependency(this, field, spec, fil, optional, aggregate, identitity, context, policy, cmp, defaultImplem);
+            Dependency dep = new Dependency(this, field, spec, fil, optional, aggregate, nullable, identitity, context, policy, cmp, defaultImplem);
 
             // Look for dependency callback :
             Element[] cbs = deps[i].getElements("Callback");
diff --git a/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/component/CheckServiceProvider.java b/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/component/CheckServiceProvider.java
index ffaab9f..cd2b927 100644
--- a/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/component/CheckServiceProvider.java
+++ b/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/component/CheckServiceProvider.java
@@ -39,7 +39,6 @@
 

 	public Properties getProps() {

 		Properties props = new Properties();

-		props.put("result", new Boolean(fs.foo()));

 		props.put("voidB", new Integer(simpleB));

 		props.put("objectB", new Integer(objectB));

 		props.put("refB", new Integer(refB));

@@ -48,13 +47,16 @@
 		props.put("objectU", new Integer(objectU));

 		props.put("refU", new Integer(refU));

 		props.put("bothU", new Integer(bothU));

-		props.put("boolean", new Boolean(fs.getBoolean()));

-		props.put("int", new Integer(fs.getInt()));

-		props.put("long", new Long(fs.getLong()));

-		props.put("double", new Double(fs.getDouble()));

+		if (fs != null) {

+		    props.put("result", new Boolean(fs.foo()));

+		    props.put("boolean", new Boolean(fs.getBoolean()));

+		    props.put("int", new Integer(fs.getInt()));

+		    props.put("long", new Long(fs.getLong()));

+		    props.put("double", new Double(fs.getDouble()));

+		    if(fs.getObject() != null) { props.put("object", fs.getObject()); }

+		}

         props.put("static", CheckService.foo);

         props.put("class", CheckService.class.getName());

-		if(fs.getObject() != null) { props.put("object", fs.getObject()); }

 		return props;

 	}

 	

diff --git a/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/dependency/DependencyTestSuite.java b/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/dependency/DependencyTestSuite.java
index 8943880..5326834 100644
--- a/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/dependency/DependencyTestSuite.java
+++ b/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/dependency/DependencyTestSuite.java
@@ -31,6 +31,7 @@
 		OSGiTestSuite ots = new OSGiTestSuite("Service Dependencies Test Suite", bc);

 		ots.addTestSuite(SimpleDependencies.class);

 		ots.addTestSuite(OptionalDependencies.class);

+		ots.addTestSuite(OptionalNoNullableDependencies.class);

 		ots.addTestSuite(MultipleDependencies.class);

 		ots.addTestSuite(OptionalMultipleDependencies.class);

 		ots.addTestSuite(DelayedSimpleDependencies.class);

diff --git a/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/dependency/OptionalNoNullableDependencies.java b/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/dependency/OptionalNoNullableDependencies.java
new file mode 100644
index 0000000..1e4a34b
--- /dev/null
+++ b/ipojo/tests/tests.core/src/main/java/org/apache/felix/ipojo/test/scenarios/dependency/OptionalNoNullableDependencies.java
@@ -0,0 +1,380 @@
+/* 

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

+

+import java.util.Properties;

+

+import org.apache.felix.ipojo.ComponentInstance;

+import org.apache.felix.ipojo.architecture.Architecture;

+import org.apache.felix.ipojo.architecture.InstanceDescription;

+import org.apache.felix.ipojo.junit4osgi.OSGiTestCase;

+import org.apache.felix.ipojo.test.scenarios.service.CheckService;

+import org.apache.felix.ipojo.test.scenarios.util.Utils;

+import org.osgi.framework.ServiceReference;

+

+public class OptionalNoNullableDependencies extends OSGiTestCase {

+	

+	ComponentInstance instance1, instance2, instance3, instance4, instance5;

+	ComponentInstance fooProvider;

+	

+	public void setUp() {

+		try {

+			Properties prov = new Properties();

+			prov.put("name", "FooProvider");

+			fooProvider = Utils.getFactoryByName(context, "FooProviderType-1").createComponentInstance(prov);

+			fooProvider.stop();

+			

+			Properties i1 = new Properties();

+			i1.put("name", "Simple");

+			instance1 = Utils.getFactoryByName(context, "SimpleOptionalNoNullableCheckServiceProvider").createComponentInstance(i1);

+		

+			Properties i2 = new Properties();

+			i2.put("name", "Void");

+			instance2 = Utils.getFactoryByName(context, "VoidOptionalNoNullableCheckServiceProvider").createComponentInstance(i2);

+		

+			Properties i3 = new Properties();

+			i3.put("name", "Object");

+			instance3 = Utils.getFactoryByName(context, "ObjectOptionalNoNullableCheckServiceProvider").createComponentInstance(i3);

+		

+			Properties i4 = new Properties();

+			i4.put("name", "Ref");

+			instance4 = Utils.getFactoryByName(context, "RefOptionalNoNullableCheckServiceProvider").createComponentInstance(i4);

+			

+			Properties i5 = new Properties();

+            i5.put("name", "Both");

+            instance5 = Utils.getFactoryByName(context, "BothOptionalNoNullableCheckServiceProvider").createComponentInstance(i5);

+		} catch(Exception e) { 

+		    e.getMessage();

+		    fail(e.getMessage()); 

+		}		

+	}

+	

+	public void tearDown() {

+		instance1.dispose();

+		instance2.dispose();

+		instance3.dispose();

+		instance4.dispose();

+		instance5.dispose();

+		fooProvider.dispose();

+		instance1 = null;

+		instance2 = null;

+		instance3 = null;

+		instance4 = null;

+		instance5 = null;

+		fooProvider = null;

+	}

+	

+	public void testSimple() {

+		ServiceReference arch_ref = Utils.getServiceReferenceByName(context, Architecture.class.getName(), instance1.getInstanceName());

+		assertNotNull("Check architecture availability", arch_ref);

+		InstanceDescription id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 1", id.getState() == ComponentInstance.VALID);

+		

+		ServiceReference cs_ref = Utils.getServiceReferenceByName(context, CheckService.class.getName(), instance1.getInstanceName());

+		assertNotNull("Check CheckService availability", cs_ref);

+		CheckService cs = (CheckService) context.getService(cs_ref);

+		Properties props = cs.getProps();

+		

+		//Check properties

+		assertNull("check CheckService invocation - 1 (" + props.get("result") + ")", props.get("result")); // Null no provider

+		assertEquals("check void bind invocation - 1", ((Integer)props.get("voidB")).intValue(), 0);

+		assertEquals("check void unbind callback invocation - 1", ((Integer)props.get("voidU")).intValue(), 0);

+		assertEquals("check object bind callback invocation - 1", ((Integer)props.get("objectB")).intValue(), 0);

+		assertEquals("check object unbind callback invocation - 1", ((Integer)props.get("objectU")).intValue(), 0);

+		assertEquals("check ref bind callback invocation - 1", ((Integer)props.get("refB")).intValue(), 0);

+		assertEquals("check ref unbind callback invocation - 1", ((Integer)props.get("refU")).intValue(), 0);

+		assertNull("Check FS invocation (object) - 1 ("+props.get("object")+")", props.get("object"));

+		

+		fooProvider.start();

+		

+		id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 2", id.getState() == ComponentInstance.VALID);

+		

+		assertNotNull("Check CheckService availability", cs_ref);

+		cs = (CheckService) context.getService(cs_ref);

+		props = cs.getProps();

+		

+		//Check properties

+		assertTrue("check CheckService invocation - 2", ((Boolean)props.get("result")).booleanValue()); // True, a provider is there

+		assertEquals("check void bind invocation - 2", ((Integer)props.get("voidB")).intValue(), 0);

+		assertEquals("check void unbind callback invocation - 2", ((Integer)props.get("voidU")).intValue(), 0);

+		assertEquals("check object bind callback invocation - 2", ((Integer)props.get("objectB")).intValue(), 0);

+		assertEquals("check object unbind callback invocation - 2", ((Integer)props.get("objectU")).intValue(), 0);

+		assertEquals("check ref bind callback invocation - 2", ((Integer)props.get("refB")).intValue(), 0);

+		assertEquals("check ref unbind callback invocation - 2", ((Integer)props.get("refU")).intValue(), 0);

+		assertNotNull("Check FS invocation (object) - 2", props.get("object"));

+		assertEquals("Check FS invocation (int) - 2", ((Integer)props.get("int")).intValue(), 1);

+		assertEquals("Check FS invocation (long) - 2", ((Long)props.get("long")).longValue(), 1);

+		assertEquals("Check FS invocation (double) - 2", ((Double)props.get("double")).doubleValue(), 1.0);

+		

+		fooProvider.stop();

+		

+		id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 3", id.getState() == ComponentInstance.VALID);

+		

+		id = null;

+		cs = null;

+		context.ungetService(arch_ref);

+		context.ungetService(cs_ref);		

+	}

+	

+	public void testVoid() {

+		ServiceReference arch_ref = Utils.getServiceReferenceByName(context, Architecture.class.getName(), instance2.getInstanceName());

+		assertNotNull("Check architecture availability", arch_ref);

+		InstanceDescription id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 1", id.getState() == ComponentInstance.VALID);

+		

+		ServiceReference cs_ref = Utils.getServiceReferenceByName(context, CheckService.class.getName(), instance2.getInstanceName());

+		assertNotNull("Check CheckService availability", cs_ref);

+		CheckService cs = (CheckService) context.getService(cs_ref);

+		Properties props = cs.getProps();

+		//Check properties

+		assertNull("check CheckService invocation - 1", props.get("result")); // Null, no provider

+		assertEquals("check void bind invocation - 1", ((Integer)props.get("voidB")).intValue(), 0);

+		assertEquals("check void unbind callback invocation - 1", ((Integer)props.get("voidU")).intValue(), 0);

+		assertEquals("check object bind callback invocation - 1", ((Integer)props.get("objectB")).intValue(), 0);

+		assertEquals("check object unbind callback invocation - 1", ((Integer)props.get("objectU")).intValue(), 0);

+		assertEquals("check ref bind callback invocation - 1", ((Integer)props.get("refB")).intValue(), 0);

+		assertEquals("check ref unbind callback invocation - 1", ((Integer)props.get("refU")).intValue(), 0);

+		assertNull("Check FS invocation (object) - 1", props.get("object"));

+		

+		fooProvider.start();

+		

+		id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 2", id.getState() == ComponentInstance.VALID);

+		

+		assertNotNull("Check CheckService availability", cs_ref);

+		cs = (CheckService) context.getService(cs_ref);

+		props = cs.getProps();

+		//Check properties

+		assertTrue("check CheckService invocation -2", ((Boolean)props.get("result")).booleanValue());

+		assertEquals("check void bind invocation -2", ((Integer)props.get("voidB")).intValue(), 1);

+		assertEquals("check void unbind callback invocation -2", ((Integer)props.get("voidU")).intValue(), 0);

+		assertEquals("check object bind callback invocation -2", ((Integer)props.get("objectB")).intValue(), 0);

+		assertEquals("check object unbind callback invocation -2", ((Integer)props.get("objectU")).intValue(), 0);

+		assertEquals("check ref bind callback invocation -2", ((Integer)props.get("refB")).intValue(), 0);

+		assertEquals("check ref unbind callback invocation -2", ((Integer)props.get("refU")).intValue(), 0);

+		assertNotNull("Check FS invocation (object) - 2", props.get("object"));

+		assertEquals("Check FS invocation (int) - 2", ((Integer)props.get("int")).intValue(), 1);

+		assertEquals("Check FS invocation (long) - 2", ((Long)props.get("long")).longValue(), 1);

+		assertEquals("Check FS invocation (double) - 2", ((Double)props.get("double")).doubleValue(), 1.0);

+		

+		fooProvider.stop();

+		

+		id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 3", id.getState() == ComponentInstance.VALID);

+		

+		cs = (CheckService) context.getService(cs_ref);

+		props = cs.getProps();

+		//Check properties

+		assertNull("check CheckService invocation -3", props.get("result"));

+		assertEquals("check void bind invocation -3", ((Integer)props.get("voidB")).intValue(), 1);

+		assertEquals("check void unbind callback invocation -3 ("+((Integer)props.get("voidU")) + ")", ((Integer)props.get("voidU")).intValue(), 1);

+		assertEquals("check object bind callback invocation -3", ((Integer)props.get("objectB")).intValue(), 0);

+		assertEquals("check object unbind callback invocation -3", ((Integer)props.get("objectU")).intValue(), 0);

+		assertEquals("check ref bind callback invocation -3", ((Integer)props.get("refB")).intValue(), 0);

+		assertEquals("check ref unbind callback invocation -3", ((Integer)props.get("refU")).intValue(), 0);

+		assertNull("Check FS invocation (object) - 3", props.get("object"));

+		

+		id = null;

+		cs = null;

+		context.ungetService(arch_ref);

+		context.ungetService(cs_ref);	

+	}

+	

+	public void testObject() {

+		ServiceReference arch_ref = Utils.getServiceReferenceByName(context, Architecture.class.getName(), instance3.getInstanceName());

+		assertNotNull("Check architecture availability", arch_ref);

+		InstanceDescription id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 1", id.getState() == ComponentInstance.VALID);

+		

+		ServiceReference cs_ref = Utils.getServiceReferenceByName(context, CheckService.class.getName(), instance3.getInstanceName());

+		assertNotNull("Check CheckService availability", cs_ref);

+		CheckService cs = (CheckService) context.getService(cs_ref);

+		Properties props = cs.getProps();

+		//Check properties

+		assertNull("check CheckService invocation -1", props.get("result")); // Null, no provider

+		assertEquals("check void bind invocation -1", ((Integer)props.get("voidB")).intValue(), 0);

+		assertEquals("check void unbind callback invocation -1", ((Integer)props.get("voidU")).intValue(), 0);

+		assertEquals("check object bind callback invocation -1", ((Integer)props.get("objectB")).intValue(), 0);

+		assertEquals("check object unbind callback invocation -1", ((Integer)props.get("objectU")).intValue(), 0);

+		assertEquals("check ref bind callback invocation -1", ((Integer)props.get("refB")).intValue(), 0);

+		assertEquals("check ref unbind callback invocation -1", ((Integer)props.get("refU")).intValue(), 0);

+		

+		fooProvider.start();

+		

+		id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 2", id.getState() == ComponentInstance.VALID);

+		

+		assertNotNull("Check CheckService availability", cs_ref);

+		cs = (CheckService) context.getService(cs_ref);

+		props = cs.getProps();

+		//Check properties

+		assertTrue("check CheckService invocation -2", ((Boolean)props.get("result")).booleanValue());

+		assertEquals("check void bind invocation -2", ((Integer)props.get("voidB")).intValue(), 0);

+		assertEquals("check void unbind callback invocation -2", ((Integer)props.get("voidU")).intValue(), 0);

+		assertEquals("check object bind callback invocation -2 (" + ((Integer)props.get("objectB")).intValue() + ")", ((Integer)props.get("objectB")).intValue(), 1);

+		assertEquals("check object unbind callback invocation -2", ((Integer)props.get("objectU")).intValue(), 0);

+		assertEquals("check ref bind callback invocation -2", ((Integer)props.get("refB")).intValue(), 0);

+		assertEquals("check ref unbind callback invocation -2", ((Integer)props.get("refU")).intValue(), 0);

+		

+		fooProvider.stop();

+		

+		id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 3", id.getState() == ComponentInstance.VALID);

+		

+		cs = (CheckService) context.getService(cs_ref);

+		props = cs.getProps();

+		//Check properties

+		assertNull("check CheckService invocation -3", props.get("result")); // No provider.

+		assertEquals("check void bind invocation -3", ((Integer)props.get("voidB")).intValue(), 0);

+		assertEquals("check void unbind callback invocation -3", ((Integer)props.get("voidU")).intValue(), 0);

+		assertEquals("check object bind callback invocation -3", ((Integer)props.get("objectB")).intValue(), 1);

+		assertEquals("check object unbind callback invocation -3", ((Integer)props.get("objectU")).intValue(), 1);

+		assertEquals("check ref bind callback invocation -3", ((Integer)props.get("refB")).intValue(), 0);

+		assertEquals("check ref unbind callback invocation -3", ((Integer)props.get("refU")).intValue(), 0);

+		

+		id = null;

+		cs = null;

+		context.ungetService(arch_ref);

+		context.ungetService(cs_ref);		

+	}

+	

+	public void testRef() {

+		ServiceReference arch_ref = Utils.getServiceReferenceByName(context, Architecture.class.getName(), instance4.getInstanceName());

+		assertNotNull("Check architecture availability", arch_ref);

+		InstanceDescription id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 1", id.getState() == ComponentInstance.VALID);

+		

+		ServiceReference cs_ref = Utils.getServiceReferenceByName(context, CheckService.class.getName(), instance4.getInstanceName());

+		assertNotNull("Check CheckService availability", cs_ref);

+		CheckService cs = (CheckService) context.getService(cs_ref);

+		Properties props = cs.getProps();

+		//Check properties

+		assertNull("check CheckService invocation -1", props.get("result")); //Null, no provider

+		assertEquals("check void bind invocation -1", ((Integer)props.get("voidB")).intValue(), 0);

+		assertEquals("check void unbind callback invocation -1", ((Integer)props.get("voidU")).intValue(), 0);

+		assertEquals("check object bind callback invocation -1", ((Integer)props.get("objectB")).intValue(), 0);

+		assertEquals("check object unbind callback invocation -1", ((Integer)props.get("objectU")).intValue(), 0);

+		assertEquals("check ref bind callback invocation -1", ((Integer)props.get("refB")).intValue(), 0);

+		assertEquals("check ref unbind callback invocation -1", ((Integer)props.get("refU")).intValue(), 0);

+		

+		fooProvider.start();

+		

+		id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 2", id.getState() == ComponentInstance.VALID);

+		

+		assertNotNull("Check CheckService availability", cs_ref);

+		cs = (CheckService) context.getService(cs_ref);

+		props = cs.getProps();

+		//Check properties

+		assertTrue("check CheckService invocation -2", ((Boolean)props.get("result")).booleanValue());

+		assertEquals("check void bind invocation -2", ((Integer)props.get("voidB")).intValue(), 0);

+		assertEquals("check void unbind callback invocation -2", ((Integer)props.get("voidU")).intValue(), 0);

+		assertEquals("check object bind callback invocation -2", ((Integer)props.get("objectB")).intValue(), 0);

+		assertEquals("check object unbind callback invocation -2", ((Integer)props.get("objectU")).intValue(), 0);

+		assertEquals("check ref bind callback invocation -2", ((Integer)props.get("refB")).intValue(), 1);

+		assertEquals("check ref unbind callback invocation -2", ((Integer)props.get("refU")).intValue(), 0);

+		

+		fooProvider.stop();

+		

+		id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+		assertTrue("Check instance validity - 3", id.getState() == ComponentInstance.VALID);

+		

+		cs = (CheckService) context.getService(cs_ref);

+		props = cs.getProps();

+		//Check properties

+		assertNull("check CheckService invocation -3", props.get("result")); // Null, no provider

+		assertEquals("check void bind invocation -3", ((Integer)props.get("voidB")).intValue(), 0);

+		assertEquals("check void unbind callback invocation -3", ((Integer)props.get("voidU")).intValue(), 0);

+		assertEquals("check object bind callback invocation -3", ((Integer)props.get("objectB")).intValue(), 0);

+		assertEquals("check object unbind callback invocation -3", ((Integer)props.get("objectU")).intValue(), 0);

+		assertEquals("check ref bind callback invocation -3", ((Integer)props.get("refB")).intValue(), 1);

+		assertEquals("check ref unbind callback invocation -3", ((Integer)props.get("refU")).intValue(), 1);

+		

+		id = null;

+		cs = null;

+		context.ungetService(arch_ref);

+		context.ungetService(cs_ref);

+	}

+	

+	public void testBoth() {

+        ServiceReference arch_ref = Utils.getServiceReferenceByName(context, Architecture.class.getName(), instance5.getInstanceName());

+        assertNotNull("Check architecture availability", arch_ref);

+        InstanceDescription id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+        assertTrue("Check instance validity - 1", id.getState() == ComponentInstance.VALID);

+        

+        ServiceReference cs_ref = Utils.getServiceReferenceByName(context, CheckService.class.getName(), instance5.getInstanceName());

+        assertNotNull("Check CheckService availability", cs_ref);

+        CheckService cs = (CheckService) context.getService(cs_ref);

+        Properties props = cs.getProps();

+        //Check properties

+        assertNull("check CheckService invocation -1", props.get("result")); // Null, no provider

+        assertEquals("check void bind invocation -1", ((Integer)props.get("voidB")).intValue(), 0);

+        assertEquals("check void unbind callback invocation -1", ((Integer)props.get("voidU")).intValue(), 0);

+        assertEquals("check object bind callback invocation -1", ((Integer)props.get("objectB")).intValue(), 0);

+        assertEquals("check object unbind callback invocation -1", ((Integer)props.get("objectU")).intValue(), 0);

+        assertEquals("check both bind callback invocation -1", ((Integer)props.get("bothB")).intValue(), 0);

+        assertEquals("check both unbind callback invocation -1", ((Integer)props.get("bothU")).intValue(), 0);

+        

+        fooProvider.start();

+        

+        id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+        assertTrue("Check instance validity - 2", id.getState() == ComponentInstance.VALID);

+        

+        assertNotNull("Check CheckService availability", cs_ref);

+        cs = (CheckService) context.getService(cs_ref);

+        props = cs.getProps();

+        //Check properties

+        assertTrue("check CheckService invocation -2", ((Boolean)props.get("result")).booleanValue());

+        assertEquals("check void bind invocation -2", ((Integer)props.get("voidB")).intValue(), 0);

+        assertEquals("check void unbind callback invocation -2", ((Integer)props.get("voidU")).intValue(), 0);

+        assertEquals("check object bind callback invocation -2", ((Integer)props.get("objectB")).intValue(), 0);

+        assertEquals("check object unbind callback invocation -2", ((Integer)props.get("objectU")).intValue(), 0);

+        assertEquals("check ref bind callback invocation -2", ((Integer)props.get("refB")).intValue(), 0);

+        assertEquals("check ref unbind callback invocation -2", ((Integer)props.get("refU")).intValue(), 0);

+        assertEquals("check both bind callback invocation -2", ((Integer)props.get("bothB")).intValue(), 1);

+        assertEquals("check both unbind callback invocation -2", ((Integer)props.get("bothU")).intValue(), 0);

+        

+        fooProvider.stop();

+        

+        id = ((Architecture) context.getService(arch_ref)).getInstanceDescription();

+        assertTrue("Check instance validity - 3", id.getState() == ComponentInstance.VALID);

+        

+        cs = (CheckService) context.getService(cs_ref);

+        props = cs.getProps();

+        //Check properties

+        assertNull("check CheckService invocation -3", props.get("result")); // Null, no provider

+        assertEquals("check void bind invocation -3", ((Integer)props.get("voidB")).intValue(), 0);

+        assertEquals("check void unbind callback invocation -3", ((Integer)props.get("voidU")).intValue(), 0);

+        assertEquals("check object bind callback invocation -3", ((Integer)props.get("objectB")).intValue(), 0);

+        assertEquals("check object unbind callback invocation -3", ((Integer)props.get("objectU")).intValue(), 0);

+        assertEquals("check ref bind callback invocation -3", ((Integer)props.get("refB")).intValue(), 0);

+        assertEquals("check ref unbind callback invocation -3", ((Integer)props.get("refU")).intValue(), 0);

+        assertEquals("check both bind callback invocation -3", ((Integer)props.get("bothB")).intValue(), 1);

+        assertEquals("check both unbind callback invocation -3", ((Integer)props.get("bothU")).intValue(), 1);

+  

+        id = null;

+        cs = null;

+        context.ungetService(arch_ref);

+        context.ungetService(cs_ref);

+    }

+

+

+}

diff --git a/ipojo/tests/tests.core/src/main/resources/metadata.xml b/ipojo/tests/tests.core/src/main/resources/metadata.xml
index 595ca8b..65b63fe 100644
--- a/ipojo/tests/tests.core/src/main/resources/metadata.xml
+++ b/ipojo/tests/tests.core/src/main/resources/metadata.xml
@@ -347,6 +347,12 @@
 	</component>

 	<component

 		className="org.apache.felix.ipojo.test.scenarios.component.CheckServiceProvider"

+		factory="SimpleOptionalNoNullableCheckServiceProvider" architecture="true">

+		<requires field="fs" optional="true" nullable="false" />

+		<provides />

+	</component>

+	<component

+		className="org.apache.felix.ipojo.test.scenarios.component.CheckServiceProvider"

 		factory="VoidOptionalCheckServiceProvider" architecture="true">

 		<requires field="fs" optional="true">

 			<callback type="bind" method="voidBind" />

@@ -356,6 +362,15 @@
 	</component>

 	<component

 		className="org.apache.felix.ipojo.test.scenarios.component.CheckServiceProvider"

+		factory="VoidOptionalNoNullableCheckServiceProvider" architecture="true">

+		<requires field="fs" optional="true" nullable="false">

+			<callback type="bind" method="voidBind" />

+			<callback type="unbind" method="voidUnbind" />

+		</requires>

+		<provides />

+	</component>

+	<component

+		className="org.apache.felix.ipojo.test.scenarios.component.CheckServiceProvider"

 		factory="ObjectOptionalCheckServiceProvider" architecture="true">

 		<requires field="fs" optional="true">

 			<callback type="bind" method="objectBind" />

@@ -365,6 +380,15 @@
 	</component>

 	<component

 		className="org.apache.felix.ipojo.test.scenarios.component.CheckServiceProvider"

+		factory="ObjectOptionalNoNullableCheckServiceProvider" architecture="true">

+		<requires field="fs" optional="true" nullable="false">

+			<callback type="bind" method="objectBind" />

+			<callback type="unbind" method="objectUnbind" />

+		</requires>

+		<provides />

+	</component>

+	<component

+		className="org.apache.felix.ipojo.test.scenarios.component.CheckServiceProvider"

 		factory="RefOptionalCheckServiceProvider" architecture="true">

 		<requires field="fs" optional="true">

 			<callback type="bind" method="refBind" />

@@ -374,6 +398,15 @@
 	</component>

 	<component

 		className="org.apache.felix.ipojo.test.scenarios.component.CheckServiceProvider"

+		factory="RefOptionalNoNullableCheckServiceProvider" architecture="true">

+		<requires field="fs" optional="true" nullable="false">

+			<callback type="bind" method="refBind" />

+			<callback type="unbind" method="refUnbind" />

+		</requires>

+		<provides />

+	</component>

+	<component

+		className="org.apache.felix.ipojo.test.scenarios.component.CheckServiceProvider"

 		factory="BothOptionalCheckServiceProvider" architecture="true">

 		<requires field="fs" optional="true">

 			<callback type="bind" method="bothBind" />

@@ -381,6 +414,15 @@
 		</requires>

 		<provides />

 	</component>

+	<component

+		className="org.apache.felix.ipojo.test.scenarios.component.CheckServiceProvider"

+		factory="BothOptionalNoNullableCheckServiceProvider" architecture="true">

+		<requires field="fs" optional="true" nullable="false">

+			<callback type="bind" method="bothBind" />

+			<callback type="unbind" method="bothUnbind" />

+		</requires>

+		<provides />

+	</component>

 

 	<component

 		className="org.apache.felix.ipojo.test.scenarios.component.MethodCheckServiceProvider"