You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ui...@apache.org on 2013/05/28 22:30:01 UTC
svn commit: r1487101 [1/2] - in
/felix/sandbox/uiterlix/dependencymanager/core: ./ .externalToolBuilders/
.settings/ src/main/java/org/apache/felix/dm/
src/main/java/org/apache/felix/dm/impl/
src/main/java/org/apache/felix/dm/impl/dependencies/ src/mai...
Author: uiterlix
Date: Tue May 28 20:30:00 2013
New Revision: 1487101
URL: http://svn.apache.org/r1487101
Log:
work in progress in component serialization.
Added:
felix/sandbox/uiterlix/dependencymanager/core/.settings/org.eclipse.m2e.core.prefs
felix/sandbox/uiterlix/dependencymanager/core/bnd.bnd
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
- copied, changed from r1364521, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/AdvancedMultiPropertyFilterIndex.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/Filter.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/Property.java
Modified:
felix/sandbox/uiterlix/dependencymanager/core/.classpath
felix/sandbox/uiterlix/dependencymanager/core/.externalToolBuilders/Maven_Ant_Builder.launch
felix/sandbox/uiterlix/dependencymanager/core/.project
felix/sandbox/uiterlix/dependencymanager/core/.settings/org.eclipse.jdt.core.prefs
felix/sandbox/uiterlix/dependencymanager/core/pom.xml
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/Component.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ComponentImpl.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/FilterService.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/SerialExecutor.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/BundleContextInterceptor.java
felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/index/ServiceRegistryCache.java
Modified: felix/sandbox/uiterlix/dependencymanager/core/.classpath
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/.classpath?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/.classpath (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/.classpath Tue May 28 20:30:00 2013
@@ -1,11 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" path="src/main/java" including="**/*.java"/>
- <classpathentry kind="src" path="." including="LICENSE*|NOTICE*|DEPENDENCIES*|*.txt" excluding="**/*.java"/>
- <classpathentry kind="output" path="target/classes"/>
- <classpathentry kind="var" path="M2_REPO/org/easymock/easymock/2.4/easymock-2.4.jar"/>
- <classpathentry kind="var" path="M2_REPO/junit/junit/4.0/junit-4.0.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/mockito/mockito-all/1.7/mockito-all-1.7.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/osgi/org.osgi.compendium/4.2.0/org.osgi.compendium-4.2.0.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/osgi/org.osgi.core/4.2.0/org.osgi.core-4.2.0.jar"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-</classpath>
\ No newline at end of file
+ <classpathentry including="**/*.java" kind="src" path="src/main/java"/>
+ <classpathentry excluding="**/*.java" including="LICENSE*|NOTICE*|DEPENDENCIES*|*.txt" kind="src" path=""/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
Modified: felix/sandbox/uiterlix/dependencymanager/core/.externalToolBuilders/Maven_Ant_Builder.launch
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/.externalToolBuilders/Maven_Ant_Builder.launch?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/.externalToolBuilders/Maven_Ant_Builder.launch (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/.externalToolBuilders/Maven_Ant_Builder.launch Tue May 28 20:30:00 2013
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,clean"/>
Modified: felix/sandbox/uiterlix/dependencymanager/core/.project
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/.project?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/.project (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/.project Tue May 28 20:30:00 2013
@@ -1,22 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
- <name>org.apache.felix.dependencymanager</name>
- <comment>Apache Felix is an OSGi implementation. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
- <projects/>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
- <arguments>
- <dictionary>
- <key>LaunchConfigHandle</key>
- <value><project>/.externalToolBuilders/Maven_Ant_Builder.launch</value>
- </dictionary>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
\ No newline at end of file
+ <name>org.apache.felix.dependencymanager</name>
+ <comment>Apache Felix is an OSGi implementation. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
+ <arguments>
+ <dictionary>
+ <key>LaunchConfigHandle</key>
+ <value><project>/.externalToolBuilders/Maven_Ant_Builder.launch</value>
+ </dictionary>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>bndtools.core.bndbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ <nature>bndtools.core.bndnature</nature>
+ </natures>
+</projectDescription>
Modified: felix/sandbox/uiterlix/dependencymanager/core/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/.settings/org.eclipse.jdt.core.prefs?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/.settings/org.eclipse.jdt.core.prefs (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/.settings/org.eclipse.jdt.core.prefs Tue May 28 20:30:00 2013
@@ -1,3 +1,6 @@
-#Fri Feb 10 10:40:26 CET 2012
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.3
+#Fri Jul 20 08:52:08 CEST 2012
eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.3
+org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.4
Added: felix/sandbox/uiterlix/dependencymanager/core/.settings/org.eclipse.m2e.core.prefs
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/.settings/org.eclipse.m2e.core.prefs?rev=1487101&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/.settings/org.eclipse.m2e.core.prefs (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/.settings/org.eclipse.m2e.core.prefs Tue May 28 20:30:00 2013
@@ -0,0 +1,5 @@
+#Fri Jul 20 08:51:50 CEST 2012
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
Added: felix/sandbox/uiterlix/dependencymanager/core/bnd.bnd
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/bnd.bnd?rev=1487101&view=auto
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/bnd.bnd (added)
+++ felix/sandbox/uiterlix/dependencymanager/core/bnd.bnd Tue May 28 20:30:00 2013
@@ -0,0 +1,11 @@
+Bundle-SymbolicName: org.apache.felix.dependencymanager
+-buildpath: osgi.core;version=4.2.0,\
+ osgi.compendium
+Private-Package: org.apache.felix.dm.impl,\
+ org.apache.felix.dm.impl.dependencies,\
+ org.apache.felix.dm.impl.index,\
+ org.apache.felix.dm.impl.metatype
+Export-Package: org.apache.felix.dm,\
+ org.apache.felix.dm.tracker
+Bundle-Version: 3.1.1-SNAPSHOT
+-includeresource: src/main/java
\ No newline at end of file
Modified: felix/sandbox/uiterlix/dependencymanager/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/pom.xml?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/pom.xml (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/pom.xml Tue May 28 20:30:00 2013
@@ -30,7 +30,7 @@
</properties>
<name>Apache Felix Dependency Manager</name>
<artifactId>org.apache.felix.dependencymanager</artifactId>
- <version>3.1.0-SNAPSHOT</version>
+ <version>3.1.1-SNAPSHOT</version>
<packaging>bundle</packaging>
<dependencies>
<dependency>
@@ -88,7 +88,6 @@
<Export-Package>org.apache.felix.dm;version="3.0.0";provide:=true,org.apache.felix.dm.tracker;version="3.1.0";provide:=true</Export-Package>
<Import-Package>*</Import-Package>
<Private-Package>org.apache.felix.dm.impl, org.apache.felix.dm.impl.*</Private-Package>
- <!-- Uncomment this next line to include source code in the bundle. -->
<Include-Resource>src/main/java</Include-Resource>
</instructions>
</configuration>
Modified: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/Component.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/Component.java?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/Component.java (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/Component.java Tue May 28 20:30:00 2013
@@ -296,4 +296,5 @@ public interface Component {
* Returns the instance variable name of auto configuration of the specified class.
*/
public String getAutoConfigInstance(Class clazz);
+
}
Modified: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java Tue May 28 20:30:00 2013
@@ -38,10 +38,11 @@ import org.apache.felix.dm.impl.dependen
import org.apache.felix.dm.impl.dependencies.ResourceDependencyImpl;
import org.apache.felix.dm.impl.dependencies.ServiceDependencyImpl;
import org.apache.felix.dm.impl.dependencies.TemporalServiceDependencyImpl;
+import org.apache.felix.dm.impl.index.AdvancedMultiPropertyFilterIndex;
import org.apache.felix.dm.impl.index.AspectFilterIndex;
-import org.apache.felix.dm.impl.index.MultiPropertyExactFilter;
import org.apache.felix.dm.impl.index.ServiceRegistryCache;
import org.apache.felix.dm.impl.metatype.PropertyMetaDataImpl;
+import org.apache.felix.dm.impl.metatype.Resource;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
@@ -78,6 +79,7 @@ public class DependencyManager {
}
DependencyManager(BundleContext context, Logger logger) {
+ System.out.println("THIS IS XUI DEPENDENCY MANAGER!");
m_context = createContext(context);
m_logger = logger;
synchronized (m_dependencyManagers) {
@@ -106,8 +108,9 @@ public class DependencyManager {
m_serviceRegistryCache.addFilterIndex(new AspectFilterIndex());
}
else {
- String[] propList = props[i].split(",");
- m_serviceRegistryCache.addFilterIndex(new MultiPropertyExactFilter(propList));
+// String[] propList = props[i].split(",");
+// m_serviceRegistryCache.addFilterIndex(new MultiPropertyExactFilter(propList));
+ m_serviceRegistryCache.addFilterIndex(new AdvancedMultiPropertyFilterIndex(props[i]));
}
}
}
@@ -160,9 +163,9 @@ public class DependencyManager {
*
* @param service the service to add
*/
- public void add(Component service) {
- m_components.add(service);
- service.start();
+ public void add(final Component service) {
+ m_components.add(service);
+ service.start();
}
/**
@@ -171,9 +174,9 @@ public class DependencyManager {
*
* @param service the service to remove
*/
- public void remove(Component service) {
- service.stop();
- m_components.remove(service);
+ public void remove(final Component service) {
+ service.stop();
+ m_components.remove(service);
}
/**
Modified: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyService.java Tue May 28 20:30:00 2013
@@ -18,7 +18,12 @@
*/
package org.apache.felix.dm;
+import org.apache.felix.dm.impl.SerialExecutor;
+import org.osgi.framework.BundleContext;
+
/**
+ * Interface to the component, so dependencies can interact with it.
+ *
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public interface DependencyService {
@@ -42,18 +47,58 @@ public interface DependencyService {
* @param dependency the dependency
*/
public void dependencyChanged(Dependency dependency);
-
+
+ /**
+ * Returns the component instance.
+ *
+ * @return component instance
+ */
public Object getService(); // is also defined on the Service interface
+
+ /**
+ * Initializes the component. Instantiates it and injects the default injectables such
+ * as {@link BundleContext} and {@link DependencyManager}.
+ */
public void initService(); // was an implementation method TODO we use it in ConfDepImpl but should not (probably)
+
+ /**
+ * Returns <code>true</code> if this component is registered. In other words, all
+ * its required dependencies are available.
+ *
+ * @return <code>true</code> if the component is registered
+ */
public boolean isRegistered(); // impl method
+
+ /**
+ * Returns a list of all instances that are part of the composition for this component.
+ *
+ * @return an array of instances
+ */
public Object[] getCompositionInstances(); // impl method
+ /**
+ * Returns <code>true</code> if this component is instantiated.
+ *
+ * @return <code>true</code> if this component is instantiated
+ */
public boolean isInstantiated();
/**
* Can be called by the dependency whenever it wants to invoke callback methods.
*/
public void invokeCallbackMethod(Object[] instances, String methodName, Class[][] signatures, Object[][] parameters);
-
+
+ /**
+ * Returns the component interface.
+ *
+ * @return the component interface
+ */
public Component getServiceInterface();
+
+ /**
+ * TODO
+ * @return
+ */
+ public SerialExecutor getSerialExecutor();
+
}
Modified: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/ServiceDependency.java Tue May 28 20:30:00 2013
@@ -209,4 +209,6 @@ public interface ServiceDependency exten
public ServiceDependency setPropagate(Object instance, String method);
public ServiceDependency setInstanceBound(boolean isInstanceBound);
+
+ public void enableDebug(String debugKey);
}
Modified: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ComponentImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ComponentImpl.java?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ComponentImpl.java (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ComponentImpl.java Tue May 28 20:30:00 2013
@@ -23,6 +23,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
@@ -106,6 +107,10 @@ public class ComponentImpl implements Co
private Map m_autoConfigInstance = new HashMap();
private boolean m_isStarted = false;
+ private boolean m_changingState = false;
+ //debug
+ private StackTraceElement[] unregisterStackTrace;
+
public ComponentImpl(BundleContext context, DependencyManager manager, Logger logger) {
synchronized (VOID) {
@@ -132,198 +137,205 @@ public class ComponentImpl implements Co
synchronized (m_dependencies) {
oldState = m_state;
newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
- m_state = newState;
+// m_state = newState;
}
calculateStateChanges(oldState, newState);
}
private void calculateStateChanges(final State oldState, final State newState) {
- if (oldState.isInactive() && (newState.isTrackingOptional())) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- activateService(newState);
- }});
- }
- if (oldState.isInactive() && (newState.isWaitingForRequired())) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- startTrackingRequired(newState);
- }});
- }
- if (oldState.isWaitingForRequired() && newState.isTrackingOptional()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- activateService(newState);
- }});
- }
- if ((oldState.isWaitingForRequired()) && newState.isInactive()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- stopTrackingRequired(oldState);
- }});
- }
- if (oldState.isTrackingOptional() && newState.isWaitingForRequiredInstantiated()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- // TODO as far as I can see there is nothing left to do here
- // unbindService(newState);
- }});
- }
- if (oldState.isTrackingOptional() && newState.isWaitingForRequired()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- deactivateService(oldState);
- }});
- }
- if (oldState.isTrackingOptional() && newState.isBound()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- bindService(newState);
- }});
- }
- if (oldState.isTrackingOptional() && newState.isInactive()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- deactivateService(oldState);
- stopTrackingRequired(oldState);
- }});
- }
- if (oldState.isWaitingForRequiredInstantiated() && newState.isWaitingForRequired()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- deactivateService(oldState);
- }});
- }
- if (oldState.isWaitingForRequiredInstantiated() && newState.isInactive()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- deactivateService(oldState);
- stopTrackingRequired(oldState);
- }});
- }
- if (oldState.isWaitingForRequiredInstantiated() && newState.isBound()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- bindService(newState);
- }});
- }
- if (oldState.isBound() && newState.isWaitingForRequiredInstantiated()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- unbindService(oldState);
- }});
- }
- if (oldState.isBound() && newState.isWaitingForRequired()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- unbindService(oldState);
- deactivateService(oldState);
- }});
- }
- if (oldState.isBound() && newState.isInactive()) {
- m_executor.enqueue(new Runnable() {
- public void run() {
- unbindService(oldState);
- deactivateService(oldState);
- stopTrackingRequired(oldState);
- }});
- }
- m_executor.execute();
+ boolean canChangeState = false;
+ synchronized (this) {
+ if (!m_changingState) {
+ m_changingState = true;
+ canChangeState = m_changingState;
+ }
+ }
+ if (canChangeState) {
+ System.err.println("changing state from " + oldState + " to " + newState);
+ m_state = newState;
+ if (oldState.isInactive() && (newState.isTrackingOptional())) {
+ activateService(newState);
+ }
+ if (oldState.isInactive() && (newState.isWaitingForRequired())) {
+ startTrackingRequired(newState);
+ }
+ if (oldState.isWaitingForRequired() && newState.isTrackingOptional()) {
+ activateService(newState);
+ }
+ if ((oldState.isWaitingForRequired()) && newState.isInactive()) {
+ stopTrackingRequired(oldState);
+ }
+ if (oldState.isTrackingOptional() && newState.isWaitingForRequiredInstantiated()) {
+ // TODO as far as I can see there is nothing left to do here
+ // unbindService(newState);
+ }
+ if (oldState.isTrackingOptional() && newState.isWaitingForRequired()) {
+ deactivateService(oldState);
+ }
+ if (oldState.isTrackingOptional() && newState.isBound()) {
+ bindService(newState);
+ }
+ if (oldState.isTrackingOptional() && newState.isInactive()) {
+ deactivateService(oldState);
+ stopTrackingRequired(oldState);
+ }
+ if (oldState.isWaitingForRequiredInstantiated() && newState.isWaitingForRequired()) {
+ deactivateService(oldState);
+ }
+ if (oldState.isWaitingForRequiredInstantiated() && newState.isInactive()) {
+ deactivateService(oldState);
+ stopTrackingRequired(oldState);
+ }
+ if (oldState.isWaitingForRequiredInstantiated() && newState.isBound()) {
+ bindService(newState);
+ }
+ if (oldState.isBound() && newState.isWaitingForRequiredInstantiated()) {
+ unbindService(oldState);
+ }
+ if (oldState.isBound() && newState.isWaitingForRequired()) {
+ unbindService(oldState);
+ deactivateService(oldState);
+ }
+ if (oldState.isBound() && newState.isInactive()) {
+ unbindService(oldState);
+ deactivateService(oldState);
+ stopTrackingRequired(oldState);
+ }
+ synchronized (this) {
+ State nextOldState = null;
+ State nextNewState = null;
+ synchronized (m_dependencies) {
+ nextOldState = m_state;
+ // starting the dependency above might have triggered another state change, so
+ // we have to fetch the current state again
+ nextNewState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
+ }
+ m_changingState = false;
+ if (!nextOldState.equals(nextNewState)) {
+ System.err.println("next: " + nextOldState + " to " + nextNewState);
+ calculateStateChanges(nextOldState, nextNewState);
+ }
+ }
+ } else {
+ System.err.println("ignoring stateChange " + oldState + " to " + newState);
+ }
}
// TODO fix code duplication between add(Dependency) and add(List)
public Component add(final Dependency dependency) {
- State oldState, newState;
- synchronized (m_dependencies) {
- oldState = m_state;
- m_dependencies.add(dependency);
- }
-
- // if we're inactive, don't do anything, otherwise we might want to start
- // the dependency
- if (!oldState.isInactive()) {
- // if the dependency is required, it should be started regardless of the state
- // we're in
- if (dependency.isRequired()) {
- ((DependencyActivation) dependency).start(this);
- }
- else {
- // if the dependency is optional, it should only be started if we're in
- // bound state
- if (oldState.isBound()) {
- ((DependencyActivation) dependency).start(this);
- }
- }
- }
+ Runnable addDependencyRunnable = new Runnable() {
- synchronized (m_dependencies) {
- oldState = m_state;
- // starting the dependency above might have triggered another state change, so
- // we have to fetch the current state again
- newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
- m_state = newState;
- }
- calculateStateChanges(oldState, newState);
+ public void run() {
+ State oldState, newState;
+ synchronized (m_dependencies) {
+ oldState = m_state;
+ m_dependencies.add(dependency);
+ }
+
+ // if we're inactive, don't do anything, otherwise we might want to start
+ // the dependency
+ if (!oldState.isInactive()) {
+ // if the dependency is required, it should be started regardless of the state
+ // we're in
+ if (dependency.isRequired()) {
+ ((DependencyActivation) dependency).start(ComponentImpl.this);
+ }
+ else {
+ // if the dependency is optional, it should only be started if we're in
+ // bound state
+ if (oldState.isBound()) {
+ ((DependencyActivation) dependency).start(ComponentImpl.this);
+ }
+ }
+ }
+
+ synchronized (m_dependencies) {
+ oldState = m_state;
+ // starting the dependency above might have triggered another state change, so
+ // we have to fetch the current state again
+ newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
+// m_state = newState;
+ }
+ calculateStateChanges(oldState, newState);
+ }
+
+ };
+ m_executor.execute(addDependencyRunnable);
return this;
}
- public Component add(List dependencies) {
- State oldState, newState;
- synchronized (m_dependencies) {
- oldState = m_state;
- for (int i = 0; i < dependencies.size(); i++) {
- m_dependencies.add(dependencies.get(i));
- }
- }
-
- // if we're inactive, don't do anything, otherwise we might want to start
- // the dependencies
- if (!oldState.isInactive()) {
- for (int i = 0; i < dependencies.size(); i++) {
- Dependency dependency = (Dependency) dependencies.get(i);
- // if the dependency is required, it should be started regardless of the state
- // we're in
- if (dependency.isRequired()) {
- ((DependencyActivation) dependency).start(this);
- }
- else {
- // if the dependency is optional, it should only be started if we're in
- // bound state
- if (oldState.isBound()) {
- ((DependencyActivation) dependency).start(this);
- }
- }
- }
- }
+ public Component add(final List dependencies) {
+ Runnable addDependenciesRunnable = new Runnable() {
- synchronized (m_dependencies) {
- oldState = m_state;
- // starting the dependency above might have triggered another state change, so
- // we have to fetch the current state again
- newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
- m_state = newState;
- }
- calculateStateChanges(oldState, newState);
+ public void run() {
+ State oldState, newState;
+ synchronized (m_dependencies) {
+ oldState = m_state;
+ for (int i = 0; i < dependencies.size(); i++) {
+ m_dependencies.add(dependencies.get(i));
+ }
+ }
+
+ // if we're inactive, don't do anything, otherwise we might want to start
+ // the dependencies
+ if (!oldState.isInactive()) {
+ for (int i = 0; i < dependencies.size(); i++) {
+ Dependency dependency = (Dependency) dependencies.get(i);
+ // if the dependency is required, it should be started regardless of the state
+ // we're in
+ if (dependency.isRequired()) {
+ ((DependencyActivation) dependency).start(ComponentImpl.this);
+ }
+ else {
+ // if the dependency is optional, it should only be started if we're in
+ // bound state
+ if (oldState.isBound()) {
+ ((DependencyActivation) dependency).start(ComponentImpl.this);
+ }
+ }
+ }
+ }
+
+ synchronized (m_dependencies) {
+ oldState = m_state;
+ // starting the dependency above might have triggered another state change, so
+ // we have to fetch the current state again
+ newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
+// m_state = newState;
+ }
+ calculateStateChanges(oldState, newState);
+
+ }
+
+ };
+ m_executor.execute(addDependenciesRunnable);
return this;
}
- public Component remove(Dependency dependency) {
- State oldState, newState;
- synchronized (m_dependencies) {
- oldState = m_state;
- m_dependencies.remove(dependency);
- }
- if (oldState.isAllRequiredAvailable() || ((oldState.isWaitingForRequired() || oldState.isWaitingForRequiredInstantiated()) && dependency.isRequired())) {
- ((DependencyActivation) dependency).stop(this);
- }
- synchronized (m_dependencies) {
- // starting the dependency above might have triggered another state change, so
- // we have to fetch the current state again
- oldState = m_state;
- newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
- m_state = newState;
- }
- calculateStateChanges(oldState, newState);
+ public Component remove(final Dependency dependency) {
+ Runnable removeDependencyRunnable = new Runnable() {
+
+ public void run() {
+ State oldState, newState;
+ synchronized (m_dependencies) {
+ oldState = m_state;
+ m_dependencies.remove(dependency);
+ }
+ if (oldState.isAllRequiredAvailable() || ((oldState.isWaitingForRequired() || oldState.isWaitingForRequiredInstantiated()) && dependency.isRequired())) {
+ ((DependencyActivation) dependency).stop(ComponentImpl.this);
+ }
+ synchronized (m_dependencies) {
+ // starting the dependency above might have triggered another state change, so
+ // we have to fetch the current state again
+ oldState = m_state;
+ newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
+// m_state = newState;
+ }
+ calculateStateChanges(oldState, newState);
+
+ }
+ };
+ m_executor.execute(removeDependencyRunnable);
return this;
}
@@ -350,7 +362,7 @@ public class ComponentImpl implements Co
synchronized (m_dependencies) {
oldState = m_state;
newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
- m_state = newState;
+// m_state = newState;
}
if (newState.isAllRequiredAvailable() || newState.isWaitingForRequiredInstantiated()) {
updateInstance(dependency);
@@ -373,7 +385,7 @@ public class ComponentImpl implements Co
synchronized (m_dependencies) {
oldState = m_state;
newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
- m_state = newState;
+// m_state = newState;
}
if (newState.isAllRequiredAvailable()) {
updateInstance(dependency);
@@ -381,30 +393,57 @@ public class ComponentImpl implements Co
calculateStateChanges(oldState, newState);
}
- public synchronized void start() {
- if (!m_isStarted) {
- m_isStarted = true;
- State oldState, newState;
- synchronized (m_dependencies) {
- oldState = m_state;
- newState = new State((List) m_dependencies.clone(), true, m_isInstantiated, m_isBound);
- m_state = newState;
- }
- calculateStateChanges(oldState, newState);
- }
+ public void start() {
+ Runnable startRunnable = new Runnable() {
+
+ public void run() {
+ boolean needsStarting = false;
+ synchronized (ComponentImpl.this) {
+ if (!m_isStarted) {
+ m_isStarted = true;
+ needsStarting = true;
+ }
+ }
+ if (needsStarting) {
+ State oldState, newState;
+ synchronized (m_dependencies) {
+ oldState = m_state;
+ newState = new State((List) m_dependencies.clone(), true, m_isInstantiated, m_isBound);
+// m_state = newState;
+ }
+ calculateStateChanges(oldState, newState);
+ }
+
+ }
+ };
+ m_executor.enqueue(startRunnable);
+ m_executor.execute();
}
- public synchronized void stop() {
- if (m_isStarted) {
- m_isStarted = false;
- State oldState, newState;
- synchronized (m_dependencies) {
- oldState = m_state;
- newState = new State((List) m_dependencies.clone(), false, m_isInstantiated, m_isBound);
- m_state = newState;
- }
- calculateStateChanges(oldState, newState);
- }
+ public void stop() {
+ Runnable stopRunnable = new Runnable() {
+
+ public void run() {
+ boolean needsStopping = false;
+ synchronized (ComponentImpl.this) {
+ if (m_isStarted) {
+ m_isStarted = false;
+ needsStopping = true;
+ }
+ }
+ if (needsStopping) {
+ State oldState, newState;
+ synchronized (m_dependencies) {
+ oldState = m_state;
+ newState = new State((List) m_dependencies.clone(), false, m_isInstantiated, m_isBound);
+// m_state = newState;
+ }
+ calculateStateChanges(oldState, newState);
+ }
+ }
+ };
+ m_executor.enqueue(stopRunnable);
+ m_executor.execute();
}
public synchronized Component setInterface(String serviceName, Dictionary properties) {
@@ -479,10 +518,18 @@ public class ComponentImpl implements Co
return null;
}
- public synchronized Component setServiceProperties(Dictionary serviceProperties) {
- m_serviceProperties = serviceProperties;
- if ((m_registration != null) && (m_serviceName != null)) {
- m_registration.setProperties(calculateServiceProperties());
+ public Component setServiceProperties(Dictionary serviceProperties) {
+ boolean needsProperties = false;
+ Dictionary properties = null;
+ synchronized (this) {
+ m_serviceProperties = serviceProperties;
+ if ((m_registration != null) && (m_serviceName != null)) {
+ properties = calculateServiceProperties();
+ needsProperties = true;
+ }
+ }
+ if (needsProperties) {
+ m_registration.setProperties(properties);
}
return this;
}
@@ -587,7 +634,7 @@ public class ComponentImpl implements Co
// itself
invoke(init);
// see if any of this caused further state changes
- calculateStateChanges();
+// calculateStateChanges();
}
private void bindService(State state) {
@@ -890,18 +937,29 @@ public class ComponentImpl implements Co
private void unregisterService() {
m_isBound = false;
if (m_serviceName != null) {
- m_registration.unregister();
- configureImplementation(ServiceRegistration.class, NULL_REGISTRATION);
- m_registration = null;
+ if (m_registration != null) {
+ m_registration.unregister();
+ configureImplementation(ServiceRegistration.class, NULL_REGISTRATION);
+ m_registration = null;
+ if ("true".equals(System.getProperty("dm.dumpUnregisterStack", "false"))) {
+ unregisterStackTrace = Thread.currentThread().getStackTrace();
+ }
+ } else {
+ if (unregisterStackTrace == null) {
+ throw new IllegalStateException("Attempt to unregister a component that has already been unregistered.");
+ } else {
+ throw new IllegalStateException("Attempt to unregister a component that has already been unregistered. Previous stack = " + Arrays.toString(unregisterStackTrace));
+ }
+ }
}
}
private void updateInstance(Dependency dependency) {
if (dependency.isAutoConfig()) {
configureImplementation(dependency.getAutoConfigType(), dependency.getAutoConfigInstance(), dependency.getAutoConfigName());
- if (dependency.isPropagated() && m_registration != null) {
- m_registration.setProperties(calculateServiceProperties());
- }
+ }
+ if (dependency.isPropagated() && m_registration != null) {
+ m_registration.setProperties(calculateServiceProperties());
}
}
@@ -1162,4 +1220,8 @@ public class ComponentImpl implements Co
}
return -1;
}
+
+ public SerialExecutor getSerialExecutor() {
+ return m_executor;
+ }
}
Modified: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/FilterService.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/FilterService.java?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/FilterService.java (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/FilterService.java Tue May 28 20:30:00 2013
@@ -272,5 +272,6 @@ public class FilterService implements Co
public BundleContext getBundleContext() {
return m_component.getBundleContext();
- };
+ }
+
}
\ No newline at end of file
Modified: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/SerialExecutor.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/SerialExecutor.java?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/SerialExecutor.java (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/SerialExecutor.java Tue May 28 20:30:00 2013
@@ -33,6 +33,7 @@ import java.util.NoSuchElementException;
public final class SerialExecutor {
private final LinkedList m_workQueue = new LinkedList();
private Runnable m_active;
+ private Thread m_activeThread;
/**
* Enqueue a new task for later execution. This method is
@@ -68,6 +69,20 @@ public final class SerialExecutor {
scheduleNext();
}
}
+
+ public void execute(Runnable runnable) {
+ boolean inCurrentThread = false;
+ synchronized (this) {
+ inCurrentThread = Thread.currentThread().equals(m_activeThread);
+ }
+ if (inCurrentThread) {
+ // do immediately
+ runnable.run();
+ } else {
+ enqueue(runnable);
+ execute();
+ }
+ }
private void scheduleNext() {
Runnable active;
@@ -79,6 +94,11 @@ public final class SerialExecutor {
m_active = null;
}
active = m_active;
+ if (m_active != null) {
+ m_activeThread = Thread.currentThread();
+ } else {
+ m_activeThread = null;
+ }
}
if (active != null) {
active.run();
Modified: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java?rev=1487101&r1=1487100&r2=1487101&view=diff
==============================================================================
--- felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java Tue May 28 20:30:00 2013
@@ -200,6 +200,10 @@ public class ResourceDependencyImpl exte
long counter;
Object[] services;
synchronized (this) {
+ if (m_resources.indexOf(resource) == -1) {
+ m_logger.log(Logger.LOG_WARNING, "handleResourceRemoved called for unknown resource: " + resource);
+ return;
+ }
m_resourceProperties.remove(m_resources.indexOf(resource));
m_resources.remove(resource);
counter = m_resources.size();
Copied: felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java (from r1364521, felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java)
URL: http://svn.apache.org/viewvc/felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java?p2=felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java&r1=1364521&r2=1487101&rev=1487101&view=diff
==============================================================================
--- felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java (original)
+++ felix/sandbox/uiterlix/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java Tue May 28 20:30:00 2013
@@ -28,9 +28,11 @@ import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Properties;
import java.util.Set;
@@ -83,6 +85,16 @@ public class ServiceDependencyImpl exten
private String m_propagateCallbackMethod;
private final Map m_sr = new HashMap(); /* <DependencyService, Set<Tuple<ServiceReference, Object>> */
private Map m_componentByRank = new HashMap(); /* <Component, Map<Long, Map<Integer, Tuple>>> */
+
+ private boolean m_debug = false;
+ private String m_debugKey = null;
+
+ private final LinkedList m_injectionQueue = new LinkedList();
+
+ public void enableDebug(String key) {
+ this.m_debug = true;
+ this.m_debugKey = key;
+ }
private static final Comparator COMPARATOR = new Comparator() {
public int getRank(ServiceReference ref) {
@@ -416,7 +428,13 @@ public class ServiceDependencyImpl exten
}
}
if (needsStarting) {
- m_tracker.open();
+ // when the swapped callback is set, also track the aspects
+ boolean trackAllServices = false;
+ boolean trackAllAspects = false;
+ if (m_callbackSwapped != null) {
+ trackAllAspects = true;
+ }
+ m_tracker.open(trackAllServices, trackAllAspects);
}
}
@@ -447,78 +465,125 @@ public class ServiceDependencyImpl exten
return service;
}
- public void addedService(ServiceReference ref, Object service) {
- boolean makeAvailable = makeAvailable();
+ public void addedService(final ServiceReference ref, final Object service) {
+ if (m_debug) {
+ debug("addedservice: " + ref);
+ }
+// final boolean makeAvailable = makeAvailable();
Object[] services;
synchronized (this) {
services = m_services.toArray();
}
for (int i = 0; i < services.length; i++) {
- DependencyService ds = (DependencyService) services[i];
- if (makeAvailable) {
- if (ds.isInstantiated() && isInstanceBound() && isRequired()) {
- invokeAdded(ds, ref, service);
- }
- // The dependency callback will be defered until all required dependency are available.
- ds.dependencyAvailable(this);
- if (!isRequired()) {
- // For optional dependency, we always invoke callback, because at this point, we know
- // that the service has been started, and the service start method has been called.
- // (See the ServiceImpl.bindService method, which will activate optional dependencies using
- // startTrackingOptional() method).
- invokeAdded(ds, ref, service);
- }
- }
- else {
- ds.dependencyChanged(this);
- // At this point, either the dependency is optional (meaning that the service has been started,
- // because if not, then our dependency would not be active); or the dependency is required,
- // meaning that either the service is not yet started, or already started.
- // In all cases, we have to inject the required dependency.
-
- // we only try to invoke the method here if we are really already instantiated
- if (ds.isInstantiated() && ds.getCompositionInstances().length > 0) {
- invokeAdded(ds, ref, service);
- }
- }
+ final DependencyService ds = (DependencyService) services[i];
+
+ Runnable addedServiceRunnable = new Runnable() {
+
+ public void run() {
+ final boolean makeAvailable = makeAvailable();
+ if (makeAvailable) {
+ if (ds.isInstantiated() && isInstanceBound() && isRequired()) {
+ if (m_debug) {
+ debug("invoke added: " + ref);
+ }
+ invokeAdded(ds, ref, service); //**
+ }
+ // The dependency callback will be deferred until all required dependency are available.
+ if (m_debug) {
+ debug("dependency available: " + ref);
+ }
+ ds.dependencyAvailable(ServiceDependencyImpl.this);
+ if (!isRequired()) {
+ // For optional dependency, we always invoke callback, because at this point, we know
+ // that the service has been started, and the service start method has been called.
+ // (See the ServiceImpl.bindService method, which will activate optional dependencies using
+ // startTrackingOptional() method).
+ if (m_debug) {
+ debug("invoke added: " + ref);
+ }
+ invokeAdded(ds, ref, service); //**
+ }
+ }
+ else {
+ if (m_debug) {
+ debug("dependency changed: " + ref);
+ }
+ ds.dependencyChanged(ServiceDependencyImpl.this);
+ // At this point, either the dependency is optional (meaning that the service has been started,
+ // because if not, then our dependency would not be active); or the dependency is required,
+ // meaning that either the service is not yet started, or already started.
+ // In all cases, we have to inject the required dependency.
+
+ // we only try to invoke the method here if we are really already instantiated
+ if (ds.isInstantiated() && ds.getCompositionInstances().length > 0) {
+ if (m_debug) {
+ debug("invoke added: " + ref);
+ }
+ invokeAdded(ds, ref, service); //**
+ }
+ }
+ }
+ };
+ ds.getSerialExecutor().execute(addedServiceRunnable);
}
}
- public void modifiedService(ServiceReference ref, Object service) {
+ public void modifiedService(final ServiceReference ref, final Object service) {
Object[] services;
synchronized (this) {
services = m_services.toArray();
}
for (int i = 0; i < services.length; i++) {
- DependencyService ds = (DependencyService) services[i];
- ds.dependencyChanged(this);
- if (ds.isRegistered()) {
- invokeChanged(ds, ref, service);
- }
+ final DependencyService ds = (DependencyService) services[i];
+ Runnable modifiedServiceRunnable = new Runnable() {
+
+ public void run() {
+ ds.dependencyChanged(ServiceDependencyImpl.this);
+ if (ds.isRegistered()) {
+ invokeChanged(ds, ref, service);
+ }
+ }
+
+ };
+ ds.getSerialExecutor().execute(modifiedServiceRunnable);
}
}
- public void removedService(ServiceReference ref, Object service) {
- boolean makeUnavailable = makeUnavailable();
-
+ public void removedService(final ServiceReference ref, final Object service) {
+ if (m_debug) {
+ debug("removedservice: " + ref);
+ }
+ final boolean makeUnavailable = makeUnavailable();
+ if (m_debug) {
+ debug("make unavailable: " + makeUnavailable);
+ }
Object[] services;
synchronized (this) {
services = m_services.toArray();
}
for (int i = 0; i < services.length; i++) {
- DependencyService ds = (DependencyService) services[i];
- if (makeUnavailable) {
- ds.dependencyUnavailable(this);
- if (!isRequired() || (ds.isInstantiated() && isInstanceBound())) {
- invokeRemoved(ds, ref, service);
- }
- }
- else {
- ds.dependencyChanged(this);
- invokeRemoved(ds, ref, service);
- }
+ final DependencyService ds = (DependencyService) services[i];
+
+ Runnable removedServiceRunnable = new Runnable() {
+
+ public void run() {
+ if (makeUnavailable) {
+ ds.dependencyUnavailable(ServiceDependencyImpl.this);
+ // when the dependency is optional or the dependency is instance bound and the component is instantiated (and the dependency is required)
+ // then remove is invoked. In other cases the removed has been when the component was unconfigured.
+ if (!isRequired() || (ds.isInstantiated() && isInstanceBound())) {
+ invokeRemoved(ds, ref, service);
+ }
+ }
+ else {
+ ds.dependencyChanged(ServiceDependencyImpl.this);
+ invokeRemoved(ds, ref, service);
+ }
+ }
+ };
+ ds.getSerialExecutor().execute(removedServiceRunnable);
}
// unget what we got in addingService (see ServiceTracker 701.4.1)
m_context.ungetService(ref);
@@ -526,6 +591,9 @@ public class ServiceDependencyImpl exten
}
public void invokeAdded(DependencyService dependencyService, ServiceReference reference, Object service) {
+ if (m_debug) {
+ debug("invoke added");
+ }
boolean added = false;
synchronized (m_sr) {
Set set = (Set) m_sr.get(dependencyService);
@@ -546,14 +614,39 @@ public class ServiceDependencyImpl exten
}
}
- private void handleAspectAwareAdded(DependencyService dependencyService, ServiceReference reference, Object service) {
+ private synchronized void waitForCallbackLock(Runnable runnable) {
+ while (m_injectionQueue.indexOf(runnable) != 0) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ private synchronized void enqueueCallback(Runnable runnable) {
+ m_injectionQueue.addLast(runnable);
+ }
+
+ private synchronized void releaseCallback(Runnable runnable) {
+ m_injectionQueue.remove(runnable);
+ notifyAll();
+ }
+
+ private void handleAspectAwareAdded(final DependencyService dependencyService, final ServiceReference reference, final Object service) {
+ if (m_debug) {
+ debug("aspectawareadded: " + reference.getProperty("service.ranking"));
+ }
if (componentIsDependencyManagerFactory(dependencyService)) {
// component is either aspect or adapter factory instance, these must be ignored.
return;
}
boolean invokeAdded = false;
+ boolean invokeSwapped = false;
Integer ranking = ServiceUtil.getRankingAsInteger(reference);
- Tuple highestRankedService = null;
+ Tuple newHighestRankedService = null;
+ Tuple prevHighestRankedService = null;
+ Runnable callbackRunnable = null;
+ Map rankings = null;
synchronized (m_componentByRank) {
Long originalServiceId = ServiceUtil.getServiceIdAsLong(reference);
Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
@@ -562,7 +655,7 @@ public class ServiceDependencyImpl exten
componentMap = new HashMap(); /* <Long, Map<Integer, Tuple>> */
m_componentByRank.put(dependencyService, componentMap);
}
- Map rankings = (Map) componentMap.get(originalServiceId); /* <Integer, Tuple> */
+ rankings = (Map) componentMap.get(originalServiceId); /* <Integer, Tuple> */
if (rankings == null) {
// new component added
rankings = new HashMap(); /* <Integer, Tuple> */
@@ -572,14 +665,86 @@ public class ServiceDependencyImpl exten
}
if (!invokeAdded) {
- highestRankedService = swapHighestRankedService(dependencyService, originalServiceId, reference, service, ranking);
+ // current highest ranked
+ prevHighestRankedService = (Tuple)getHighestRankedService(dependencyService, originalServiceId).getValue();
+ newHighestRankedService = swapHighestRankedService(dependencyService, originalServiceId, reference, service, ranking);
+ if (m_debug) {
+ debug("prevhigh: " + prevHighestRankedService.getServiceReference().getProperty("service.ranking") + ", new high: " + newHighestRankedService.getServiceReference().getProperty("service.ranking"));
+ }
+ if (!prevHighestRankedService.getServiceReference().equals(newHighestRankedService.getServiceReference())) {
+ // new highest ranked service
+ if (m_debug) {
+ debug("New highest ranked to swap to");
+ }
+ invokeSwapped = true;
+ } else {
+ if (m_debug) {
+ debug("Ignoring lower ranked or irrelevant swap");
+ }
+ }
+ }
+ if (m_debug) {
+ debug(m_componentByRank.toString());
+ }
+
+ // up until this point should be synchronized on m_componentsByRank to keep integrity of the administration and consequences
+ // then the do phase comes, here we want to guarantee the effects of this operation are done like they were synchronized, however
+ // synchronization on m_componentsByRank to too course grained here, so we'd like to switch to synchronization on the
+ // original service id, therefore we're using our own guarded block to ensure the correct order.
+
+ if (invokeAdded) {
+ if (m_debug) {
+ debug("invoke added: " + reference.getProperty("service.ranking"));
+ }
+ callbackRunnable = createCallbackRunnable(dependencyService, reference, service, m_callbackAdded);
+ enqueueCallback(callbackRunnable);
+ } else if (invokeSwapped) {
+ if (m_debug) {
+ debug("invoke swapped: " + newHighestRankedService.getServiceReference().getProperty("service.ranking") + " replacing " + prevHighestRankedService.getServiceReference().getProperty("service.ranking"));
+ }
+ callbackRunnable = createSwapRunnable(dependencyService, prevHighestRankedService.getServiceReference(), prevHighestRankedService.getService(), newHighestRankedService.getServiceReference(), newHighestRankedService.getService());
+ enqueueCallback(callbackRunnable);
+ }
+ }
+ if (callbackRunnable != null) {
+ waitForCallbackLock(callbackRunnable);
+ synchronized (rankings) {
+ releaseCallback(callbackRunnable);
+ execute(callbackRunnable);
}
}
- if (invokeAdded) {
- invoke(dependencyService, reference, service, m_callbackAdded);
- } else {
- invokeSwappedCallback(dependencyService, highestRankedService.getServiceReference(), highestRankedService.getService(), reference, service);
- }
+ }
+
+ private Runnable createCallbackRunnable(final DependencyService dependencyService, final ServiceReference reference, final Object service, final String callback) {
+ return new Runnable() {
+ public void run() {
+ invoke(dependencyService, reference, service, callback);
+ }
+ public String toString() {
+ return callback + " on " + dependencyService;
+ }
+ };
+ }
+
+ private Runnable createSwapRunnable(final DependencyService dependencyService, final ServiceReference prevReference, final Object prevService, final ServiceReference newReference, final Object newService) {
+ return new Runnable() {
+ public void run() {
+ invokeSwappedCallback(dependencyService, prevReference, prevService, newReference, newService);
+ }
+ public String toString() {
+ return "swap on " + dependencyService;
+ }
+ };
+ }
+
+ private void execute(Runnable runnable) {
+ runnable.run();
+ }
+
+ private void debug(String message) {
+ if (m_debug) {
+ System.out.println("[" + m_debugKey + "] " + Thread.currentThread().getId() + " : " + message);
+ }
}
private boolean componentIsDependencyManagerFactory(DependencyService dependencyService) {
@@ -594,13 +759,14 @@ public class ServiceDependencyImpl exten
}
private Tuple swapHighestRankedService(DependencyService dependencyService, Long serviceId, ServiceReference newReference, Object newService, Integer newRanking) {
- // does a component with a higher ranking exists
+ // does a component with a higher ranking exist
synchronized (m_componentByRank) {
Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
Map rankings = (Map) componentMap.get(serviceId); /* <Integer, Tuple> */
- Entry highestEntry = getHighestRankedService(dependencyService, serviceId); /* <Integer, Tuple> */
- rankings.remove(highestEntry.getKey());
+// Entry highestEntry = getHighestRankedService(dependencyService, serviceId); /* <Integer, Tuple> */
+// rankings.remove(highestEntry.getKey());
rankings.put(newRanking, new Tuple(newReference, newService));
+ Entry highestEntry = getHighestRankedService(dependencyService, serviceId); /* <Integer, Tuple> */
return (Tuple) highestEntry.getValue();
}
}
@@ -643,6 +809,9 @@ public class ServiceDependencyImpl exten
// 1) a call to added(original-service)
// 2) that causes a swap
// 3) a call to removed(aspect-service) <-- that's what we're talking about
+ if (m_debug) {
+ debug(m_componentByRank.toString());
+ }
return (componentMap != null && rankings != null && rankings.size() == 1 && ((Entry)rankings.entrySet().iterator().next()).getKey()
.equals(ServiceUtil.getRankingAsInteger(reference)));
}
@@ -653,11 +822,17 @@ public class ServiceDependencyImpl exten
}
public void invokeRemoved(DependencyService dependencyService, ServiceReference reference, Object service) {
+ if (m_debug) {
+ debug("invoke removed");
+ }
boolean removed = false;
synchronized (m_sr) {
Set set = (Set) m_sr.get(dependencyService);
removed = (set != null && set.remove(new Tuple(reference, service)));
}
+ if (m_debug) {
+ debug("removed: " + removed);
+ }
if (removed) {
if (m_callbackSwapped != null) {
handleAspectAwareRemoved(dependencyService, reference, service);
@@ -669,26 +844,56 @@ public class ServiceDependencyImpl exten
}
private void handleAspectAwareRemoved(DependencyService dependencyService, ServiceReference reference, Object service) {
+ if (m_debug) {
+ debug("aspectawareremoved: " + reference.getProperty("service.ranking"));
+ }
if (componentIsDependencyManagerFactory(dependencyService)) {
// component is either aspect or adapter factory instance, these must be ignored.
return;
}
+ // we might need to swap here too!
+ boolean invokeRemoved = false;
Long serviceId = ServiceUtil.getServiceIdAsLong(reference);
- synchronized (m_componentByRank) {
- if (isLastService(dependencyService, reference, service, serviceId)) {
- invoke(dependencyService, reference, service, m_callbackRemoved);
+ Tuple prevHighestRankedService = null;
+ Tuple newHighestRankedService = null;
+ boolean invokeSwapped = false;
+ Map rankings = null;
+ Runnable callbackRunnable = null;
+ synchronized (m_componentByRank) {
+ Long originalServiceId = ServiceUtil.getServiceIdAsLong(reference);
+ if (isLastService(dependencyService, reference, service, serviceId)) {
+ invokeRemoved = true;
+ } else {
+ // not the last service, but should we swap?
+ prevHighestRankedService = (Tuple)getHighestRankedService(dependencyService, originalServiceId).getValue();
+ if (prevHighestRankedService.getServiceReference().equals(reference)) {
+ // swapping out
+ if (m_debug) {
+ debug("Swap out on remove!");
+ }
+ invokeSwapped = true;
}
- Long originalServiceId = ServiceUtil.getServiceIdAsLong(reference);
+ }
+ if (m_debug) {
+ debug("is last service: " + invokeRemoved);
+ }
+ // cleanup
+ try {
Map componentMap = (Map) m_componentByRank.get(dependencyService); /* <Long, Map<Integer, Tuple>> */
if (componentMap != null) {
- Map rankings = (Map) componentMap.get(originalServiceId); /* <Integer, Tuple> */
+ rankings = (Map) componentMap.get(originalServiceId); /* <Integer, Tuple> */
+ List rankingsToRemove = new ArrayList();
for (Iterator entryIterator = rankings.entrySet().iterator(); entryIterator.hasNext(); ) {
Entry mapEntry = (Entry) entryIterator.next();
if (((Tuple)mapEntry.getValue()).getServiceReference().equals(reference)) {
// remove the reference
- rankings.remove(mapEntry.getKey());
+ // rankings.remove(mapEntry.getKey());
+ rankingsToRemove.add(mapEntry.getKey());
}
}
+ for (Iterator rankingIterator = rankingsToRemove.iterator(); rankingIterator.hasNext(); ) {
+ rankings.remove(rankingIterator.next());
+ }
if (rankings.size() == 0) {
componentMap.remove(originalServiceId);
}
@@ -696,10 +901,41 @@ public class ServiceDependencyImpl exten
m_componentByRank.remove(dependencyService);
}
}
+ } catch (Exception e) {
+ e.printStackTrace();
}
+ // determine current highest ranked service
+ if (invokeSwapped) {
+ newHighestRankedService = (Tuple)getHighestRankedService(dependencyService, originalServiceId).getValue();
+ }
+ if (invokeRemoved) {
+ // handle invoke outside the sync block since we won't know what will happen there
+ if (m_debug) {
+ debug("invoke removed: " + reference.getProperty("service.ranking"));
+ }
+ callbackRunnable = createCallbackRunnable(dependencyService, reference, service, m_callbackRemoved);
+ enqueueCallback(callbackRunnable);
+ } else if (invokeSwapped) {
+ if (m_debug) {
+ debug("invoke swapped: " + newHighestRankedService.getServiceReference().getProperty("service.ranking") + " replacing " + prevHighestRankedService.getServiceReference().getProperty("service.ranking"));
+ }
+ callbackRunnable = createSwapRunnable(dependencyService, prevHighestRankedService.getServiceReference(), prevHighestRankedService.getService(), newHighestRankedService.getServiceReference(), newHighestRankedService.getService());
+ enqueueCallback(callbackRunnable);
+ }
+ }
+ if (callbackRunnable != null) {
+ waitForCallbackLock(callbackRunnable);
+ synchronized (rankings) {
+ releaseCallback(callbackRunnable);
+ execute(callbackRunnable);
+ }
+ }
}
public void invoke(DependencyService dependencyService, ServiceReference reference, Object service, String name) {
+ if (m_debug) {
+ debug("invoke: " + name);
+ }
if (name != null) {
dependencyService.invokeCallbackMethod(getCallbackInstances(dependencyService), name,
new Class[][] {
@@ -724,11 +960,26 @@ public class ServiceDependencyImpl exten
throw new IllegalStateException("Attempt to swap a service for a service with the same rank! previousReference: " + previousReference + ", currentReference: " + currentServiceReference);
}
- component.invokeCallbackMethod(getCallbackInstances(component), m_callbackSwapped, new Class[][] { { m_trackedServiceName, m_trackedServiceName },
- { Object.class, Object.class }, { ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName },
- { ServiceReference.class, Object.class, ServiceReference.class, Object.class } }, new Object[][] { { previous, current },
- { previous, current }, { previousReference, previous, currentServiceReference, current },
- { previousReference, previous, currentServiceReference, current } });
+ component.invokeCallbackMethod(getCallbackInstances(component), m_callbackSwapped, new Class[][] {
+ { m_trackedServiceName, m_trackedServiceName },
+ { Object.class, Object.class },
+ { ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName },
+ { ServiceReference.class, Object.class, ServiceReference.class, Object.class },
+ { Component.class, m_trackedServiceName, m_trackedServiceName },
+ { Component.class, Object.class, Object.class },
+ { Component.class, ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName },
+ { Component.class, ServiceReference.class, Object.class, ServiceReference.class, Object.class }
+ },
+ new Object[][] {
+ { previous, current },
+ { previous, current },
+ { previousReference, previous, currentServiceReference, current },
+ { previousReference, previous, currentServiceReference, current },
+ { component, previous, current },
+ { component, previous, current },
+ { component, previousReference, previous, currentServiceReference, current },
+ { component, previousReference, previous, currentServiceReference, current }
+ });
}
protected synchronized boolean makeAvailable() {
@@ -740,7 +991,7 @@ public class ServiceDependencyImpl exten
}
private synchronized boolean makeUnavailable() {
- if ((isAvailable()) && (!m_tracker.hasReference())) {
+ if ((isAvailable()) && (m_tracker.getServiceReference() == null)) {
m_isAvailable = false;
return true;
}
@@ -1066,6 +1317,9 @@ public class ServiceDependencyImpl exten
}
public void invokeAdded(DependencyService service) {
+ if (m_debug) {
+ debug("invoke added due to configure. (component is activated)");
+ }
ServiceReference[] refs = m_tracker.getServiceReferences();
if (refs != null) {
for (int i = 0; i < refs.length; i++) {
@@ -1077,20 +1331,27 @@ public class ServiceDependencyImpl exten
}
public void invokeRemoved(DependencyService service) {
+ if (m_debug) {
+ debug("invoke removed due to unconfigure. (component is destroyed)");
+ }
Set references = null;
+ Object[] tupleArray = null;
synchronized (m_sr) {
references = (Set) m_sr.get(service);
+ // is this null check necessary ??
+ if (references != null) {
+ tupleArray = references.toArray(new Tuple[references.size()]);
+// references.clear();
+ }
}
- Tuple[] refs = (Tuple[]) (references != null ? references.toArray(new Tuple[references.size()]) : new Tuple[0]);
+
+ Tuple[] refs = (Tuple[]) (tupleArray != null ? tupleArray : new Tuple[0]);
for (int i = 0; i < refs.length; i++) {
ServiceReference sr = refs[i].getServiceReference();
Object svc = refs[i].getService();
invokeRemoved(service, sr, svc);
}
- if (references != null) {
- references.clear();
- }
}
public Dictionary getProperties() {