* Fix issue Felix-803:
The core xml schema accepted the 'interface' attribute in service dependencies. This attribute were replaced by 'specification' to be consistent with other service dependencies.
The 'interface' attribute is now prohibited.
* Fix issue Felix-805:
Instances were not created when the targeted factory becomes valid later.
* Add a mechanism to avoid that setter methods are called twice if two threads try to invoke the callback with the same value.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@711559 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
index 2f25cde..988b1f0 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
@@ -72,22 +72,26 @@
* @param bundle the bundle id declaring the instance
*/
synchronized void addInstance(Dictionary instance, long bundle) {
+ m_logger.log(Logger.DEBUG, "New instance to managed, looking for " + instance.get("component"));
ManagedInstance managed = new ManagedInstance(instance, bundle);
for (int i = 0; i < m_factories.size(); i++) {
IPojoFactory factory = (IPojoFactory) m_factories.get(i);
- if (factory.getState() == Factory.VALID && managed.match(factory)) {
- managed.create(factory);
- List list = (List) m_attached.get(factory);
- if (list == null) {
- list = new ArrayList();
- list.add(managed);
- m_attached.put(factory, list);
- // Subscribe to the factory state change
- factory.addFactoryStateListener(this);
- } else {
- list.add(managed);
+ if (managed.matchName(factory)) {
+ // Subscribe to the factory state change
+ m_logger.log(Logger.DEBUG, "Listen factory " + factory.getName() + " events");
+ factory.addFactoryStateListener(this);
+ if (factory.getState() == Factory.VALID && managed.match(factory)) {
+ managed.create(factory);
+ List list = (List) m_attached.get(factory);
+ if (list == null) {
+ list = new ArrayList();
+ list.add(managed);
+ m_attached.put(factory, list);
+ } else {
+ list.add(managed);
+ }
+ return;
}
- return;
}
}
// If there is no matching factory, add the instance to the idle list
@@ -144,13 +148,14 @@
*/
public synchronized void addFactory(IPojoFactory factory) {
List createdInstances = new ArrayList(1);
+ m_logger.log(Logger.DEBUG, "Add the factory " + factory.getName());
m_factories.add(factory);
for (int i = 0; i < m_idle.size(); i++) {
ManagedInstance managed = (ManagedInstance) m_idle.get(i);
- if (managed.match(factory)) {
+ if (managed.matchName(factory)) {
// We have to subscribe to the factory.
factory.addFactoryStateListener(this);
- if (factory.getState() == Factory.VALID) {
+ if (factory.getState() == Factory.VALID && managed.match(factory)) {
managed.create(factory);
List list = (List) m_attached.get(factory);
if (list == null) {
@@ -229,8 +234,10 @@
*/
public void stateChanged(Factory factory, int newState) {
if (newState == Factory.VALID) {
+ m_logger.log(Logger.DEBUG, "A factory is becoming valid : " + factory.getName());
onValidation((IPojoFactory) factory);
} else {
+ m_logger.log(Logger.DEBUG, "A factory is bocoming invalid : " + factory.getName());
onInvalidation((IPojoFactory) factory);
}
}
@@ -286,6 +293,19 @@
ComponentInstance getInstance() {
return m_instance;
}
+
+
+ /**
+ * Checks if the required factory name match with the given factory.
+ * This methods checks only the name, and not the configuration.
+ * @param factory the factory to test
+ * @return <code>true</code> if the factory name matches, <code>false</code>
+ * otherwise.
+ */
+ public boolean matchName(IPojoFactory factory) {
+ String component = (String) m_configuration.get("component");
+ return factory.getName().equals(component) || factory.getClassName().equalsIgnoreCase(component);
+ }
/**
* Checks if the given factory match with the factory
@@ -298,8 +318,7 @@
*/
public boolean match(IPojoFactory factory) {
// Test factory name (and classname)
- String component = (String) m_configuration.get("component");
- if (factory.getName().equals(component) || factory.getClassName().equalsIgnoreCase(component)) {
+ if (matchName(factory)) {
// Test factory accessibility
if (factory.m_isPublic || factory.getBundleContext().getBundle().getBundleId() == m_bundleId) {
// Test the configuration validity.
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
index 68fed56..ea44b1e 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
@@ -123,13 +123,17 @@
* @param msg the message to log
*/
private void dispatch(int level, String msg) {
-
- ServiceReference ref = m_context.getServiceReference(LogService.class.getName());
LogService log = null;
- if (ref != null) {
- log = (LogService) m_context.getService(ref);
+ ServiceReference ref = null;
+ try {
+ ref = m_context.getServiceReference(LogService.class.getName());
+ if (ref != null) {
+ log = (LogService) m_context.getService(ref);
+ }
+ } catch (IllegalStateException e) {
+ // Handle the case where the iPOJO bundle is stopping
}
-
+
String message = null;
switch (level) {
case DEBUG:
@@ -182,11 +186,15 @@
* @param exception the exception attached to the message
*/
private void dispatch(int level, String msg, Throwable exception) {
-
- ServiceReference ref = m_context.getServiceReference(LogService.class.getName());
LogService log = null;
- if (ref != null) {
- log = (LogService) m_context.getService(ref);
+ ServiceReference ref = null;
+ try {
+ ref = m_context.getServiceReference(LogService.class.getName());
+ if (ref != null) {
+ log = (LogService) m_context.getService(ref);
+ }
+ } catch (IllegalStateException e) {
+ // Handle the case where the iPOJO bundle is stopping
}
String message = null;
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
index 643f41a..a022d71 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
@@ -454,11 +454,10 @@
try {
if (instance == null) {
m_method.call(new Object[] { m_value });
- m_invoked = true;
} else {
m_method.call(instance, new Object[] { m_value });
- m_invoked = true;
}
+ m_invoked = true;
} catch (NoSuchMethodException e) {
m_handler.error("The method " + m_method + " does not exist in the implementation class " + m_manager.getClassName());
m_manager.stop();
diff --git a/ipojo/core/src/main/resources/core.xsd b/ipojo/core/src/main/resources/core.xsd
index c89b193..9cdbfcf 100644
--- a/ipojo/core/src/main/resources/core.xsd
+++ b/ipojo/core/src/main/resources/core.xsd
@@ -218,12 +218,12 @@
</xs:sequence>
<xs:attribute name="interface" type="xs:string"
- use="optional">
+ use="prohibited">
<xs:annotation>
- <xs:documentation>The interface describing the required service type. This attribute is needed only when using aggregate dependencies with field injection and when the type of this field is a list, vector, collection and set. This attribute is deprecated.</xs:documentation>
+ <xs:documentation>The interface describing the required service type. This attribute is needed only when using aggregate dependencies with field injection and when the type of this field is a list, vector, collection and set. This attribute is deprecated, use 'specification'.</xs:documentation>
</xs:annotation>
</xs:attribute>
-
+
<xs:attribute name="field" type="xs:string"
use="optional">
<xs:annotation>
diff --git a/ipojo/tests/core/configadmin/src/main/java/org/apache/felix/ipojo/test/scenarios/configadmin/ManagedServiceFactoryTestForServices.java b/ipojo/tests/core/configadmin/src/main/java/org/apache/felix/ipojo/test/scenarios/configadmin/ManagedServiceFactoryTestForServices.java
index 14f1485..867f66f 100644
--- a/ipojo/tests/core/configadmin/src/main/java/org/apache/felix/ipojo/test/scenarios/configadmin/ManagedServiceFactoryTestForServices.java
+++ b/ipojo/tests/core/configadmin/src/main/java/org/apache/felix/ipojo/test/scenarios/configadmin/ManagedServiceFactoryTestForServices.java
@@ -249,7 +249,7 @@
architecture = (Architecture) Utils.getServiceObject(context, Architecture.class.getName(), "(architecture.instance="+pid+")");
assertEquals("Assert Message", "message2", mes);
- // assertEquals("Assert count", 2, count);
+ assertEquals("Assert count", 2, count);
assertEquals("Check 1 object", 1, architecture.getInstanceDescription().getCreatedObjects().length);
try {
diff --git a/ipojo/tests/core/configadmin/src/main/java/org/apache/felix/ipojo/test/scenarios/configadmin/ManagedServiceTestForImmediate.java b/ipojo/tests/core/configadmin/src/main/java/org/apache/felix/ipojo/test/scenarios/configadmin/ManagedServiceTestForImmediate.java
index ab207f5..1027afc 100644
--- a/ipojo/tests/core/configadmin/src/main/java/org/apache/felix/ipojo/test/scenarios/configadmin/ManagedServiceTestForImmediate.java
+++ b/ipojo/tests/core/configadmin/src/main/java/org/apache/felix/ipojo/test/scenarios/configadmin/ManagedServiceTestForImmediate.java
@@ -217,10 +217,11 @@
FooService fs = (FooService) context.getService(ref);
Properties p = fs.fooProps();
String mes = p.getProperty("message");
- //int count = ((Integer) p.get("count")).intValue();
+ // int count1 = ((Integer) p.get("count")).intValue();
assertEquals("Check 1 object", 1, instance.getInstanceDescription().getCreatedObjects().length);
assertEquals("Check message - 1 (" + mes +")", "message2", mes); // Already reconfigured.
- // assertEquals("Check count", 2, count); // Two : 1) "message" on immediate, "message2" on the reconfiguration
+ // assertEquals("Check count", 2, count); // Two : 1) "message" on immediate, "message2" on the reconfiguration,
+ // not necessary as the property can be set before the immediate instance creation
instance.dispose();
@@ -256,10 +257,10 @@
fs = (FooService) context.getService(ref);
p = fs.fooProps();
mes = p.getProperty("message");
- //count = ((Integer) p.get("count")).intValue();
+ // int count = ((Integer) p.get("count")).intValue();
assertEquals("Check 1 object", 1, instance.getInstanceDescription().getCreatedObjects().length);
assertEquals("Check message already reconfigured", "message3", mes); // Already reconfigured.
- //assertEquals("Check count", 2, count); // message before the reconfiguration, message3 after the reconfiguration
+ //assertEquals("Check count", count1 + 1, count); // message before the reconfiguration, message3 after the reconfiguration
instance.dispose();
diff --git a/ipojo/tests/core/external-handlers/src/main/java/org/apache/felix/ipojo/test/scenarios/eh/HandlerTest.java b/ipojo/tests/core/external-handlers/src/main/java/org/apache/felix/ipojo/test/scenarios/eh/HandlerTest.java
index b1e0a03..09066ed 100644
--- a/ipojo/tests/core/external-handlers/src/main/java/org/apache/felix/ipojo/test/scenarios/eh/HandlerTest.java
+++ b/ipojo/tests/core/external-handlers/src/main/java/org/apache/felix/ipojo/test/scenarios/eh/HandlerTest.java
@@ -21,7 +21,6 @@
import java.util.Properties;
import org.apache.felix.ipojo.ComponentInstance;
-import org.apache.felix.ipojo.HandlerFactory;
import org.apache.felix.ipojo.HandlerManagerFactory;
import org.apache.felix.ipojo.architecture.Architecture;
import org.apache.felix.ipojo.junit4osgi.OSGiTestCase;
diff --git a/ipojo/tests/core/service-dependency-bindingpolicy/src/main/resources/metadata.xml b/ipojo/tests/core/service-dependency-bindingpolicy/src/main/resources/metadata.xml
index e4c0460..33f79ce 100644
--- a/ipojo/tests/core/service-dependency-bindingpolicy/src/main/resources/metadata.xml
+++ b/ipojo/tests/core/service-dependency-bindingpolicy/src/main/resources/metadata.xml
@@ -60,7 +60,7 @@
classname="org.apache.felix.ipojo.test.scenarios.service.dependency.policies.MethodCheckServiceProvider"
name="StaticMRefCheckServiceProvider" architecture="true">
<requires
- interface="org.apache.felix.ipojo.test.scenarios.service.dependency.service.FooService"
+ specification="org.apache.felix.ipojo.test.scenarios.service.dependency.service.FooService"
policy="static">
<callback type="bind" method="refBind" />
<callback type="unbind" method="refUnbind" />
@@ -139,7 +139,7 @@
name="StaticMRefOptionalCheckServiceProvider"
architecture="true">
<requires
- interface="org.apache.felix.ipojo.test.scenarios.service.dependency.service.FooService"
+ specification="org.apache.felix.ipojo.test.scenarios.service.dependency.service.FooService"
optional="true" policy="static">
<callback type="bind" method="refBind" />
<callback type="unbind" method="refUnbind" />
@@ -151,7 +151,7 @@
name="StaticMBothOptionalCheckServiceProvider"
architecture="true">
<requires
- interface="org.apache.felix.ipojo.test.scenarios.service.dependency.service.FooService"
+ specification="org.apache.felix.ipojo.test.scenarios.service.dependency.service.FooService"
optional="true" policy="static">
<callback type="bind" method="bothBind" />
<callback type="unbind" method="bothUnbind" />
@@ -220,7 +220,7 @@
name="StaticMRefMultipleCheckServiceProvider"
architecture="true">
<requires
- interface="org.apache.felix.ipojo.test.scenarios.service.dependency.service.FooService"
+ specification="org.apache.felix.ipojo.test.scenarios.service.dependency.service.FooService"
aggregate="true" policy="static">
<callback type="bind" method="refBind" />
<callback type="unbind" method="refUnbind" />