Added the notion of ranking to aspects so they can dynamically be chained. Fixed a bug in bundle dependencies.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@918508 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/core/pom.xml b/dependencymanager/core/pom.xml
index 12725dc..6acd83c 100644
--- a/dependencymanager/core/pom.xml
+++ b/dependencymanager/core/pom.xml
@@ -55,9 +55,9 @@
<Export-Package>org.apache.felix.dm;version="3.0.0",org.apache.felix.dm.service;version="3.0.0",org.apache.felix.dm.management;version="3.0.0",org.apache.felix.dm.dependencies;version="3.0.0",org.apache.felix.dm.resources;version="3.0.0"</Export-Package>
<Import-Package>!org.apache.felix.dm,!org.apache.felix.dm.service,!org.apache.felix.dm.management,!org.apache.felix.dm.dependencies,!org.apache.felix.dm.resources,*</Import-Package>
<Private-Package>org.apache.felix.dm.impl,org.apache.felix.dm.impl.dependencies,org.apache.felix.dm.impl.tracker</Private-Package>
- <!-- Uncomment this line to include source code in the bundle.
+ <!-- Uncomment this line to include source code in the bundle.-->
<Include-Resource>src/main/java</Include-Resource>
- -->
+ <!-- -->
</instructions>
</configuration>
</plugin>
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
index 4b07c24..03c5738 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
@@ -148,8 +148,11 @@
return m_manager.createResourceDependency();
}
- public Service createAspectService(Class serviceInterface, String serviceFilter, Object aspectImplementation, Dictionary properties) {
- return m_manager.createAspectService(serviceInterface, serviceFilter, aspectImplementation, properties);
+ public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object aspectImplementation, Dictionary properties) {
+ return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, aspectImplementation, properties);
+ }
+ public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, Dictionary properties) {
+ return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, factory, factoryCreateMethod, properties);
}
public Service createAdapterService(Class serviceInterface, String serviceFilter, Class adapterInterface, Object adapterImplementation, Dictionary adapterProperties) {
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
index f608e16..65b97b7 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
@@ -54,6 +54,7 @@
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class DependencyManager {
+ public static final String ASPECT = "org.apache.felix.dependencymanager.aspect";
private final BundleContext m_context;
private final Logger m_logger;
private List m_services = Collections.synchronizedList(new ArrayList());
@@ -167,15 +168,33 @@
* @param aspectProperties additional properties to use with the aspect service registration
* @return a service that acts as a factory for generating aspects
*/
- public Service createAspectService(Class serviceInterface, String serviceFilter, Object aspectImplementation, Dictionary aspectProperties) {
+ public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object aspectImplementation, Dictionary aspectProperties) {
return createService()
- .setImplementation(new AspectImpl(serviceInterface, serviceFilter, aspectImplementation, aspectProperties))
+ .setImplementation(new AspectImpl(serviceInterface, serviceFilter, ranking, aspectImplementation, aspectProperties))
.add(createServiceDependency()
- .setService(serviceInterface, serviceFilter)
+ .setService(serviceInterface, createAspectFilter(serviceFilter))
.setAutoConfig(false)
.setCallbacks("added", "removed")
);
}
+ public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, Dictionary aspectProperties) {
+ return createService()
+ .setImplementation(new AspectImpl(serviceInterface, serviceFilter, ranking, factory, factoryCreateMethod, aspectProperties))
+ .add(createServiceDependency()
+ .setService(serviceInterface, createAspectFilter(serviceFilter))
+ .setAutoConfig(false)
+ .setCallbacks("added", "removed")
+ );
+ }
+ private String createAspectFilter(String filter) {
+ // we only want to match services which are not themselves aspects
+ if (filter == null || filter.length() == 0) {
+ return "(!(" + ASPECT + "=*))";
+ }
+ else {
+ return "(&(!(" + ASPECT + "=*))" + filter + ")";
+ }
+ }
/**
* Creates a new adapter. The adapter will be applied to any service that
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectImpl.java
index 29fa6b3..31c7a20 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectImpl.java
@@ -23,7 +23,9 @@
import java.util.List;
import java.util.Properties;
+import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
public class AspectImpl extends AbstractDecorator {
@@ -32,18 +34,38 @@
private final String m_serviceFilter;
private final Object m_aspectImplementation;
private final Dictionary m_aspectProperties;
+ private final Object m_factory;
+ private final String m_factoryCreateMethod;
+ private final int m_ranking;
- public AspectImpl(Class serviceInterface, String serviceFilter, Object aspectImplementation, Dictionary properties) {
+ public AspectImpl(Class serviceInterface, String serviceFilter, int ranking, Object aspectImplementation, Dictionary properties) {
m_serviceInterface = serviceInterface;
m_serviceFilter = serviceFilter;
m_aspectImplementation = aspectImplementation;
m_aspectProperties = properties;
+ m_factory = null;
+ m_factoryCreateMethod = null;
+ m_ranking = ranking;
}
+
+ public AspectImpl(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, Dictionary properties) {
+ m_serviceInterface = serviceInterface;
+ m_serviceFilter = serviceFilter;
+ m_factory = factory;
+ m_factoryCreateMethod = factoryCreateMethod;
+ m_aspectProperties = properties;
+ m_aspectImplementation = null;
+ m_ranking = ranking;
+ }
public Service createService(Object[] properties) {
ServiceReference ref = (ServiceReference) properties[0];
Object service = properties[1];
Properties props = new Properties();
+ // first add our aspect property
+ props.put(DependencyManager.ASPECT, "true");
+ // and the ranking
+ props.put(Constants.SERVICE_RANKING, Integer.valueOf(m_ranking));
String[] keys = ref.getPropertyKeys();
for (int i = 0; i < keys.length; i++) {
props.put(keys[i], ref.getProperty(keys[i]));
@@ -57,12 +79,31 @@
}
List dependencies = m_service.getDependencies();
dependencies.remove(0);
- return m_manager.createService()
+ if (m_aspectImplementation == null) {
+ return m_manager.createService()
.setInterface(m_serviceInterface.getName(), props)
- .setImplementation(m_aspectImplementation)
+ .setFactory(m_factory, m_factoryCreateMethod)
.add(dependencies)
.add(m_manager.createServiceDependency()
- .setService(m_serviceInterface, ref)
+ .setService(m_serviceInterface, createAspectFilter(m_serviceFilter))
.setRequired(true));
+ }
+ else {
+ return m_manager.createService()
+ .setInterface(m_serviceInterface.getName(), props)
+ .setImplementation(m_aspectImplementation)
+ .add(dependencies)
+ .add(m_manager.createServiceDependency()
+ .setService(m_serviceInterface, createAspectFilter(m_serviceFilter))
+ .setRequired(true));
+ }
+ }
+ private String createAspectFilter(String filter) {
+ if (filter == null || filter.length() == 0) {
+ return "(|(!(" + Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=" + (m_ranking - 1) + "))";
+ }
+ else {
+ return "(&(|(!(" + Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=" + (m_ranking - 1) + "))" + filter + ")";
+ }
}
}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceImpl.java
index 0422fc7..51a42cd 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceImpl.java
@@ -828,6 +828,10 @@
for (int i = 0; i < instances.length; i++) {
Object serviceInstance = instances[i];
Class serviceClazz = serviceInstance.getClass();
+ if (Proxy.isProxyClass(serviceClazz)) {
+ serviceInstance = Proxy.getInvocationHandler(serviceInstance);
+ serviceClazz = serviceInstance.getClass();
+ }
while (serviceClazz != null) {
Field[] fields = serviceClazz.getDeclaredFields();
for (int j = 0; j < fields.length; j++) {
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java
index 12b6332..a97d054 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java
@@ -384,8 +384,8 @@
return lookupBundle();
}
- public Object lookupBundle() {
- Object service = null;
+ public Bundle lookupBundle() {
+ Bundle service = null;
if (m_isStarted) {
service = getBundle();
}
@@ -415,7 +415,7 @@
return service;
}
- private Object getNullObject() {
+ private Bundle getNullObject() {
if (m_nullObject == null) {
try {
m_nullObject = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { Bundle.class }, new DefaultNullObject());
@@ -424,7 +424,7 @@
m_logger.log(Logger.LOG_ERROR, "Could not create null object for Bundle.", e);
}
}
- return m_nullObject;
+ return (Bundle) m_nullObject;
}
public String getAutoConfigName() {
@@ -437,13 +437,7 @@
public void invokeAdded(DependencyService service) {
// we remember these for future reference, needed for required service callbacks
- if (m_isStarted) {
- // use the tracker
- }
- else {
- // do a manual lookup
- }
- m_bundleInstance = null; // TODO save what we looked up here
+ m_bundleInstance = lookupBundle();
invokeAdded(service, m_bundleInstance);
}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
index 9eeff70..89f68d4 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
@@ -336,7 +336,7 @@
m_tracker = new ServiceTracker(m_context, m_context.createFilter(m_trackedServiceFilter), this);
}
catch (InvalidSyntaxException e) {
- throw new IllegalStateException("Invalid filter definition for dependency.");
+ throw new IllegalStateException("Invalid filter definition for dependency: " + m_trackedServiceFilter);
}
}
else if (m_trackedServiceReference != null) {