FELIX-4146 Add getInstances and getInstanceNames in the Factory interface
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1497007 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/runtime/composite-it/ipojo-composite-runtime-test/src/test/java/org/apache/felix/ipojo/runtime/core/FactoryManagementTest.java b/ipojo/runtime/composite-it/ipojo-composite-runtime-test/src/test/java/org/apache/felix/ipojo/runtime/core/FactoryManagementTest.java
index 93402e7..e357689 100644
--- a/ipojo/runtime/composite-it/ipojo-composite-runtime-test/src/test/java/org/apache/felix/ipojo/runtime/core/FactoryManagementTest.java
+++ b/ipojo/runtime/composite-it/ipojo-composite-runtime-test/src/test/java/org/apache/felix/ipojo/runtime/core/FactoryManagementTest.java
@@ -30,6 +30,7 @@
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
+import java.util.ArrayList;
import java.util.Dictionary;
import java.util.List;
import java.util.Properties;
@@ -113,6 +114,14 @@
return null;
}
+ public List<ComponentInstance> getInstances() {
+ return new ArrayList<ComponentInstance>();
+ }
+
+ public List<String> getInstancesNames() {
+ return new ArrayList<String>();
+ }
+
}
@Before
diff --git a/ipojo/runtime/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java b/ipojo/runtime/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java
index 8af0c6c..f219810 100644
--- a/ipojo/runtime/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java
+++ b/ipojo/runtime/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java
@@ -178,4 +178,12 @@
return m_delegate.getComponentMetadata();
}
+ public List<ComponentInstance> getInstances() {
+ return m_delegate.getInstances();
+ }
+
+ public List<String> getInstancesNames() {
+ return m_delegate.getInstancesNames();
+ }
+
}
diff --git a/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/FiveInstances.java b/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/FiveInstances.java
new file mode 100644
index 0000000..26484c2
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/FiveInstances.java
@@ -0,0 +1,27 @@
+/*
+ * 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.runtime.core.components;
+
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.runtime.core.services.NoService;
+
+@Component(name="FiveInstances")
+public class FiveInstances implements NoService {
+}
diff --git a/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/NoInstances.java b/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/NoInstances.java
new file mode 100644
index 0000000..97c9518
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/NoInstances.java
@@ -0,0 +1,27 @@
+/*
+ * 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.runtime.core.components;
+
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.runtime.core.services.NoService;
+
+@Component(name="NoInstances")
+public class NoInstances implements NoService {
+}
diff --git a/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/OneDuplicateInstance.java b/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/OneDuplicateInstance.java
new file mode 100644
index 0000000..8bf63c2
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/OneDuplicateInstance.java
@@ -0,0 +1,27 @@
+/*
+ * 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.runtime.core.components;
+
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.runtime.core.services.NoService;
+
+@Component(name="OneDuplicateInstance")
+public class OneDuplicateInstance implements NoService {
+}
diff --git a/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/NoService.java b/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/NoService.java
new file mode 100644
index 0000000..69cec05
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-factory-test/src/main/java/org/apache/felix/ipojo/runtime/core/services/NoService.java
@@ -0,0 +1,23 @@
+/*
+ * 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.runtime.core.services;
+
+public interface NoService {
+
+}
diff --git a/ipojo/runtime/core-it/ipojo-core-factory-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestInstances.java b/ipojo/runtime/core-it/ipojo-core-factory-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestInstances.java
new file mode 100644
index 0000000..f2978c9
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-factory-test/src/test/java/org/apache/felix/ipojo/runtime/core/TestInstances.java
@@ -0,0 +1,176 @@
+/*
+ * 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.runtime.core;
+
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.MissingHandlerException;
+import org.apache.felix.ipojo.UnacceptableConfiguration;
+import org.junit.Test;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import static junit.framework.Assert.*;
+
+/**
+ * Checks the retrieval of instances and instance names from the Factory.
+ */
+public class TestInstances extends Common {
+
+ @Test
+ public void testNoInstances() {
+ Factory factory = ipojoHelper.getFactory("NoInstances");
+ assertNotNull(factory);
+
+ assertNotNull(factory.getInstancesNames());
+ assertNotNull(factory.getInstances());
+
+ assertEquals(0, factory.getInstancesNames().size());
+ assertEquals(0, factory.getInstances().size());
+ }
+
+ @Test
+ public void testOneDuplicateInstance() {
+ Factory factory = ipojoHelper.getFactory("OneDuplicateInstance");
+ assertNotNull(factory);
+
+ // Create one instance
+ ComponentInstance instance = createInstanceOrFail(factory, "OneDuplicateInstance-0");
+
+ assertNotNull(factory.getInstancesNames());
+ assertNotNull(factory.getInstances());
+
+ assertEquals(1, factory.getInstancesNames().size());
+ assertEquals(1, factory.getInstances().size());
+
+ assertContains("", factory.getInstancesNames().toArray(new String[1]), "OneDuplicateInstance-0");
+
+ // Create another instance with the same name
+ // The instance should not be created, and we should have only the first instance
+ try {
+ createInstance(factory, "OneDuplicateInstance-0");
+ fail("The instance OneDuplicateInstance-0 has been created with factory " + factory.getName() + ". "
+ + "It's shouldn't have been created has it's a duplicate instance");
+ } catch (UnacceptableConfiguration e) {
+ // expected Exception
+ } catch (Exception e){
+ fail("Cannot create instance OneDuplicateInstance-0 with factory " + factory.getName() + ". "
+ + "The wrong exception has been raised : " + e.toString());
+ }
+ assertNotNull(factory.getInstancesNames());
+ assertNotNull(factory.getInstances());
+
+ assertEquals(1, factory.getInstancesNames().size());
+ assertEquals(1, factory.getInstances().size());
+
+ // Dispose of the instance
+ instance.dispose();
+
+ assertNotNull(factory.getInstancesNames());
+ assertNotNull(factory.getInstances());
+
+ assertEquals(0, factory.getInstancesNames().size());
+ assertEquals(0, factory.getInstances().size());
+ }
+
+ @Test
+ public void testFiveInstances() {
+ Factory factory = ipojoHelper.getFactory("FiveInstances");
+ assertNotNull(factory);
+
+ // No instances for the moment
+ assertNotNull(factory.getInstancesNames());
+ assertNotNull(factory.getInstances());
+
+ assertEquals(0, factory.getInstancesNames().size());
+ assertEquals(0, factory.getInstances().size());
+
+ // Create 5 instances
+ ComponentInstance[] instances = createNInstanceOrFail(factory, "FiveInstances", 5);
+
+ assertNotNull(factory.getInstancesNames());
+ assertNotNull(factory.getInstances());
+
+ assertEquals(5, factory.getInstancesNames().size());
+ assertEquals(5, factory.getInstances().size());
+
+ assertContains("", factory.getInstancesNames().toArray(new String[5]), "FiveInstances-0");
+ assertContains("", factory.getInstancesNames().toArray(new String[5]), "FiveInstances-1");
+ assertContains("", factory.getInstancesNames().toArray(new String[5]), "FiveInstances-2");
+ assertContains("", factory.getInstancesNames().toArray(new String[5]), "FiveInstances-3");
+ assertContains("", factory.getInstancesNames().toArray(new String[5]), "FiveInstances-4");
+
+ // Dispose of instances 0, 3 and 2
+ // 2 instances left
+ instances[0].dispose();
+ instances[3].dispose();
+ instances[2].dispose();
+
+
+ assertNotNull(factory.getInstancesNames());
+ assertNotNull(factory.getInstances());
+
+ assertEquals(2, factory.getInstancesNames().size());
+ assertEquals(2, factory.getInstances().size());
+
+ assertContains("", factory.getInstancesNames().toArray(new String[2]), "FiveInstances-1");
+ assertContains("", factory.getInstancesNames().toArray(new String[2]), "FiveInstances-4");
+
+ // Dispose of instances 1 and 4
+ // No instances left
+ instances[1].dispose();
+ instances[4].dispose();
+
+ assertNotNull(factory.getInstancesNames());
+ assertNotNull(factory.getInstances());
+
+ assertEquals(0, factory.getInstancesNames().size());
+ assertEquals(0, factory.getInstances().size());
+ }
+
+ public ComponentInstance[] createNInstanceOrFail(Factory factory, String baseName, Integer n) {
+ ComponentInstance[] instances = new ComponentInstance[n];
+ for (int i = 0; i < n; i++) {
+ instances[i] = createInstanceOrFail(factory, baseName + "-" + i);
+ }
+ return instances;
+ }
+
+ public ComponentInstance createInstanceOrFail(Factory factory, String name) {
+ ComponentInstance instance = null;
+ try {
+ instance = createInstance(factory, name);
+ } catch (Exception e) {
+ fail("Cannot create instance " + name + " with factory " + factory.getName() + ". "
+ + "Raised exception : " + e.toString());
+ }
+ return instance;
+ }
+
+ public ComponentInstance createInstance(Factory factory, String name)
+ throws MissingHandlerException, UnacceptableConfiguration, ConfigurationException {
+ Dictionary conf = new Hashtable();
+ conf.put("instance.name", name);
+ return factory.createComponentInstance(conf);
+ }
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Factory.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Factory.java
index c84885e..c1b5a21 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Factory.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Factory.java
@@ -18,15 +18,16 @@
*/
package org.apache.felix.ipojo;
-import java.util.Dictionary;
-import java.util.List;
-
import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
import org.apache.felix.ipojo.metadata.Element;
import org.osgi.framework.BundleContext;
+import java.util.Dictionary;
+import java.util.List;
+
/**
* Component Type Factory Service. This service is exposed by a instance manager factory, and allows the dynamic creation of component instance.
+ *
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public interface Factory {
@@ -36,20 +37,16 @@
* A valid factory is a factory where all required handlers are available.
*/
int VALID = 1;
-
/**
* Factory State.
* An invalid factory is a factory where at least one required handler is
* unavailable. Creating an instance with an invalid factory failed.
*/
int INVALID = 0;
-
-
/**
* Instance configuration can set the instance name using this property.
*/
String INSTANCE_NAME_PROPERTY = "instance.name";
-
/**
* Instance configuration can set the factory version they target using this property.
*/
@@ -57,35 +54,39 @@
/**
* Creates an instance manager (i.e. component type instance).
+ *
* @param configuration the configuration properties for this component.
* @return the created instance manager.
* @throws UnacceptableConfiguration if the given configuration is not valid.
- * @throws MissingHandlerException if an handler is missing.
- * @throws ConfigurationException if the instance configuration failed.
+ * @throws MissingHandlerException if an handler is missing.
+ * @throws ConfigurationException if the instance configuration failed.
*/
ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException;
/**
* Creates an instance manager (i.e. component type instance).
* The instance is created in the scope given in argument.
- * @param configuration the configuration properties for this component.
+ *
+ * @param configuration the configuration properties for this component.
* @param serviceContext the service context of the component.
* @return the created instance manager.
* @throws UnacceptableConfiguration if the given configuration is not valid.
- * @throws MissingHandlerException if an handler is missing.
- * @throws ConfigurationException if the instance configuration failed.
+ * @throws MissingHandlerException if an handler is missing.
+ * @throws ConfigurationException if the instance configuration failed.
*/
ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException;
/**
* Gets the component type information containing provided service,
* configuration properties ...
+ *
* @return the component type information.
*/
Element getDescription();
/**
* Gets the component type description.
+ *
* @return the component type description object
*/
ComponentTypeDescription getComponentDescription();
@@ -93,6 +94,7 @@
/**
* Checks if the given configuration is acceptable as a configuration
* of a component instance.
+ *
* @param conf the configuration to test
* @return <code>true</code> if the configuration is acceptable
*/
@@ -100,6 +102,7 @@
/**
* Returns the factory name.
+ *
* @return the name of the factory.
*/
String getName();
@@ -107,21 +110,24 @@
/**
* Reconfigures an instance already created. This configuration needs to
* have the name property to identify the instance.
+ *
* @param conf the configuration to reconfigure the instance. The instance.name property must be set to identify
* the instance to reconfigure.
- * @throws UnacceptableConfiguration if the given configuration is not consistent for the targeted instance.
- * @throws MissingHandlerException if an handler is missing.
+ * @throws UnacceptableConfiguration if the given configuration is not consistent for the targeted instance.
+ * @throws MissingHandlerException if an handler is missing.
*/
void reconfigure(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException;
/**
* Adds a factory state listener on the current factory.
+ *
* @param listener the listener to add
*/
void addFactoryStateListener(FactoryStateListener listener);
/**
* Removes the given factory state listener from the listener list.
+ *
* @param listener the listener to remove
*/
void removeFactoryStateListener(FactoryStateListener listener);
@@ -129,6 +135,7 @@
/**
* Gets the list of missing handlers.
* The handlers are given under the form namespace:name
+ *
* @return the list containing the name of missing handlers
*/
List getMissingHandlers();
@@ -136,6 +143,7 @@
/**
* Get the list of required handlers.
* The handlers are given under the form namespace:name
+ *
* @return the list containing the name of required handlers
*/
List getRequiredHandlers();
@@ -143,6 +151,7 @@
/**
* Returns the class name of the component type.
* For factories which does not contains a class, return "composite"
+ *
* @return the class name of the component type or "composite"
* @deprecated
*/
@@ -150,27 +159,47 @@
/**
* Returns the state of the factory.
+ *
* @return the state of the factory
*/
int getState();
/**
* Gets the bundle context of the factory.
+ *
* @return the bundle context of the factory.
*/
BundleContext getBundleContext();
/**
* Gets the version of the component type.
+ *
* @return the component type version or <code>null</code> if
- * not specified.
+ * not specified.
*/
String getVersion();
/**
* Gets the component type metadata (Element - Attribute structure)
+ *
* @return the root element of the component metadata. The result must <b>not</b> be modified.
*/
Element getComponentMetadata();
+ /**
+ * Gets the list of instances created by the factory. The instances must be still alive.
+ *
+ * @return the list of created (and living) instances
+ * @since 1.10.2
+ */
+ List<ComponentInstance> getInstances();
+
+ /**
+ * Gets the list of the names of the instances created by the factory. The instances must be still alive.
+ *
+ * @return the list of the names of created (and living) instances
+ * @since 1.10.2
+ */
+ List<String> getInstancesNames();
+
}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
index daebcf3..c817093 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
@@ -368,6 +368,28 @@
}
/**
+ * Gets the list of instances created by the factory. The instances must be still alive.
+ *
+ * @return the list of created (and living) instances
+ * @since 1.10.2
+ */
+ public List<ComponentInstance> getInstances() {
+ // m_componentInstances is a concurrent hashmap, we can create retrieve values directly.
+ return new ArrayList<ComponentInstance>(m_componentInstances.values());
+ }
+
+ /**
+ * Gets the list of the names of the instances created by the factory. The instances must be still alive.
+ *
+ * @return the list of the names of created (and living) instances
+ * @since 1.10.2
+ */
+ public List<String> getInstancesNames() {
+ // m_componentInstances is a concurrent hashmap, we can create retrieve values directly.
+ return new ArrayList<String>(m_componentInstances.keySet());
+ }
+
+ /**
* Computes the list of missing handlers.
* @return the list of missing handlers.
* @see org.apache.felix.ipojo.Factory#getMissingHandlers()