Author: pderop
Date: Fri Sep 18 22:09:45 2015
New Revision: 1703922
URL: http://svn.apache.org/viewvc?rev=1703922&view=rev
Log:
FELIX-5045: Committed a fix that avoid invoking optional dependency callbacks
before start.
Modified:
felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
Modified:
felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
URL:
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java?rev=1703922&r1=1703921&r2=1703922&view=diff
==============================================================================
---
felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
(original)
+++
felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
Fri Sep 18 22:09:45 2015
@@ -269,6 +269,12 @@ public class ComponentImpl implements Co
* @see
org.apache.felix.dm.itest.api.FELIX4913_OptionalCallbackInvokedTwiceTest which
reproduces the use case.
*/
private final Map<Event, Event> m_invokeCallbackCache = new
IdentityHashMap<>();
+
+ /**
+ * Flag used to check if the start callback has been invoked.
+ * We use this flag to ensure that we only inject optional dependencies
after the start callback has been called.
+ */
+ private boolean m_startCalled;
/**
* Default component declaration implementation.
@@ -974,7 +980,7 @@ public class ComponentImpl implements Co
if (oldState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED
&& newState == ComponentState.TRACKING_OPTIONAL) {
invokeAutoConfigInstanceBoundDependencies();
invokeAddRequiredInstanceBoundDependencies();
- invoke(m_callbackStart);
+ invokeStart();
invokeAddOptionalDependencies();
registerService();
notifyListeners(newState);
@@ -983,7 +989,7 @@ public class ComponentImpl implements Co
if (oldState == ComponentState.TRACKING_OPTIONAL && newState ==
ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
unregisterService();
invokeRemoveOptionalDependencies();
- invoke(m_callbackStop);
+ invokeStop();
invokeRemoveInstanceBoundDependencies();
notifyListeners(newState);
return true;
@@ -1006,7 +1012,17 @@ public class ComponentImpl implements Co
return false;
}
- /**
+ private void invokeStart() {
+ invoke(m_callbackStart);
+ m_startCalled = true;
+ }
+
+ private void invokeStop() {
+ invoke(m_callbackStop);
+ m_startCalled = false;
+ }
+
+ /**
* Sets the m_handlingChange flag that indicates if the state machine is
currently running the handleChange method.
*/
private void handlingChange(boolean transiting) {
@@ -1408,11 +1424,16 @@ public class ComponentImpl implements Co
/**
* This method ensures that a dependency callback is invoked only one
time;
+ * It also ensures that if the dependency callback is optional, then we
only
+ * invoke the bind method if the component start callback has already
been called.
*/
private void invokeCallbackSafe(DependencyContext dc, EventType type,
Event event) {
- if (m_invokeCallbackCache.put(event, event) == null) {
- dc.invokeCallback(type, event);
- }
+ if (! dc.isRequired() && ! m_startCalled) {
+ return;
+ }
+ if (m_invokeCallbackCache.put(event, event) == null) {
+ dc.invokeCallback(type, event);
+ }
}
/**