FELIX-4869: Fixed a bug where optional dependency callbacks are not invoked if the optional dependency
is added while the component is fully started (TRACKING_OPTIONAL), and while dependency is already available.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1676513 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
index f08d4c1..63bfe70 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
@@ -343,40 +343,44 @@
dependencyEvents.add(e);
dc.setAvailable(true);
- // Recalculate state changes. We only do this if the dependency is started. If the dependency is not started,
- // it means it is actually starting. And in this case, we don't recalculate state changes now. We'll do it
- // once all currently available services are found, and then after, we'll recalculate state change
- // (see the startDependencies method).
+ // In the following switch block, we only recalculate state changes
+ // if the dependency is fully started. If the dependency is not started,
+ // it means it is actually starting (the service tracker is executing the open method).
+ // And in this case, we don't recalculate state changes now. We'll do it
+ // once all currently available services are found, and then after,
+ // we'll recalculate state change (see the startDependencies method).
+ //
// All this is done for two reasons:
// 1- optimization: it is preferable to recalculate state changes once we know about all currently available dependency services
// (after the tracker has returned from its open method).
// 2- This also allows to determine the list of currently available dependency services from within the component start method callback
// (this will be extremely useful when porting the Felix SCR on top of DM4).
- if (dc.isStarted()) {
- switch (m_state) {
- case WAITING_FOR_REQUIRED:
- if (dc.isRequired())
- handleChange();
- break;
- case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
- if (!dc.isInstanceBound()) {
- if (dc.isRequired()) {
- dc.invokeCallback(EventType.ADDED, e);
- }
- updateInstance(dc, e, false, true);
- }
- else {
- if (dc.isRequired())
- handleChange();
- }
- break;
- case TRACKING_OPTIONAL:
- dc.invokeCallback(EventType.ADDED, e);
- updateInstance(dc, e, false, true);
- break;
- default:
+ switch (m_state) {
+ case WAITING_FOR_REQUIRED:
+ if (dc.isStarted() && dc.isRequired()) {
+ // if dependency is starting, we'll handle change after the tracker has returned (see startDependencies method).
+ handleChange();
}
+ break;
+ case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
+ if (!dc.isInstanceBound()) {
+ if (dc.isRequired()) {
+ dc.invokeCallback(EventType.ADDED, e);
+ }
+ updateInstance(dc, e, false, true);
+ } else {
+ if (dc.isStarted() && dc.isRequired()) {
+ // if dependency is starting, we'll handle change after the tracker has returned (see startDependencies method).
+ handleChange();
+ }
+ }
+ break;
+ case TRACKING_OPTIONAL:
+ dc.invokeCallback(EventType.ADDED, e);
+ updateInstance(dc, e, false, true);
+ break;
+ default:
}
}
@@ -388,22 +392,20 @@
dependencyEvents.remove(e);
dependencyEvents.add(e);
- if (dc.isStarted()) {
- switch (m_state) {
- case TRACKING_OPTIONAL:
+ switch (m_state) {
+ case TRACKING_OPTIONAL:
+ dc.invokeCallback(EventType.CHANGED, e);
+ updateInstance(dc, e, true, false);
+ break;
+
+ case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
+ if (!dc.isInstanceBound()) {
dc.invokeCallback(EventType.CHANGED, e);
updateInstance(dc, e, true, false);
- break;
-
- case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
- if (!dc.isInstanceBound()) {
- dc.invokeCallback(EventType.CHANGED, e);
- updateInstance(dc, e, true, false);
- }
- break;
- default:
- // noop
}
+ break;
+ default:
+ // noop
}
}
@@ -430,24 +432,21 @@
// Now, really remove the dependency event.
dependencyEvents.remove(e);
- // Only check if the component instance has to be updated if the dependency is really started.
- if (dc.isStarted()) {
- // Depending on the state, we possible have to invoke the callbacks and update the component instance.
- switch (m_state) {
- case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
- if (!dc.isInstanceBound()) {
- if (dc.isRequired()) {
- dc.invokeCallback(EventType.REMOVED, e);
- }
- updateInstance(dc, e, false, false);
+ // Depending on the state, we possible have to invoke the callbacks and update the component instance.
+ switch (m_state) {
+ case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
+ if (!dc.isInstanceBound()) {
+ if (dc.isRequired()) {
+ dc.invokeCallback(EventType.REMOVED, e);
}
- break;
- case TRACKING_OPTIONAL:
- dc.invokeCallback(EventType.REMOVED, e);
updateInstance(dc, e, false, false);
- break;
- default:
}
+ break;
+ case TRACKING_OPTIONAL:
+ dc.invokeCallback(EventType.REMOVED, e);
+ updateInstance(dc, e, false, false);
+ break;
+ default:
}
}
@@ -459,25 +458,23 @@
dependencyEvents.remove(oldEvent);
dependencyEvents.add(newEvent);
- if (dc.isStarted()) {
- // Depending on the state, we possible have to invoke the callbacks and update the component instance.
- switch (m_state) {
- case WAITING_FOR_REQUIRED:
- // No need to swap, we don't have yet injected anything
- break;
- case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
- // Only swap *non* instance-bound dependencies
- if (!dc.isInstanceBound()) {
- if (dc.isRequired()) {
- dc.invokeCallback(EventType.SWAPPED, oldEvent, newEvent);
- }
+ // Depending on the state, we possible have to invoke the callbacks and update the component instance.
+ switch (m_state) {
+ case WAITING_FOR_REQUIRED:
+ // No need to swap, we don't have yet injected anything
+ break;
+ case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
+ // Only swap *non* instance-bound dependencies
+ if (!dc.isInstanceBound()) {
+ if (dc.isRequired()) {
+ dc.invokeCallback(EventType.SWAPPED, oldEvent, newEvent);
}
- break;
- case TRACKING_OPTIONAL:
- dc.invokeCallback(EventType.SWAPPED, oldEvent, newEvent);
- break;
- default:
}
+ break;
+ case TRACKING_OPTIONAL:
+ dc.invokeCallback(EventType.SWAPPED, oldEvent, newEvent);
+ break;
+ default:
}
}
@@ -742,7 +739,7 @@
}
}
- private void instantiateComponent() {
+ void instantiateComponent() {
m_logger.debug("instantiating component.");
// TODO add more complex factory instantiations of one or more components in a composition here