Added the ability to dynamically configure service dependency "required" and "filter" attributes from the Service's init method
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@953578 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 1d81cad..da38818 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
@@ -22,7 +22,6 @@
import java.util.List;
import org.apache.felix.dm.DependencyManager;
-import org.apache.felix.dm.dependencies.Dependency;
import org.apache.felix.dm.service.Service;
import org.osgi.framework.Bundle;
@@ -41,24 +40,21 @@
}
@Override
- public void buildService(MetaData serviceMetaData,
- List<MetaData> serviceDependencies,
- Bundle b, DependencyManager dm) throws Exception
+ public void buildService(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
+ throws Exception
{
- Class<?> adapterImpl = b.loadClass(serviceMetaData.getString(Params.impl));
- String[] adapterService = serviceMetaData.getStrings(Params.adapterService, null);
- Dictionary<String, Object> adapterProperties = serviceMetaData.getDictionary(Params.adapterProperties, null);
- Class<?> adapteeService = b.loadClass(serviceMetaData.getString(Params.adapteeService));
- String adapteeFilter = serviceMetaData.getString(Params.adapteeFilter, null);
+ Class<?> adapterImpl = 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);
- setCommonServiceParams(service, serviceMetaData);
- for (MetaData dependencyMetaData: serviceDependencies)
- {
- Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
- service.add(dp);
- }
+ 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.
+ service.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
dm.add(service);
}
}
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 fd316f1..8fbde27 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
@@ -22,7 +22,6 @@
import java.util.List;
import org.apache.felix.dm.DependencyManager;
-import org.apache.felix.dm.dependencies.Dependency;
import org.apache.felix.dm.service.Service;
import org.osgi.framework.Bundle;
import org.osgi.service.log.LogService;
@@ -38,29 +37,27 @@
}
@Override
- public void buildService(MetaData serviceMetaData,
- List<MetaData> serviceDependencies,
- Bundle b, DependencyManager dm) throws Exception
+ public void buildService(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
+ throws Exception
{
- Log.instance().log(LogService.LOG_DEBUG, "building aspect service: service metadata=" + serviceMetaData
- + ", dependencyMetaData=" + serviceDependencies);
+ Log.instance().log(LogService.LOG_INFO,
+ "AspectServiceBuilder: building aspect service: %s with dependencies %s",
+ srvMeta, depsMeta);
- Class<?> serviceInterface = b.loadClass(serviceMetaData.getString(Params.service));
- String serviceFilter = serviceMetaData.getString(Params.filter, null);
- Dictionary<String, Object> aspectProperties = serviceMetaData.getDictionary(Params.properties, null);
- int ranking = serviceMetaData.getInt(Params.ranking, 1);
- String implClass = serviceMetaData.getString(Params.impl);
+ Class<?> serviceInterface = b.loadClass(srvMeta.getString(Params.service));
+ 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 = serviceMetaData.getString(Params.field, null);
+ String field = srvMeta.getString(Params.field, null);
Service service = dm.createAspectService(serviceInterface, serviceFilter, ranking, field)
.setImplementation(impl)
.setServiceProperties(aspectProperties);
- setCommonServiceParams(service, serviceMetaData);
- for (MetaData dependencyMetaData: serviceDependencies)
- {
- Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
- service.add(dp);
- }
+ 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.
+ service.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
dm.add(service);
}
}
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 249c65b..8d82336 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
@@ -37,25 +37,22 @@
}
@Override
- public void buildService(MetaData serviceMetaData,
- List<MetaData> serviceDependencies,
- Bundle b, DependencyManager dm) throws Exception
+ public void buildService(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
+ throws Exception
{
- int stateMask = serviceMetaData.getInt(Params.stateMask, Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE);
- String filter = serviceMetaData.getString(Params.filter, null);
- Class<?> adapterImpl = b.loadClass(serviceMetaData.getString(Params.impl));
- String[] service = serviceMetaData.getStrings(Params.service, null);
- Dictionary<String, Object> properties = serviceMetaData.getDictionary(Params.properties, null);
- boolean propagate = "true".equals(serviceMetaData.getString(Params.propagate, "false"));
+ 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));
+ 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);
- setCommonServiceParams(srv, serviceMetaData);
- for (MetaData dependencyMetaData: serviceDependencies)
- {
- Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
- srv.add(dp);
- }
+ .setInterface(service, properties)
+ .setImplementation(adapterImpl);
+ 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.
+ srv.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
dm.add(srv);
}
}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
index 1b206c3..3fdaa71 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
@@ -86,6 +86,9 @@
case ResourceDependency:
dp = createResourceDependency(dm, instanceBound);
break;
+
+ default:
+ throw new IllegalArgumentException("Can't build service dependency: " + type);
}
return dp;
}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyManagerRuntime.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyManagerRuntime.java
index 92b4b62..7887ae9 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyManagerRuntime.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyManagerRuntime.java
@@ -84,15 +84,13 @@
@SuppressWarnings("unchecked")
protected void stop()
{
- m_log.log(LogService.LOG_INFO, "DependencyManager Runtime stopping: removing services");
+ m_log.log(LogService.LOG_INFO, "Runtime: stopping services");
for (DependencyManager dm: m_managers.values())
{
List<Service> services = new ArrayList<Service>(dm.getServices());
for (Service service: services)
{
- m_log.log(LogService.LOG_INFO, "DependencyManager Runtime stopping: removing service: "
- + service);
dm.remove(service);
}
}
@@ -142,7 +140,7 @@
URL descriptorURL = b.getEntry(descriptorPath);
if (descriptorURL == null)
{
- m_log.log(LogService.LOG_ERROR,
+ m_log.log(LogService.LOG_ERROR, "Runtime: " +
"DependencyManager component descriptor not found: " + descriptorPath);
continue;
}
@@ -157,16 +155,16 @@
@SuppressWarnings("unchecked")
private void bundleStopping(Bundle b)
{
- m_log.log(LogService.LOG_INFO, "Removing services from stopping bundle: " + b.getSymbolicName());
+ m_log.log(LogService.LOG_INFO, "Runtime: Removing services from stopping bundle: " + b.getSymbolicName());
DependencyManager dm = m_managers.remove(b);
if (dm != null)
{
List<Service> services = new ArrayList(dm.getServices());
- for (Service service: services)
+ for (Service service : services)
{
- m_log.log(LogService.LOG_INFO, "Removing service service: " + service);
+ m_log.log(LogService.LOG_INFO, "Runtime: Removing service: " + service);
dm.remove(service);
- }
+ }
}
}
@@ -177,7 +175,7 @@
*/
private void loadDescriptor(Bundle b, URL descriptorURL)
{
- m_log.log(LogService.LOG_DEBUG, "Parsing descriptor " + descriptorURL
+ m_log.log(LogService.LOG_DEBUG, "Runtime: ++++ Parsing descriptor " + descriptorURL
+ " from bundle " + b.getSymbolicName());
BufferedReader in = null;
@@ -197,7 +195,7 @@
catch (Throwable t)
{
- m_log.log(LogService.LOG_ERROR, "Error while parsing descriptor "
+ m_log.log(LogService.LOG_ERROR, "Runtime: Error while parsing descriptor "
+ descriptorURL + " from bundle " + b.getSymbolicName(), t);
}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParser.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParser.java
index 81728f8..0da39e5 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParser.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParser.java
@@ -31,7 +31,8 @@
/**
* This class parses files generated in OSGI-INF/*.dm by the DependencyManager bnd plugin.
- * Each descriptor contains a JSON definition of a Service, along with its corresponding service dependency or configuration dependencies.
+ * Each descriptor contains a JSON definition of a Service, along with its corresponding
+ * dependencies.
*/
public class DescriptorParser
{
@@ -48,7 +49,7 @@
// The first line is a Service Component (a Service, an Aspect Service, etc ...)
line = reader.readLine();
- Log.instance().log(LogService.LOG_DEBUG, "Parsing destriptor entry line: " + line);
+ Log.instance().log(LogService.LOG_DEBUG, "DescriptorParser: parsing service %s", line);
JSONObject json = new JSONObject(line);
JSONMetaData serviceMetaData = new JSONMetaData(json);
@@ -64,7 +65,7 @@
List<MetaData> serviceDependencies = new ArrayList<MetaData>();
while ((line = reader.readLine()) != null)
{
- Log.instance().log(LogService.LOG_DEBUG, "Parsing destriptor entry line: " + line);
+ Log.instance().log(LogService.LOG_DEBUG, "Parsing dependency Ms", line);
JSONObject dep = new JSONObject(line);
serviceDependencies.add(new JSONMetaData(dep));
}
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 b499dec..6994ffc 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
@@ -37,25 +37,22 @@
}
@Override
- public void buildService(MetaData serviceMetaData,
- List<MetaData> serviceDependencies,
- Bundle b, DependencyManager dm) throws Exception
+ public void buildService(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
+ throws Exception
{
- Class<?> impl = b.loadClass(serviceMetaData.getString(Params.impl));
- String factoryPid = serviceMetaData.getString(Params.factoryPid);
- String updated = serviceMetaData.getString(Params.updated);
- String[] services = serviceMetaData.getStrings(Params.service, null);
- Dictionary<String, Object> properties = serviceMetaData.getDictionary(Params.properties, null);
- boolean propagate = "true".equals(serviceMetaData.getString(Params.propagate, "false"));
+ Class<?> impl = 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);
- setCommonServiceParams(srv, serviceMetaData);
- for (MetaData dependencyMetaData: serviceDependencies)
- {
- Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
- srv.add(dp);
- }
+ 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.
+ srv.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
dm.add(srv);
}
}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Log.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Log.java
index 9739e1a..68999c5 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Log.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/Log.java
@@ -18,10 +18,12 @@
*/
package org.apache.felix.dm.runtime;
-import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
-public class Log implements LogService
+/**
+ * This class logs some formattable strings into the OSGi Log Service.
+ */
+public class Log
{
/** The log service */
private LogService m_logService;
@@ -37,24 +39,14 @@
public void setLogService(LogService logService) {
m_logService = logService;
}
+
+ public void log(int level, String format, Object ... args)
+ {
+ m_logService.log(level, String.format(format, args));
+ }
- public void log(int level, String message, Throwable exception)
+ public void log(int level, String format, Throwable t, Object ... args)
{
- m_logService.log(level, message, exception);
- }
-
- public void log(int level, String message)
- {
- m_logService.log(level, message);
- }
-
- public void log(ServiceReference sr, int level, String message, Throwable exception)
- {
- m_logService.log(sr, level, message, exception);
- }
-
- public void log(ServiceReference sr, int level, String message)
- {
- m_logService.log(sr, level, message);
+ m_logService.log(level, String.format(format, args), t);
}
}
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java
index 166a006..e87220d 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/MetaData.java
@@ -84,4 +84,9 @@
* Modifies a String[] value.
*/
void setDictionary(Params key, Dictionary<String, Object> dictionary);
+
+ /**
+ * Clone this MetaData object.
+ */
+ Object clone() throws CloneNotSupportedException;
}
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 f281b1e..6ae100a 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
@@ -37,24 +37,21 @@
}
@Override
- public void buildService(MetaData serviceMetaData,
- List<MetaData> serviceDependencies,
- Bundle b, DependencyManager dm) throws Exception
+ public void buildService(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
+ throws Exception
{
- String filter = serviceMetaData.getString(Params.filter, null);
- Class<?> impl = b.loadClass(serviceMetaData.getString(Params.impl));
- String[] service = serviceMetaData.getStrings(Params.service, null);
- Dictionary<String, Object> properties = serviceMetaData.getDictionary(Params.properties, null);
- boolean propagate = "true".equals(serviceMetaData.getString(Params.propagate, "false"));
+ String filter = srvMeta.getString(Params.filter, null);
+ Class<?> impl = 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);
- setCommonServiceParams(srv, serviceMetaData);
- for (MetaData dependencyMetaData: serviceDependencies)
- {
- Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
- srv.add(dp);
- }
+ 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.
+ srv.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
dm.add(srv);
}
}
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 86d0039..a6d5245 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
@@ -32,6 +32,7 @@
public class ServiceBuilder extends ServiceComponentBuilder
{
private final static String TYPE = "Service";
+ private final static String DM_FACTORY_NAME = "dm.factory.name";
@Override
public String getType()
@@ -40,72 +41,44 @@
}
@Override
- public void buildService(MetaData srvMeta, List<MetaData> srvDeps, Bundle b, DependencyManager dm)
+ public void buildService(MetaData srvMeta, List<MetaData> depsMeta, Bundle b, DependencyManager dm)
throws Exception
{
- Log.instance().log(LogService.LOG_DEBUG, "building service: service metadata=" + srvMeta
- + ", dependencyMetaData=" + srvDeps);
-
- // Get service parameters (lifecycle callbacks, composition, factory, etc ...)
-
Service service = dm.createService();
String factory = srvMeta.getString(Params.factory, null);
- String factoryConfigure = srvMeta.getString(Params.factoryConfigure, null);
- String impl = srvMeta.getString(Params.impl);
- String init = srvMeta.getString(Params.init, null);
- String start = srvMeta.getString(Params.start, null);
- String stop = srvMeta.getString(Params.stop, null);
- String destroy = srvMeta.getString(Params.destroy, null);
- String composition = srvMeta.getString(Params.composition, null);
- Dictionary<String, Object> serviceProperties = srvMeta.getDictionary(Params.properties, null);
- String[] provide = srvMeta.getStrings(Params.provide, null);
// Check if we must provide a Set Factory.
if (factory == null)
{
- // No: instantiate the service.
- service.setImplementation(b.loadClass(impl));
- if (composition != null)
- {
- service.setComposition(composition);
- }
- if (provide != null)
- {
- service.setInterface(provide, serviceProperties);
- }
+ Log.instance().log(LogService.LOG_INFO,
+ "ServiceBuilder: building service %s with dependencies %s",
+ srvMeta, depsMeta);
+ String impl = srvMeta.getString(Params.impl);
+ 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));
+ service.setComposition(composition);
+ service.setInterface(provide, serviceProperties);
// Creates a ServiceHandler, which will filter all service lifecycle callbacks.
- /*
- ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(service, b, dm, srvMeta,
- srvDeps);
+ ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(service, b, dm, srvMeta, depsMeta);
service.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
- String confDependency = DependencyBuilder.DependencyType.ConfigurationDependency.toString();
- */
- // TODO REMOVE
- for (MetaData depMeta: srvDeps)
- {
- Dependency dp = new DependencyBuilder(depMeta).build(b, dm);
- service.add(dp);
- }
}
else
{
+ Log.instance().log(LogService.LOG_INFO,
+ "ServiceBuilder: providing factory set for service %s with dependencies %s",
+ srvMeta, depsMeta);
+
// We don't instantiate the service, but instead we provide a Set in the registry.
// This Set will act as a factory and another component may registers some
// service configurations into it in order to fire some service instantiations.
-
- ServiceFactory serviceFactory = new ServiceFactory(b.loadClass(impl), init, start, stop, destroy,
- composition, serviceProperties, provide,
- factoryConfigure);
- for (MetaData dependencyMetaData: srvDeps)
- {
- Dependency dp = new DependencyBuilder(dependencyMetaData).build(b, dm);
- serviceFactory.addDependency(dp);
- }
+ ServiceFactory serviceFactory = new ServiceFactory(b, srvMeta, depsMeta);
service.setImplementation(serviceFactory);
service.setCallbacks(null, "start", "stop", null);
Hashtable<String, String> props = new Hashtable<String, String>();
- props.put("dm.factory.name", factory);
+ props.put(DM_FACTORY_NAME, factory);
service.setInterface(Set.class.getName(), props);
}
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 b37c5c7..fdfa731 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
@@ -20,8 +20,6 @@
import java.lang.reflect.Method;
import java.util.AbstractSet;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
@@ -30,8 +28,9 @@
import java.util.concurrent.ConcurrentHashMap;
import org.apache.felix.dm.DependencyManager;
-import org.apache.felix.dm.dependencies.Dependency;
import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.service.log.LogService;
/**
* This class implements a <code>java.util.Set</code> which acts as a service factory.
@@ -50,41 +49,11 @@
private Object m_impl;
/**
- * The Service class used to instantiate Service instances
- */
- private final Class<?> m_implClass;
-
- /**
- * The Service init lifecycle callback.
- */
- private final String m_init;
-
- /**
- * The Service start lifecycle callback.
- */
- private final String m_start;
-
- /**
- * The Service stop lifecycle callback.
- */
- private final String m_stop;
-
- /**
- * The Service destroy lifecycle callback.
- */
- private final String m_destroy;
-
- /**
- * The getComposition Service callback.
- */
- private final String m_composition;
-
- /**
* The Service provided in the OSGi registry.
*/
private final String[] m_provide;
- /**factoryConfigure
+ /**
* The properties to be provided by the Service.
*/
private final Dictionary m_serviceProperties;
@@ -102,7 +71,12 @@
/**
* The list of Dependencies which are applied in the Service.
*/
- private final ArrayList<Dependency> m_dependencies = new ArrayList<Dependency>();
+ private MetaData m_srvMeta;
+
+ /**
+ * The list of Dependencies which are applied in the Service.
+ */
+ private List<MetaData> m_depsMeta;
/**
* The DependencyManager (injected by reflection), which is used to create Service instances.
@@ -122,6 +96,11 @@
private volatile boolean m_active;
/**
+ * The bundle containing the Service annotated with the factory attribute.
+ */
+ private Bundle m_bundle;
+
+ /**
* Flag used to check if a service is being created
*/
private final static Object SERVICE_CREATING = new Object();
@@ -166,37 +145,20 @@
/**
* Sole constructor.
- * @param impl The Service impl class
- * @param init The init lifecyle callback
- * @param start The start lifecyle callback
- * @param stop The stop lifecyle callback
- * @param destroy The destroy lifecyle callback
- * @param composition The getComposition Service method.
+ * @param b the bundle containing the Service annotated with the factory attribute
+ * @param impl The Service implementation class
* @param serviceProperties The Service properties
* @param provide The Services provided by this Service
* @param factoryConfigure The configure callback invoked in order to pass configurations added in this Set.
*/
- public ServiceFactory(Class<?> impl, String init, String start, String stop, String destroy, String composition, Dictionary serviceProperties, String[] provide, String factoryConfigure)
+ public ServiceFactory(Bundle b, MetaData srvMeta, List<MetaData> depsMeta)
{
- m_implClass = impl;
- m_init = init;
- m_start = start;
- m_stop = stop;
- m_destroy = destroy;
- m_composition = composition;
- m_serviceProperties = serviceProperties;
- m_provide = Arrays.copyOf(provide, provide.length);
- m_configure = factoryConfigure;
- }
-
- /**
- * Method called in order to track all Dependencies added in our Service.
- * The ComponentManager will forward all Service Dependencies in this method and we'll attach them
- * to all concrete Service instances (when we will create them).
- */
- public void addDependency(Dependency dp)
- {
- m_dependencies.add(dp);
+ m_serviceProperties = srvMeta.getDictionary(Params.properties, null);;
+ m_provide = srvMeta.getStrings(Params.provide, null);
+ m_configure = srvMeta.getString(Params.factoryConfigure, null);
+ m_bundle = b;
+ m_srvMeta = srvMeta;
+ m_depsMeta = depsMeta;
}
/**
@@ -379,7 +341,8 @@
{
// Create the Service / impl
Service s = m_dm.createService();
- m_impl = createServiceImpl();
+ Class implClass = m_bundle.loadClass(m_srvMeta.getString(Params.impl));
+ m_impl = implClass.newInstance();
// Invoke "configure" callback
if (m_configure != null)
@@ -389,30 +352,28 @@
// Create Service
s.setImplementation(m_impl);
- s.setCallbacks(m_init, m_start, m_stop, m_destroy);
- if (m_composition != null)
- {
- s.setComposition(m_composition);
- }
if (m_provide != null)
{
// Merge service properties with the configuration provided by the factory.
Dictionary serviceProperties = mergeSettings(m_serviceProperties, configuration);
s.setInterface(m_provide, serviceProperties);
}
-
- // Plug original dependencies
- s.add((List<Dependency>) m_dependencies.clone());
+
+ s.setComposition(m_srvMeta.getString(Params.composition, null));
+ 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");
// 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);
m_services.put(serviceKey, s);
}
- catch (RuntimeException e)
+ catch (Throwable t)
{
// Make sure the SERVICE_CREATING flag is also removed
m_services.remove(serviceKey);
- throw e;
+ Log.instance().log(LogService.LOG_ERROR, "ServiceFactory: could not instantiate service %s", t, m_srvMeta);
}
}
else
@@ -420,6 +381,7 @@
// Reconfigure an already existing Service.
if (m_configure != null)
{
+ Log.instance().log(LogService.LOG_INFO, "ServiceFactory: updating service %s", m_impl);
invokeConfigure(m_impl, m_configure, configuration);
}
@@ -434,6 +396,7 @@
private void doRemove(Dictionary configuraton)
{
+ Log.instance().log(LogService.LOG_INFO, "ServiceFactory: removing service %s", m_srvMeta);
ServiceKey serviceKey = new ServiceKey(configuraton);
Object service = m_services.remove(serviceKey);
if (service != null && service != SERVICE_CREATING)
@@ -480,7 +443,7 @@
Object key = keys.nextElement();
Object val = serviceProperties.get(key);
props.put(key, val);
- }
+ }
}
Enumeration keys = factoryConfiguration.keys();
@@ -498,30 +461,6 @@
}
/**
- * Create a Service impl instance
- */
- private Object createServiceImpl()
- {
- try
- {
- m_impl = m_implClass.newInstance();
- return m_impl;
- }
- catch (Throwable t)
- {
- if (t instanceof RuntimeException)
- {
- throw (RuntimeException) t;
- }
- else
- {
- throw new RuntimeException("Could not create Service instance for class "
- + m_implClass, t);
- }
- }
- }
-
- /**
* Invokes the configure callback method on the service instance implemenatation.
* @param impl
* @param factoryConfige
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 e8cc435..7f79a26 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
@@ -21,20 +21,68 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.dependencies.BundleDependency;
+import org.apache.felix.dm.dependencies.ConfigurationDependency;
import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.dependencies.ResourceDependency;
+import org.apache.felix.dm.dependencies.ServiceDependency;
+import org.apache.felix.dm.dependencies.TemporalServiceDependency;
import org.apache.felix.dm.service.Service;
import org.osgi.framework.Bundle;
+import org.osgi.service.log.LogService;
/**
- * This class acts as a service implementation lifecycle handler. If the actual service implementation
- * init method returns a Map, then this map will is inspected for dependency filters, which will be
- * applied to the dependencies specified in the service.
+ * Allow Services to configure dynamically their dependency filters from their init() method.
+ * Basically, this class acts as a service implementation lifecycle handler. When we detect that the Service is
+ * called in its init() method, and if its init() method returns a Map, then the Map is assumed to contain
+ * dependency filters, which will be applied to all service dependencies. The Map optionally returned by
+ * Service's init method has to contains the following keys:
+ * <ul>
+ * <li>name.filter: the value must be a valid OSGi filter. the "name" prefix must match a ServiceDependency
+ * name attribute</li>
+ * <li>name.required: the value is a boolean ("true"|"false") and must the "name" prefix must match a
+ * ServiceDependency name attribute</li>
+ * </ul>
+ *
+ * Example of a Service whose dependency filter is configured from ConfigAdmin:
+ *
+ * <blockquote>
+ *
+ * <pre>
+ * /**
+ * * All Service whose service dependency filter/require attribute may be configured from ConfigAdmin
+ * */
+ * @Service
+ * class X {
+ * private Dictionary m_config;
+ *
+ * @ConfigurationDependency(pid="MyPid")
+ * void configure(Dictionary conf) {
+ * // Initialize our service from config ...
+ *
+ * // And store the config for late usage (from our init method)
+ * m_config = config;
+ * }
+ *
+ * @Init
+ * Map init() {
+ * return new HashMap() {{
+ * put("dependency1.filter", m_config.get("filter"));
+ * put("dependency1.required", m_config.get("required"));
+ * }};
+ * }
+ *
+ * @ServiceDependency(name="dependency1")
+ * void bindOtherService(OtherService other) {
+ * // the filter and required flag will be configured from our init method.
+ * }
+ * }
*/
public class ServiceLifecycleHandler
{
@@ -42,86 +90,115 @@
private String m_start;
private String m_stop;
private String m_destroy;
- private List<MetaData> m_dependencies = new ArrayList<MetaData>();
- private Map<String, MetaData> m_namedDependencies = new HashMap<String, MetaData>();
+ private MetaData m_srvMeta;
+ private List<MetaData> m_depsMeta;
+ private List<Dependency> m_deps = new ArrayList<Dependency>();
private Bundle m_bundle;
public ServiceLifecycleHandler(Service srv, Bundle srvBundle, DependencyManager dm,
- MetaData srvMetaData, List<MetaData> srvDep)
+ MetaData srvMeta, List<MetaData> depMeta)
throws Exception
{
- m_init = srvMetaData.getString(Params.init, null);
- m_start = srvMetaData.getString(Params.start, null);
- m_stop = srvMetaData.getString(Params.stop, null);
- m_destroy = srvMetaData.getString(Params.destroy, null);
+ m_srvMeta = srvMeta;
+ m_init = srvMeta.getString(Params.init, null);
+ m_start = srvMeta.getString(Params.start, null);
+ m_stop = srvMeta.getString(Params.stop, null);
+ m_destroy = srvMeta.getString(Params.destroy, null);
m_bundle = srvBundle;
+ // Plug configuration dependencies now, and remove them from the dependency list.
+ // (we want these dependencies to be injected before the init method).
+
String confDependency = DependencyBuilder.DependencyType.ConfigurationDependency.toString();
- for (MetaData depMeta: srvDep)
+ Iterator<MetaData> dependencies = depMeta.iterator();
+ while (dependencies.hasNext())
{
- if (depMeta.getString(Params.type).equals(confDependency))
+ MetaData dependency = dependencies.next();
+ if (dependency.getString(Params.type).equals(confDependency))
{
- // Register Configuration dependencies now
- Dependency dp = new DependencyBuilder(depMeta).build(m_bundle, dm);
+ // Register Configuration dependency now.
+ Dependency dp = new DependencyBuilder(dependency).build(m_bundle, dm);
srv.add(dp);
- }
- else
- {
- String name = depMeta.getString(Params.name, null);
- if (name != null)
- {
- m_namedDependencies.put(name, depMeta);
- }
- else
- {
- m_dependencies.add(depMeta);
- }
+ dependencies.remove();
}
}
-
+
+ m_depsMeta = depMeta;
}
@SuppressWarnings("unchecked")
public void init(Object serviceInstance, DependencyManager dm, Service service)
throws Exception
{
- // Invoke the service instance actual init method.
- Object o = invokeMethod(serviceInstance, m_init, dm, service);
-
- // If the init method returned a Map, then apply all filters found from it into
- // the service dependencies. Keys = Dependency name / values = Dependency filter
- if (o != null && Map.class.isAssignableFrom(o.getClass()))
+ // Invoke the service instance init method, and check if it returns a dependency
+ // customization map. This map will be used to configure some dependency filters
+ // (or required flag).
+ Object o = invokeMethod(serviceInstance, m_init, dm, service);
+ Map<String, String> customization = (o != null && Map.class.isAssignableFrom(o.getClass())) ?
+ (Map<String, String>) o : new HashMap<String, String>();
+
+ Log.instance().log(LogService.LOG_DEBUG,
+ "ServiceLifecycleHandler.init: invoked init method from service %s " +
+ ", returned map: %s", serviceInstance, customization);
+
+ for (MetaData dependency : m_depsMeta)
{
- Map<String, String> filters = (Map<String, String>) o;
- for (Map.Entry<String, String> entry: filters.entrySet())
+ // Check if this dependency has a name, and if we find the name from the
+ // customization map, then apply filters and required flag from the map into it.
+
+ String name = dependency.getString(Params.name, null);
+ if (name != null)
{
- String name = entry.getKey();
- String filter = entry.getValue();
-
- MetaData dependency = m_namedDependencies.remove(name);
- if (dependency != null)
- {
- dependency.setString(Params.filter, filter);
- DependencyBuilder depBuilder = new DependencyBuilder(dependency);
- Dependency d = depBuilder.build(m_bundle, dm, true);
- service.add(d);
- }
- else
- {
- throw new IllegalArgumentException("Invalid filter Map: the filter key " + name
- + " does not correspond " +
- " to a known Dependency.");
+ String filter = customization.get(name + ".filter");
+ String required = customization.get(name + ".required");
+
+ if (filter != null || required != null) {
+ dependency = (MetaData) dependency.clone();
+ if (filter != null)
+ {
+ dependency.setString(Params.filter, filter);
+ }
+ if (required != null)
+ {
+ dependency.setString(Params.required, required);
+ }
}
}
+ DependencyBuilder depBuilder = new DependencyBuilder(dependency);
+ Log.instance().log(LogService.LOG_INFO,
+ "ServiceLifecycleHandler.init: adding dependency %s into service %s",
+ dependency, m_srvMeta);
+ Dependency d = depBuilder.build(m_bundle, dm, true);
+ m_deps.add(d);
+ service.add(d);
}
-
- plugDependencies(m_namedDependencies.values(), dm, service);
- plugDependencies(m_dependencies, dm, service);
}
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_deps.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);
}
@@ -141,18 +218,18 @@
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
return invokeMethod(serviceInstance,
- method,
- new Class[][] {
- { Object.class, DependencyManager.class, Service.class },
- { DependencyManager.class, Service.class },
- { Object.class },
- {}
+ method,
+ new Class[][] {
+ { Object.class, DependencyManager.class, Service.class },
+ { DependencyManager.class, Service.class },
+ { Object.class },
+ {}
},
- new Object[][] {
- { serviceInstance, dm, service },
- { dm, service },
- { serviceInstance },
- {}
+ new Object[][] {
+ { serviceInstance, dm, service },
+ { dm, service },
+ { serviceInstance },
+ {}
});
}
@@ -189,15 +266,4 @@
return null;
}
-
- private void plugDependencies(Collection<MetaData> dependencies, DependencyManager dm, Service service)
- throws Exception
- {
- for (MetaData dependency: dependencies)
- {
- DependencyBuilder depBuilder = new DependencyBuilder(dependency);
- Dependency d = depBuilder.build(m_bundle, dm, true);
- service.add(d);
- }
- }
}