Allow to define an Aspect Service implemented with a DynamicProxy.
Added factoryMethod attribute in all services.
Don't turn off anymore "instance bound" flag in extra (init) service dependencies.
Renamed Service factory attribute into factorySet attribute.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@957379 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java
index 3446192..87c085a 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AdapterServiceBuilder.java
@@ -43,14 +43,22 @@
public void buildService(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
throws Exception
{
- Class<?> adapterImpl = b.loadClass(srvMeta.getString(Params.impl));
+ Class<?> adapterImplClass = b.loadClass(srvMeta.getString(Params.impl));
String[] adapterService = srvMeta.getStrings(Params.adapterService, null);
Dictionary<String, Object> adapterProperties = srvMeta.getDictionary(Params.adapterProperties, null);
Class<?> adapteeService = b.loadClass(srvMeta.getString(Params.adapteeService));
String adapteeFilter = srvMeta.getString(Params.adapteeFilter, null);
Service service = dm.createAdapterService(adapteeService, adapteeFilter)
- .setInterface(adapterService, adapterProperties)
- .setImplementation(adapterImpl);
+ .setInterface(adapterService, adapterProperties);
+ String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+ if (factoryMethod == null)
+ {
+ service.setImplementation(adapterImplClass);
+ }
+ else
+ {
+ service.setFactory(adapterImplClass, factoryMethod);
+ }
service.setComposition(srvMeta.getString(Params.composition, null));
ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(service, b, dm, srvMeta, depsMeta);
// The dependencies will be plugged by our lifecycle handler.
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java
index 4130cb8..f14ca18 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AspectServiceBuilder.java
@@ -48,12 +48,21 @@
String serviceFilter = srvMeta.getString(Params.filter, null);
Dictionary<String, Object> aspectProperties = srvMeta.getDictionary(Params.properties, null);
int ranking = srvMeta.getInt(Params.ranking, 1);
- String implClass = srvMeta.getString(Params.impl);
- Object impl = b.loadClass(implClass);
- String field = srvMeta.getString(Params.field, null);
+ String implClassName = srvMeta.getString(Params.impl);
+ Object implClass = b.loadClass(implClassName);
+ String field = srvMeta.getString(Params.field, null);
+ String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
Service service = dm.createAspectService(serviceInterface, serviceFilter, ranking, field)
- .setImplementation(impl)
.setServiceProperties(aspectProperties);
+ if (factoryMethod == null)
+ {
+ service.setImplementation(implClass);
+ }
+ else
+ {
+ service.setFactory(implClass, factoryMethod);
+ }
+
service.setComposition(srvMeta.getString(Params.composition, null));
ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(service, b, dm, srvMeta, depsMeta);
// The dependencies will be plugged by our lifecycle handler.
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/BundleAdapterServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/BundleAdapterServiceBuilder.java
index 4b40ba2..6eb41ef 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/BundleAdapterServiceBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/BundleAdapterServiceBuilder.java
@@ -41,13 +41,22 @@
{
int stateMask = srvMeta.getInt(Params.stateMask, Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE);
String filter = srvMeta.getString(Params.filter, null);
- Class<?> adapterImpl = b.loadClass(srvMeta.getString(Params.impl));
+ Class<?> adapterImplClass = b.loadClass(srvMeta.getString(Params.impl));
String[] service = srvMeta.getStrings(Params.service, null);
Dictionary<String, Object> properties = srvMeta.getDictionary(Params.properties, null);
boolean propagate = "true".equals(srvMeta.getString(Params.propagate, "false"));
Service srv = dm.createBundleAdapterService(stateMask, filter, propagate)
- .setInterface(service, properties)
- .setImplementation(adapterImpl);
+ .setInterface(service, properties);
+ String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+ if (factoryMethod == null)
+ {
+ srv.setImplementation(adapterImplClass);
+ }
+ else
+ {
+ srv.setFactory(adapterImplClass, factoryMethod);
+ }
+
srv.setComposition(srvMeta.getString(Params.composition, null));
ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(srv, b, dm, srvMeta, depsMeta);
// The dependencies will be plugged by our lifecycle handler.
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/FactoryConfigurationAdapterServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/FactoryConfigurationAdapterServiceBuilder.java
index 13301eb..1f049ed 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/FactoryConfigurationAdapterServiceBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/FactoryConfigurationAdapterServiceBuilder.java
@@ -39,15 +39,23 @@
public void buildService(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
throws Exception
{
- Class<?> impl = b.loadClass(srvMeta.getString(Params.impl));
+ Class<?> implClass = b.loadClass(srvMeta.getString(Params.impl));
String factoryPid = srvMeta.getString(Params.factoryPid);
String updated = srvMeta.getString(Params.updated);
String[] services = srvMeta.getStrings(Params.service, null);
Dictionary<String, Object> properties = srvMeta.getDictionary(Params.properties, null);
boolean propagate = "true".equals(srvMeta.getString(Params.propagate, "false"));
Service srv = dm.createFactoryConfigurationAdapterService(factoryPid, updated, propagate)
- .setInterface(services, properties)
- .setImplementation(impl);
+ .setInterface(services, properties);
+ String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+ if (factoryMethod == null)
+ {
+ srv.setImplementation(implClass);
+ }
+ else
+ {
+ srv.setFactory(implClass, factoryMethod);
+ }
srv.setComposition(srvMeta.getString(Params.composition, null));
ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(srv, b, dm, srvMeta, depsMeta);
// The dependencies will be plugged by our lifecycle handler.
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/InvocationUtil.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/InvocationUtil.java
new file mode 100644
index 0000000..39d5555
--- /dev/null
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/InvocationUtil.java
@@ -0,0 +1,76 @@
+package org.apache.felix.dm.runtime;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+
+/**
+ * Class copied from DM core (but, ultimately, the core should export this class so we could then
+ * import/reuse it).
+ */
+public class InvocationUtil
+{
+ public static Object invokeCallbackMethod(Object instance, String methodName, Class[][] signatures,
+ Object[][] parameters)
+ throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
+ {
+ Class currentClazz = instance.getClass();
+ while (currentClazz != null)
+ {
+ try
+ {
+ return invokeMethod(instance, currentClazz, methodName, signatures, parameters, false);
+ }
+ catch (NoSuchMethodException nsme)
+ {
+ // ignore
+ }
+ currentClazz = currentClazz.getSuperclass();
+ }
+ throw new NoSuchMethodException(methodName);
+ }
+
+ public static Object invokeMethod(Object object, Class clazz, String name, Class[][] signatures,
+ Object[][] parameters, boolean isSuper)
+ throws NoSuchMethodException, InvocationTargetException, IllegalArgumentException, IllegalAccessException
+ {
+ if (object == null)
+ {
+ throw new IllegalArgumentException("Instance cannot be null");
+ }
+ if (clazz == null)
+ {
+ throw new IllegalArgumentException("Class cannot be null");
+ }
+
+ // If we're talking to a proxy here, dig one level deeper to expose the
+ // underlying invocation handler ...
+
+ if (Proxy.isProxyClass(clazz))
+ {
+ object = Proxy.getInvocationHandler(object);
+ clazz = object.getClass();
+ }
+
+ Method m = null;
+ for (int i = 0; i < signatures.length; i++)
+ {
+ Class[] signature = signatures[i];
+ try
+ {
+ m = clazz.getDeclaredMethod(name, signature);
+ if (!(isSuper && Modifier.isPrivate(m.getModifiers())))
+ {
+ m.setAccessible(true);
+ return m.invoke(object, parameters[i]);
+ }
+ }
+ catch (NoSuchMethodException e)
+ {
+ // ignore this and keep looking
+ }
+ }
+ throw new NoSuchMethodException(name);
+ }
+}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Params.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Params.java
index fa0ffb7..445b5d4 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Params.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Params.java
@@ -51,8 +51,9 @@
stateMask,
ranking,
factoryPid,
- factory,
+ factorySet,
factoryConfigure,
+ factoryMethod,
name,
field
}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ResourceAdapterServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ResourceAdapterServiceBuilder.java
index ede3c53..ac89efe 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ResourceAdapterServiceBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ResourceAdapterServiceBuilder.java
@@ -40,13 +40,21 @@
throws Exception
{
String filter = srvMeta.getString(Params.filter, null);
- Class<?> impl = b.loadClass(srvMeta.getString(Params.impl));
+ Class<?> implClass = b.loadClass(srvMeta.getString(Params.impl));
String[] service = srvMeta.getStrings(Params.service, null);
Dictionary<String, Object> properties = srvMeta.getDictionary(Params.properties, null);
boolean propagate = "true".equals(srvMeta.getString(Params.propagate, "false"));
Service srv = dm.createResourceAdapterService(filter, propagate)
- .setInterface(service, properties)
- .setImplementation(impl);
+ .setInterface(service, properties);
+ String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+ if (factoryMethod == null)
+ {
+ srv.setImplementation(implClass);
+ }
+ else
+ {
+ srv.setFactory(implClass, factoryMethod);
+ }
srv.setComposition(srvMeta.getString(Params.composition, null));
ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(srv, b, dm, srvMeta, depsMeta);
// The dependencies will be plugged by our lifecycle handler.
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceBuilder.java
index bd435c6..b8213e1 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceBuilder.java
@@ -44,7 +44,7 @@
throws Exception
{
Service service = dm.createService();
- String factory = srvMeta.getString(Params.factory, null);
+ String factory = srvMeta.getString(Params.factorySet, null);
// Check if we must provide a Set Factory.
if (factory == null)
@@ -57,7 +57,14 @@
String composition = srvMeta.getString(Params.composition, null);
Dictionary<String, Object> serviceProperties = srvMeta.getDictionary(Params.properties, null);
String[] provide = srvMeta.getStrings(Params.provide, null);
- service.setImplementation(b.loadClass(impl));
+ String factoryMethod = srvMeta.getString(Params.factoryMethod, null);
+ if (factoryMethod == null)
+ {
+ service.setImplementation(b.loadClass(impl));
+ } else
+ {
+ service.setFactory(b.loadClass(impl), factoryMethod);
+ }
service.setComposition(composition);
service.setInterface(provide, serviceProperties);
// Adds dependencies (except named dependencies, which are managed by the lifecycle handler).
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceFactory.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceFactory.java
index 98dd03d..f1697e1 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceFactory.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceFactory.java
@@ -100,7 +100,7 @@
* The bundle containing the Service annotated with the factory attribute.
*/
private Bundle m_bundle;
-
+
/**
* Flag used to check if a service is being created
*/
@@ -154,7 +154,7 @@
*/
public ServiceFactory(Bundle b, MetaData srvMeta, List<MetaData> depsMeta)
{
- m_serviceProperties = srvMeta.getDictionary(Params.properties, null);;
+ m_serviceProperties = srvMeta.getDictionary(Params.properties, null);
m_provide = srvMeta.getStrings(Params.provide, null);
m_configure = srvMeta.getString(Params.factoryConfigure, null);
m_bundle = b;
@@ -343,7 +343,17 @@
// Create the Service / impl
Service s = m_dm.createService();
Class implClass = m_bundle.loadClass(m_srvMeta.getString(Params.impl));
- m_impl = implClass.newInstance();
+ String factoryMethod = m_srvMeta.getString(Params.factoryMethod, null);
+ if (factoryMethod == null)
+ {
+ m_impl = implClass.newInstance();
+ }
+ else
+ {
+ Method m = implClass.getDeclaredMethod(factoryMethod);
+ m.setAccessible(true);
+ m_impl = m.invoke(null);
+ }
// Invoke "configure" callback
if (m_configure != null)
@@ -359,26 +369,29 @@
Dictionary serviceProperties = mergeSettings(m_serviceProperties, configuration);
s.setInterface(m_provide, serviceProperties);
}
-
+
s.setComposition(m_srvMeta.getString(Params.composition, null));
- ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(s, m_bundle, m_dm, m_srvMeta, m_depsMeta);
+ ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(s, m_bundle, m_dm,
+ m_srvMeta, m_depsMeta);
// The dependencies will be plugged by our lifecycle handler.
s.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
// Adds dependencies (except named dependencies, which are managed by the lifecycle handler).
- for (MetaData dependency : m_depsMeta)
+ for (MetaData dependency: m_depsMeta)
{
String name = dependency.getString(Params.name, null);
- if (name == null) {
+ if (name == null)
+ {
DependencyBuilder depBuilder = new DependencyBuilder(dependency);
- Log.instance().log(LogService.LOG_INFO,
+ Log.instance().log(
+ LogService.LOG_INFO,
"ServiceLifecycleHandler.init: adding dependency %s into service %s",
dependency, m_srvMeta);
Dependency d = depBuilder.build(m_bundle, m_dm, false);
s.add(d);
}
}
-
+
// Register the Service instance, and keep track of it.
Log.instance().log(LogService.LOG_INFO, "ServiceFactory: created service %s", m_srvMeta);
m_dm.add(s);
@@ -388,7 +401,8 @@
{
// Make sure the SERVICE_CREATING flag is also removed
m_services.remove(serviceKey);
- Log.instance().log(LogService.LOG_ERROR, "ServiceFactory: could not instantiate service %s", t, m_srvMeta);
+ Log.instance().log(LogService.LOG_ERROR, "ServiceFactory: could not instantiate service %s",
+ t, m_srvMeta);
}
}
else
@@ -424,7 +438,7 @@
{
try
{
- for (Object service : m_services.values())
+ for (Object service: m_services.values())
{
if (service instanceof Service)
{
@@ -458,7 +472,7 @@
Object key = keys.nextElement();
Object val = serviceProperties.get(key);
props.put(key, val);
- }
+ }
}
Enumeration keys = factoryConfiguration.keys();
@@ -478,16 +492,16 @@
/**
* Invokes the configure callback method on the service instance implemenatation.
* @param impl
- * @param factoryConfige
+ * @param configure
* @param config
*/
- private void invokeConfigure(Object impl, String factoryConfige, Dictionary config)
+ private void invokeConfigure(Object impl, String configure, Dictionary config)
{
try
{
- Method m = impl.getClass().getMethod(factoryConfige, Dictionary.class);
- m.setAccessible(true);
- m.invoke(impl, new Object[] { config });
+ InvocationUtil.invokeCallbackMethod(impl, configure,
+ new Class[][] { { Dictionary.class } },
+ new Object[][] { { config } });
}
catch (Throwable t)
@@ -498,8 +512,8 @@
}
else
{
- throw new RuntimeException("Could not invoke method " + factoryConfige
- + " on object " + impl);
+ throw new RuntimeException("Could not invoke method " + configure
+ + " on object " + impl);
}
}
}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceLifecycleHandler.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceLifecycleHandler.java
index 89c1a33..9afc47f 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceLifecycleHandler.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ServiceLifecycleHandler.java
@@ -164,28 +164,6 @@
public void start(Object serviceInstance, DependencyManager dm, Service service)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
- // Remove "instance bound" flag from all dependencies, because we want to be deactivated
- // once we lose one of the deps ...
- Iterator it = m_namedDeps.iterator();
- while (it.hasNext())
- {
- Dependency d = (Dependency) it.next();
- if (d instanceof ServiceDependency) {
- ((ServiceDependency)d).setInstanceBound(false);
- } else if (d instanceof BundleDependency)
- {
- ((BundleDependency)d).setInstanceBound(false);
- } else if (d instanceof ResourceDependency)
- {
- ((ResourceDependency) d).setInstanceBound(false);
- } else if (d instanceof ConfigurationDependency)
- {
- ((ConfigurationDependency) d).setInstanceBound(false);
- } else if (d instanceof TemporalServiceDependency)
- {
- ((TemporalServiceDependency) d).setInstanceBound(false);
- }
- }
invokeMethod(serviceInstance, m_start, dm, service);
}
@@ -228,29 +206,16 @@
// The annotated class did not provide an annotation for this lifecycle callback.
return null;
}
-
- Class clazz = instance.getClass();
-
- while (clazz != null)
+
+ try
{
- for (int i = 0; i < signatures.length; i++)
- {
- Class<?>[] signature = signatures[i];
- try
- {
- // Don't use getMethod because getMethod only look for public methods !
- Method m = instance.getClass().getDeclaredMethod(method, signature);
- m.setAccessible(true);
- return m.invoke(instance, params[i]);
- }
- catch (NoSuchMethodException e)
- {
- // ignore this and keep looking
- }
- }
- clazz = clazz.getSuperclass();
+ return InvocationUtil.invokeCallbackMethod(instance, method, signatures, params);
+ }
+
+ catch (NoSuchMethodException e)
+ {
+ // ignore this
+ return null;
}
-
- return null;
}
}