You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2015/09/19 00:09:45 UTC
svn commit: r1703922 -
/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
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);
+ }
}
/**