Fix issue Felix-853.
iPOJO has a new service object creation strategy allowing creating an object per asking instance. Moreover, new strategies can be created (by implementing CreationStrategy).
The 'factory' attribute of the 'provides' becomes 'strategy' which makes more sense.
Commit the creation strategy test suite.
Improve the efficiency of Properties and Callbacks.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@728056 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/tests/core/service-providing-strategies/pom.xml b/ipojo/tests/core/service-providing-strategies/pom.xml
new file mode 100755
index 0000000..80be307
--- /dev/null
+++ b/ipojo/tests/core/service-providing-strategies/pom.xml
@@ -0,0 +1,104 @@
+<!--
+ 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.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <name>iPOJO Service Providing Strategy Test Suite</name>
+ <artifactId>tests.core.ps.strategy</artifactId>
+ <groupId>ipojo.tests</groupId>
+ <version>1.1.0-SNAPSHOT</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.metadata</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>1.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.junit4osgi</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <artifactId>tests.core.ps</artifactId>
+ <groupId>ipojo.tests</groupId>
+ <version>1.1.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.3</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>
+ ${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Private-Package>
+ org.apache.felix.ipojo.test.scenarios.component.strategies, org.apache.felix.ipojo.test.scenarios.ps.strategies
+ </Private-Package>
+ <Test-Suite>
+ org.apache.felix.ipojo.test.scenarios.ps.strategies.ProvidedServiceStrategyTestSuite
+ </Test-Suite>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ <configuration>
+ <ignoreAnnotations>true</ignoreAnnotations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.4</source>
+ <target>1.4</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/BarConsumer.java b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/BarConsumer.java
new file mode 100644
index 0000000..c7cf2d2
--- /dev/null
+++ b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/BarConsumer.java
@@ -0,0 +1,23 @@
+package org.apache.felix.ipojo.test.scenarios.component.strategies;
+
+import java.util.Properties;
+
+import org.apache.felix.ipojo.test.scenarios.ps.service.BarService;
+import org.apache.felix.ipojo.test.scenarios.ps.service.CheckService;
+
+public class BarConsumer implements CheckService {
+
+ private BarService bs;
+
+
+ public boolean check() {
+ return bs.bar();
+ }
+
+ public Properties getProps() {
+ Properties props = bs.getProps();
+ props.put("object", bs);
+ return props;
+ }
+
+}
diff --git a/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/Consumer.java b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/Consumer.java
new file mode 100644
index 0000000..1479eb1
--- /dev/null
+++ b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/Consumer.java
@@ -0,0 +1,23 @@
+package org.apache.felix.ipojo.test.scenarios.component.strategies;
+
+import java.util.Properties;
+
+import org.apache.felix.ipojo.test.scenarios.ps.service.CheckService;
+import org.apache.felix.ipojo.test.scenarios.ps.service.FooService;
+
+public class Consumer implements CheckService {
+
+ private FooService fs;
+
+
+ public boolean check() {
+ return fs.foo();
+ }
+
+ public Properties getProps() {
+ Properties props = fs.fooProps();
+ props.put("object", fs);
+ return props;
+ }
+
+}
diff --git a/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/DummyCreationStrategy.java b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/DummyCreationStrategy.java
new file mode 100644
index 0000000..d0b7660
--- /dev/null
+++ b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/DummyCreationStrategy.java
@@ -0,0 +1,168 @@
+package org.apache.felix.ipojo.test.scenarios.component.strategies;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.IPOJOServiceFactory;
+import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.handlers.providedservice.CreationStrategy;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class DummyCreationStrategy extends CreationStrategy implements InvocationHandler {
+
+ /**
+ * Map [ComponentInstance->ServiceObject] storing created service objects.
+ */
+ private Map/*<ComponentInstance, ServiceObject>*/ m_instances = new HashMap();
+
+ private InstanceManager m_manager;
+
+ private String[] m_specs;
+
+ /**
+ * A method is invoked on the proxy object.
+ * If the method is the {@link IPOJOServiceFactory#getService(ComponentInstance)}
+ * method, this method creates a service object if no already created for the asking
+ * component instance.
+ * If the method is {@link IPOJOServiceFactory#ungetService(ComponentInstance, Object)}
+ * the service object is unget (i.e. removed from the map and deleted).
+ * In all other cases, a {@link UnsupportedOperationException} is thrown as this policy
+ * requires to use the {@link IPOJOServiceFactory} interaction pattern.
+ * @param arg0 the proxy object
+ * @param arg1 the called method
+ * @param arg2 the arguments
+ * @return the service object attached to the asking instance for 'get',
+ * <code>null</code> for 'unget',
+ * a {@link UnsupportedOperationException} for all other methods.
+ * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
+ */
+ public Object invoke(Object arg0, Method arg1, Object[] arg2) {
+ if (isGetServiceMethod(arg1)) {
+ return getService((ComponentInstance) arg2[0]);
+ }
+
+ if (isUngetServiceMethod(arg1)) {
+ ungetService((ComponentInstance) arg2[0], arg2[1]);
+ return null;
+ }
+
+ throw new UnsupportedOperationException("This service requires an advanced creation policy. "
+ + "Before calling the service, call the getService(ComponentInstance) method to get "
+ + "the service object. " + arg1.getName()); // TODO DEBUG
+ }
+
+ /**
+ * A service object is required.
+ * This policy returns a service object per asking instance.
+ * @param instance the instance requiring the service object
+ * @return the service object for this instance
+ * @see org.apache.felix.ipojo.IPOJOServiceFactory#getService(org.apache.felix.ipojo.ComponentInstance)
+ */
+ public Object getService(ComponentInstance instance) {
+ Object obj = m_instances.get(instance);
+ if (obj == null) {
+ obj = m_manager.createPojoObject();
+ m_instances.put(instance, obj);
+ }
+ return obj;
+ }
+
+ /**
+ * A service object is unget.
+ * The service object is removed from the map and deleted.
+ * @param instance the instance releasing the service
+ * @param svcObject the service object
+ * @see org.apache.felix.ipojo.IPOJOServiceFactory#ungetService(org.apache.felix.ipojo.ComponentInstance, java.lang.Object)
+ */
+ public void ungetService(ComponentInstance instance, Object svcObject) {
+ Object pojo = m_instances.remove(instance);
+ m_manager.deletePojoObject(pojo);
+ }
+
+ /**
+ * The service is going to be registered.
+ * @param im the instance manager
+ * @param interfaces the published interfaces
+ * @param props the properties
+ * @see org.apache.felix.ipojo.handlers.providedservice.CreationStrategy#onPublication(org.osgi.framework.BundleContext, java.lang.String[], java.util.Properties)
+ */
+ public void onPublication(InstanceManager im, String[] interfaces,
+ Properties props) {
+
+ m_manager = im;
+ m_specs = interfaces;
+
+ }
+
+ /**
+ * The service is going to be unregistered.
+ * The instance map is cleared. Created object are disposed.
+ * @see org.apache.felix.ipojo.handlers.providedservice.CreationStrategy#onUnpublication()
+ */
+ public void onUnpublication() {
+ Collection col = m_instances.values();
+ Iterator it = col.iterator();
+ while (it.hasNext()) {
+ m_manager.deletePojoObject(it.next());
+ }
+ m_instances.clear();
+ }
+
+ /**
+ * OSGi Service Factory getService method.
+ * @param arg0 the asking bundle
+ * @param arg1 the service registration
+ * @return a proxy implementing the {@link IPOJOServiceFactory}
+ * @see org.osgi.framework.ServiceFactory#getService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration)
+ */
+ public Object getService(Bundle arg0, ServiceRegistration arg1) {
+ Object proxy = Proxy.newProxyInstance(m_manager.getClazz().getClassLoader(),
+ getSpecificationsWithIPOJOServiceFactory(m_specs, m_manager.getContext()), this);
+ return proxy;
+ }
+
+ /**
+ * OSGi Service factory unget method.
+ * Does nothing.
+ * @param arg0 the asking bundle
+ * @param arg1 the service registration
+ * @param arg2 the service object created for this bundle.
+ * @see org.osgi.framework.ServiceFactory#ungetService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration, java.lang.Object)
+ */
+ public void ungetService(Bundle arg0, ServiceRegistration arg1,
+ Object arg2) { }
+
+ /**
+ * Utility method returning the class array of provided service
+ * specification and the {@link IPOJOServiceFactory} interface.
+ * @param specs the published service interface
+ * @param bc the bundle context, used to load classes
+ * @return the class array containing provided service specification and
+ * the {@link IPOJOServiceFactory} class.
+ */
+ private Class[] getSpecificationsWithIPOJOServiceFactory(String[] specs, BundleContext bc) {
+ Class[] classes = new Class[specs.length + 1];
+ int i = 0;
+ for (i = 0; i < specs.length; i++) {
+ try {
+ classes[i] = bc.getBundle().loadClass(specs[i]);
+ } catch (ClassNotFoundException e) {
+ // Should not happen.
+ }
+ }
+ classes[i] = IPOJOServiceFactory.class;
+ return classes;
+ }
+
+
+}
+
diff --git a/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/FooBarProviderType1.java b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/FooBarProviderType1.java
new file mode 100644
index 0000000..be254c5
--- /dev/null
+++ b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/FooBarProviderType1.java
@@ -0,0 +1,86 @@
+/*
+ * 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.component.strategies;
+
+import java.util.Properties;
+
+import org.apache.felix.ipojo.test.scenarios.ps.service.BarService;
+import org.apache.felix.ipojo.test.scenarios.ps.service.FooService;
+
+public class FooBarProviderType1 implements FooService, BarService {
+
+ public static long id = 0;
+
+ public static long getNewId() {
+ id++;
+ return id;
+ }
+
+ public static long getReturnedIds() {
+ return id;
+ }
+
+ public static void resetIds() {
+ id = 0;
+ }
+
+ private int m_bar;
+ private String m_foo;
+
+ private long myid = getNewId();
+
+
+
+ public boolean foo() {
+ return true;
+ }
+
+ public Properties fooProps() {
+ System.out.println(this + " - id : " + myid); //TODO DEBUG
+ Properties p = new Properties();
+ p.put("bar", new Integer(m_bar));
+ if(m_foo != null) {
+ p.put("foo", m_foo);
+ }
+
+ p.put("id", new Long(myid));
+ return p;
+ }
+
+
+ public boolean getBoolean() { return true; }
+
+ public double getDouble() { return 1.0; }
+
+ public int getInt() { return 1; }
+
+ public long getLong() { return 1; }
+
+ public Boolean getObject() { return new Boolean(true); }
+
+ public boolean bar() {
+ return foo();
+ }
+
+ public Properties getProps() {
+ return fooProps();
+ }
+
+
+}
diff --git a/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/FooProviderType1.java b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/FooProviderType1.java
new file mode 100755
index 0000000..967a8de
--- /dev/null
+++ b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/component/strategies/FooProviderType1.java
@@ -0,0 +1,77 @@
+/*
+ * 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.component.strategies;
+
+import java.util.Properties;
+
+import org.apache.felix.ipojo.test.scenarios.ps.service.FooService;
+
+public class FooProviderType1 implements FooService {
+
+ public static long id = 0;
+
+ public static long getNewId() {
+ id++;
+ return id;
+ }
+
+ public static long getReturnedIds() {
+ return id;
+ }
+
+ public static void resetIds() {
+ id = 0;
+ }
+
+ private int m_bar;
+ private String m_foo;
+
+ private long myid = getNewId();
+
+
+
+ public boolean foo() {
+ return true;
+ }
+
+ public Properties fooProps() {
+ System.out.println(this + " - id : " + myid); //TODO DEBUG
+ Properties p = new Properties();
+ p.put("bar", new Integer(m_bar));
+ if(m_foo != null) {
+ p.put("foo", m_foo);
+ }
+
+ p.put("id", new Long(myid));
+ return p;
+ }
+
+
+ public boolean getBoolean() { return true; }
+
+ public double getDouble() { return 1.0; }
+
+ public int getInt() { return 1; }
+
+ public long getLong() { return 1; }
+
+ public Boolean getObject() { return new Boolean(true); }
+
+
+}
diff --git a/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/ps/strategies/CustomStrategyTest.java b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/ps/strategies/CustomStrategyTest.java
new file mode 100644
index 0000000..f5635f4
--- /dev/null
+++ b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/ps/strategies/CustomStrategyTest.java
@@ -0,0 +1,200 @@
+package org.apache.felix.ipojo.test.scenarios.ps.strategies;
+
+import java.util.Properties;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.junit4osgi.OSGiTestCase;
+import org.apache.felix.ipojo.junit4osgi.helpers.IPOJOHelper;
+import org.apache.felix.ipojo.test.scenarios.component.strategies.FooBarProviderType1;
+import org.apache.felix.ipojo.test.scenarios.component.strategies.FooProviderType1;
+import org.apache.felix.ipojo.test.scenarios.ps.service.BarService;
+import org.apache.felix.ipojo.test.scenarios.ps.service.CheckService;
+import org.apache.felix.ipojo.test.scenarios.ps.service.FooService;
+import org.osgi.framework.ServiceReference;
+
+public class CustomStrategyTest extends OSGiTestCase {
+
+
+ private IPOJOHelper helper;
+ private ComponentInstance cons1, cons2, prov;
+ private ComponentInstance cons3, prov2;
+
+ public void setUp() {
+ helper = new IPOJOHelper(this);
+ cons1 = helper.createComponentInstance("PSS-Cons");
+ assertEquals("cons1 invalid", ComponentInstance.INVALID, cons1.getState());
+ cons2 = helper.createComponentInstance("PSS-Cons");
+ assertEquals("cons2 invalid", ComponentInstance.INVALID, cons2.getState());
+ prov = helper.createComponentInstance("PSS-FooProviderType-Custom");
+ prov2 = helper.createComponentInstance("PSS-FooBarProviderType-Custom");
+ cons3 = helper.createComponentInstance("PSS-ConsBar");
+ prov2.stop();
+ prov.stop();
+ }
+
+ public void tearDown() {
+ reset();
+ }
+
+
+ private void reset() {
+ FooProviderType1.resetIds();
+ FooBarProviderType1.resetIds();
+ }
+
+ private void checkCreatedObjects(ComponentInstance ci, int expected) {
+ assertEquals("Number of created objects", expected, ci.getInstanceDescription().getCreatedObjects().length);
+ }
+
+ public void testOneService() {
+ prov.start();
+ cons2.stop();
+ cons1.stop();
+ assertEquals("Prov valid", ComponentInstance.VALID, prov.getState());
+ ServiceReference ref = helper.getServiceReferenceByName(FooService.class.getName(), prov.getInstanceName());
+ assertNotNull("Service available", ref);
+ checkCreatedObjects(prov, 0);
+
+ // Step 1 : create start one consumer
+ cons1.start();
+ ServiceReference refcons1 = helper.getServiceReferenceByName(CheckService.class.getName(), cons1.getInstanceName());
+ assertNotNull("Cons1 Service available", refcons1);
+
+ CheckService cs_cons1 = (CheckService) getServiceObject(refcons1);
+ Properties props = cs_cons1.getProps();
+ Long id = (Long) props.get("id");
+ FooService fscons1 = (FooService) props.get("object");
+ assertEquals("id 1", 1, id.intValue());
+ checkCreatedObjects(prov, 1);
+
+
+ // Step 2 : create a second consumer
+ cons2.start();
+ ServiceReference refcons2 = helper.getServiceReferenceByName(CheckService.class.getName(), cons2.getInstanceName());
+ assertNotNull("Cons2 Service available", refcons2);
+
+ CheckService cs_cons2 = (CheckService) getServiceObject(refcons2);
+ Properties props2 = cs_cons2.getProps();
+ Long id2 = (Long) props2.get("id");
+ FooService fscons2 = (FooService) props2.get("object");
+ assertEquals("id 2", 2, id2.intValue());
+ checkCreatedObjects(prov, 2);
+
+
+ assertNotSame("Two objects", fscons1, fscons2);
+
+ // Step 3 : stop the second provider
+ System.out.println("cons2 stopping");
+ cons2.stop();
+ System.out.println("cons2 stopped");
+ checkCreatedObjects(prov, 1);
+
+ // Step 4 : stop the first consumer
+ cons1.stop();
+ checkCreatedObjects(prov, 0);
+ }
+
+ public void testObjectCreation() {
+ prov.start();
+
+ // The two consumers are started and use their own objects.
+ ServiceReference refcons1 = helper.getServiceReferenceByName(CheckService.class.getName(), cons1.getInstanceName());
+ assertNotNull("Cons1 Service available", refcons1);
+ CheckService cs_cons1 = (CheckService) getServiceObject(refcons1);
+ Properties props = cs_cons1.getProps();
+ FooService fscons1 = (FooService) props.get("object");
+
+ ServiceReference refcons2 = helper.getServiceReferenceByName(CheckService.class.getName(), cons2.getInstanceName());
+ assertNotNull("Cons2 Service available", refcons2);
+ CheckService cs_cons2 = (CheckService) getServiceObject(refcons2);
+ Properties props2 = cs_cons2.getProps();
+ FooService fscons2 = (FooService) props2.get("object");
+
+ checkCreatedObjects(prov, 2);
+ assertNotSame("Two objects", fscons1, fscons2);
+
+ // Stop the provider
+ prov.stop();
+ // Cons1 and 2 are invalid.
+ assertEquals("Cons1 invalidity", ComponentInstance.INVALID, cons1.getState());
+ assertEquals("Cons2 invalidity", ComponentInstance.INVALID, cons2.getState());
+
+ // No object created in prov
+ checkCreatedObjects(prov, 0);
+
+ // Restart the provider
+ prov.start();
+
+ // Consumers are valid.
+ assertEquals("Cons1 validity", ComponentInstance.VALID, cons1.getState());
+ assertEquals("Cons2 validity", ComponentInstance.VALID, cons2.getState());
+
+ // Check objects
+ refcons1 = helper.getServiceReferenceByName(CheckService.class.getName(), cons1.getInstanceName());
+ assertNotNull("Cons1 Service available", refcons1);
+ cs_cons1 = (CheckService) getServiceObject(refcons1);
+ props = cs_cons1.getProps();
+ Object fscons3 = (FooService) props.get("object");
+
+ refcons2 = helper.getServiceReferenceByName(CheckService.class.getName(), cons2.getInstanceName());
+ assertNotNull("Cons2 Service available", refcons2);
+ cs_cons2 = (CheckService) getServiceObject(refcons2);
+ props2 = cs_cons2.getProps();
+ Object fscons4 = (FooService) props2.get("object");
+
+ checkCreatedObjects(prov, 2);
+ assertNotSame("Two objects", fscons3, fscons4);
+ assertNotSame("Two new objects - 1", fscons3, fscons1);
+ assertNotSame("Two new objects - 2", fscons4, fscons2);
+
+ }
+
+ public void testTwoServices() {
+ cons3.stop();
+ prov2.start();
+ cons1.stop();
+ assertEquals("Prov valid", ComponentInstance.VALID, prov2.getState());
+ ServiceReference ref = helper.getServiceReferenceByName(FooService.class.getName(), prov2.getInstanceName());
+ assertNotNull("Service available", ref);
+ ServiceReference refBar = helper.getServiceReferenceByName(BarService.class.getName(), prov2.getInstanceName());
+ assertNotNull("Service available", refBar);
+ checkCreatedObjects(prov2, 0);
+
+ // Step 1 : create start one consumer
+ cons1.start();
+ ServiceReference refcons1 = helper.getServiceReferenceByName(CheckService.class.getName(), cons1.getInstanceName());
+ assertNotNull("Cons1 Service available", refcons1);
+
+ CheckService cs_cons1 = (CheckService) getServiceObject(refcons1);
+ Properties props = cs_cons1.getProps();
+ Long id = (Long) props.get("id");
+ FooService fscons1 = (FooService) props.get("object");
+ assertEquals("id 1", 1, id.intValue());
+ checkCreatedObjects(prov2, 1);
+
+
+ // Step 2 : create a second consumer
+ cons3.start();
+ ServiceReference refcons2 = helper.getServiceReferenceByName(CheckService.class.getName(), cons3.getInstanceName());
+ assertNotNull("Cons2 Service available", refcons2);
+
+ CheckService cs_cons2 = (CheckService) getServiceObject(refcons2);
+ Properties props2 = cs_cons2.getProps();
+ Long id2 = (Long) props2.get("id");
+ FooService fscons2 = (FooService) props2.get("object");
+ assertEquals("id 2", 2, id2.intValue());
+ checkCreatedObjects(prov2, 2);
+
+
+ assertNotSame("Two objects", fscons1, fscons2);
+
+ // Step 3 : stop the second provider
+ cons3.stop();
+ checkCreatedObjects(prov2, 1);
+
+ // Step 4 : stop the first consumer
+ cons1.stop();
+ checkCreatedObjects(prov, 0);
+ }
+
+}
diff --git a/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/ps/strategies/PerInstanceStrategyTest.java b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/ps/strategies/PerInstanceStrategyTest.java
new file mode 100644
index 0000000..e59b2ce
--- /dev/null
+++ b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/ps/strategies/PerInstanceStrategyTest.java
@@ -0,0 +1,200 @@
+package org.apache.felix.ipojo.test.scenarios.ps.strategies;
+
+import java.util.Properties;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.junit4osgi.OSGiTestCase;
+import org.apache.felix.ipojo.junit4osgi.helpers.IPOJOHelper;
+import org.apache.felix.ipojo.test.scenarios.component.strategies.FooBarProviderType1;
+import org.apache.felix.ipojo.test.scenarios.component.strategies.FooProviderType1;
+import org.apache.felix.ipojo.test.scenarios.ps.service.BarService;
+import org.apache.felix.ipojo.test.scenarios.ps.service.CheckService;
+import org.apache.felix.ipojo.test.scenarios.ps.service.FooService;
+import org.osgi.framework.ServiceReference;
+
+public class PerInstanceStrategyTest extends OSGiTestCase {
+
+
+ private IPOJOHelper helper;
+ private ComponentInstance cons1, cons2, prov;
+ private ComponentInstance cons3, prov2;
+
+ public void setUp() {
+ helper = new IPOJOHelper(this);
+ cons1 = helper.createComponentInstance("PSS-Cons");
+ assertEquals("cons1 invalid", ComponentInstance.INVALID, cons1.getState());
+ cons2 = helper.createComponentInstance("PSS-Cons");
+ assertEquals("cons2 invalid", ComponentInstance.INVALID, cons2.getState());
+ prov = helper.createComponentInstance("PSS-FooProviderType-Instance");
+ prov2 = helper.createComponentInstance("PSS-FooBarProviderType-Instance");
+ cons3 = helper.createComponentInstance("PSS-ConsBar");
+ prov2.stop();
+ prov.stop();
+ }
+
+ public void tearDown() {
+ reset();
+ }
+
+
+ private void reset() {
+ FooProviderType1.resetIds();
+ FooBarProviderType1.resetIds();
+ }
+
+ private void checkCreatedObjects(ComponentInstance ci, int expected) {
+ assertEquals("Number of created objects", expected, ci.getInstanceDescription().getCreatedObjects().length);
+ }
+
+ public void testOneService() {
+ prov.start();
+ cons2.stop();
+ cons1.stop();
+ assertEquals("Prov valid", ComponentInstance.VALID, prov.getState());
+ ServiceReference ref = helper.getServiceReferenceByName(FooService.class.getName(), prov.getInstanceName());
+ assertNotNull("Service available", ref);
+ checkCreatedObjects(prov, 0);
+
+ // Step 1 : create start one consumer
+ cons1.start();
+ ServiceReference refcons1 = helper.getServiceReferenceByName(CheckService.class.getName(), cons1.getInstanceName());
+ assertNotNull("Cons1 Service available", refcons1);
+
+ CheckService cs_cons1 = (CheckService) getServiceObject(refcons1);
+ Properties props = cs_cons1.getProps();
+ Long id = (Long) props.get("id");
+ FooService fscons1 = (FooService) props.get("object");
+ assertEquals("id 1", 1, id.intValue());
+ checkCreatedObjects(prov, 1);
+
+
+ // Step 2 : create a second consumer
+ cons2.start();
+ ServiceReference refcons2 = helper.getServiceReferenceByName(CheckService.class.getName(), cons2.getInstanceName());
+ assertNotNull("Cons2 Service available", refcons2);
+
+ CheckService cs_cons2 = (CheckService) getServiceObject(refcons2);
+ Properties props2 = cs_cons2.getProps();
+ Long id2 = (Long) props2.get("id");
+ FooService fscons2 = (FooService) props2.get("object");
+ assertEquals("id 2", 2, id2.intValue());
+ checkCreatedObjects(prov, 2);
+
+
+ assertNotSame("Two objects", fscons1, fscons2);
+
+ // Step 3 : stop the second provider
+ System.out.println("cons2 stopping");
+ cons2.stop();
+ System.out.println("cons2 stopped");
+ checkCreatedObjects(prov, 1);
+
+ // Step 4 : stop the first consumer
+ cons1.stop();
+ checkCreatedObjects(prov, 0);
+ }
+
+ public void testObjectCreation() {
+ prov.start();
+
+ // The two consumers are started and use their own objects.
+ ServiceReference refcons1 = helper.getServiceReferenceByName(CheckService.class.getName(), cons1.getInstanceName());
+ assertNotNull("Cons1 Service available", refcons1);
+ CheckService cs_cons1 = (CheckService) getServiceObject(refcons1);
+ Properties props = cs_cons1.getProps();
+ FooService fscons1 = (FooService) props.get("object");
+
+ ServiceReference refcons2 = helper.getServiceReferenceByName(CheckService.class.getName(), cons2.getInstanceName());
+ assertNotNull("Cons2 Service available", refcons2);
+ CheckService cs_cons2 = (CheckService) getServiceObject(refcons2);
+ Properties props2 = cs_cons2.getProps();
+ FooService fscons2 = (FooService) props2.get("object");
+
+ checkCreatedObjects(prov, 2);
+ assertNotSame("Two objects", fscons1, fscons2);
+
+ // Stop the provider
+ prov.stop();
+ // Cons1 and 2 are invalid.
+ assertEquals("Cons1 invalidity", ComponentInstance.INVALID, cons1.getState());
+ assertEquals("Cons2 invalidity", ComponentInstance.INVALID, cons2.getState());
+
+ // No object created in prov
+ checkCreatedObjects(prov, 0);
+
+ // Restart the provider
+ prov.start();
+
+ // Consumers are valid.
+ assertEquals("Cons1 validity", ComponentInstance.VALID, cons1.getState());
+ assertEquals("Cons2 validity", ComponentInstance.VALID, cons2.getState());
+
+ // Check objects
+ refcons1 = helper.getServiceReferenceByName(CheckService.class.getName(), cons1.getInstanceName());
+ assertNotNull("Cons1 Service available", refcons1);
+ cs_cons1 = (CheckService) getServiceObject(refcons1);
+ props = cs_cons1.getProps();
+ Object fscons3 = (FooService) props.get("object");
+
+ refcons2 = helper.getServiceReferenceByName(CheckService.class.getName(), cons2.getInstanceName());
+ assertNotNull("Cons2 Service available", refcons2);
+ cs_cons2 = (CheckService) getServiceObject(refcons2);
+ props2 = cs_cons2.getProps();
+ Object fscons4 = (FooService) props2.get("object");
+
+ checkCreatedObjects(prov, 2);
+ assertNotSame("Two objects", fscons3, fscons4);
+ assertNotSame("Two new objects - 1", fscons3, fscons1);
+ assertNotSame("Two new objects - 2", fscons4, fscons2);
+
+ }
+
+ public void testTwoServices() {
+ cons3.stop();
+ prov2.start();
+ cons1.stop();
+ assertEquals("Prov valid", ComponentInstance.VALID, prov2.getState());
+ ServiceReference ref = helper.getServiceReferenceByName(FooService.class.getName(), prov2.getInstanceName());
+ assertNotNull("Service available", ref);
+ ServiceReference refBar = helper.getServiceReferenceByName(BarService.class.getName(), prov2.getInstanceName());
+ assertNotNull("Service available", refBar);
+ checkCreatedObjects(prov2, 0);
+
+ // Step 1 : create start one consumer
+ cons1.start();
+ ServiceReference refcons1 = helper.getServiceReferenceByName(CheckService.class.getName(), cons1.getInstanceName());
+ assertNotNull("Cons1 Service available", refcons1);
+
+ CheckService cs_cons1 = (CheckService) getServiceObject(refcons1);
+ Properties props = cs_cons1.getProps();
+ Long id = (Long) props.get("id");
+ FooService fscons1 = (FooService) props.get("object");
+ assertEquals("id 1", 1, id.intValue());
+ checkCreatedObjects(prov2, 1);
+
+
+ // Step 2 : create a second consumer
+ cons3.start();
+ ServiceReference refcons2 = helper.getServiceReferenceByName(CheckService.class.getName(), cons3.getInstanceName());
+ assertNotNull("Cons2 Service available", refcons2);
+
+ CheckService cs_cons2 = (CheckService) getServiceObject(refcons2);
+ Properties props2 = cs_cons2.getProps();
+ Long id2 = (Long) props2.get("id");
+ FooService fscons2 = (FooService) props2.get("object");
+ assertEquals("id 2", 2, id2.intValue());
+ checkCreatedObjects(prov2, 2);
+
+
+ assertNotSame("Two objects", fscons1, fscons2);
+
+ // Step 3 : stop the second provider
+ cons3.stop();
+ checkCreatedObjects(prov2, 1);
+
+ // Step 4 : stop the first consumer
+ cons1.stop();
+ checkCreatedObjects(prov, 0);
+ }
+
+}
diff --git a/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/ps/strategies/ProvidedServiceStrategyTestSuite.java b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/ps/strategies/ProvidedServiceStrategyTestSuite.java
new file mode 100755
index 0000000..9b1a99d
--- /dev/null
+++ b/ipojo/tests/core/service-providing-strategies/src/main/java/org/apache/felix/ipojo/test/scenarios/ps/strategies/ProvidedServiceStrategyTestSuite.java
@@ -0,0 +1,36 @@
+/*
+ * 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.ps.strategies;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.felix.ipojo.junit4osgi.OSGiTestSuite;
+import org.osgi.framework.BundleContext;
+
+public class ProvidedServiceStrategyTestSuite extends TestSuite {
+
+ public static Test suite(BundleContext bc) {
+ OSGiTestSuite ots = new OSGiTestSuite("Provided Service Strategy Test Suite", bc);
+ ots.addTestSuite(PerInstanceStrategyTest.class);
+ ots.addTestSuite(CustomStrategyTest.class);
+ return ots;
+ }
+
+}
diff --git a/ipojo/tests/core/service-providing-strategies/src/main/resources/metadata.xml b/ipojo/tests/core/service-providing-strategies/src/main/resources/metadata.xml
new file mode 100755
index 0000000..dccd19c
--- /dev/null
+++ b/ipojo/tests/core/service-providing-strategies/src/main/resources/metadata.xml
@@ -0,0 +1,42 @@
+<ipojo>
+ <!-- Simple provider -->
+ <component
+ classname="org.apache.felix.ipojo.test.scenarios.component.strategies.FooProviderType1"
+ name="PSS-FooProviderType-Instance" architecture="true">
+ <provides strategy="instance"/>
+ </component>
+
+ <component
+ classname="org.apache.felix.ipojo.test.scenarios.component.strategies.Consumer"
+ name="PSS-Cons" architecture="true">
+ <requires field="fs"/>
+ <provides/>
+ </component>
+
+ <component
+ classname="org.apache.felix.ipojo.test.scenarios.component.strategies.BarConsumer"
+ name="PSS-ConsBar" architecture="true">
+ <requires field="bs"/>
+ <provides/>
+ </component>
+
+ <component
+ classname="org.apache.felix.ipojo.test.scenarios.component.strategies.FooBarProviderType1"
+ name="PSS-FooBarProviderType-Instance" architecture="true">
+ <provides strategy="instance"/>
+ </component>
+
+ <component
+ classname="org.apache.felix.ipojo.test.scenarios.component.strategies.FooProviderType1"
+ name="PSS-FooProviderType-Custom" architecture="true">
+ <provides strategy="org.apache.felix.ipojo.test.scenarios.component.strategies.DummyCreationStrategy"/>
+ </component>
+
+ <component
+ classname="org.apache.felix.ipojo.test.scenarios.component.strategies.FooBarProviderType1"
+ name="PSS-FooBarProviderType-Custom" architecture="true">
+ <provides strategy="org.apache.felix.ipojo.test.scenarios.component.strategies.DummyCreationStrategy"/>
+ </component>
+
+
+</ipojo>