use of org.apache.felix.dm.DependencyManager in project felix by apache.
the class DependencyManagerRuntime method loadDescriptor.
/**
* Load a DependencyManager component descriptor from a given bundle.
* @param b
* @param descriptorURL
*/
private void loadDescriptor(Bundle b, URL descriptorURL) {
Log.instance().debug("Parsing descriptor %s from bundle %s", descriptorURL, b.getSymbolicName());
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(descriptorURL.openStream()));
DependencyManager dm = m_managers.get(b);
if (dm == null) {
dm = new DependencyManager(b.getBundleContext());
m_managers.put(b, dm);
}
m_parser.parse(in, b, dm);
} catch (Throwable t) {
Log.instance().error("Runtime: Error while parsing descriptor %s from bundle %s", t, descriptorURL, b.getSymbolicName());
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ignored) {
}
}
}
}
use of org.apache.felix.dm.DependencyManager in project felix by apache.
the class ServiceLifecycleHandler method start.
/**
* Handles the Service's start lifecycle callback. We just invoke the service "start" service callback on
* the service instance, as well as on all eventual service composites.
* We take care to check if a start callback returns a Map, which is meant to contain
* some additional properties which must be appended to existing service properties.
* Such extra properties takes precedence over existing service properties.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void start(Component service) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
// Check if some extra service properties are returned by start method.
DependencyManager dm = service.getDependencyManager();
Map<String, String> extraProperties = new HashMap<String, String>();
Object[] composites = service.getInstances();
for (Object composite : composites) {
Object o = invokeMethod(composite, m_start, dm, service);
if (o != null && Map.class.isAssignableFrom(o.getClass())) {
extraProperties.putAll((Map) o);
}
}
if (extraProperties.size() > 0) {
// Store extra properties returned by start callbacks into existing service properties
Dictionary existingProperties = service.getServiceProperties();
if (existingProperties != null) {
Hashtable props = new Hashtable();
Enumeration e = existingProperties.keys();
while (e.hasMoreElements()) {
Object key = e.nextElement();
props.put(key, existingProperties.get(key));
}
props.putAll(extraProperties);
service.setServiceProperties(props);
} else {
service.setServiceProperties(new Hashtable(extraProperties));
}
}
}
use of org.apache.felix.dm.DependencyManager in project felix by apache.
the class ServiceLifecycleHandler method init.
/**
* Handles an "init" lifecycle service callback. We just catch the "init" method, and callback
* the actual Service' init method, to see if a dependency customization map is returned.
* We also check if a Lifecycle Controller is used. In this case, we add a hidden custom dependency,
* allowing to take control of when the component is actually started/stopped.
* We also handle an edge case described in FELIX-4050, where component state calculation
* may mess up if some dependencies are added using the API from the init method.
*
* @param c The Annotated Component
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void init(Component c) throws Exception {
Object serviceInstance = c.getInstances()[0];
DependencyManager dm = c.getDependencyManager();
// Check if a lifecycle controller is defined for this service. If true, then
// We'll use the ToggleServiceDependency in order to manually activate/deactivate
// the component ...
String starter = m_srvMeta.getString(Params.starter, null);
String stopper = m_srvMeta.getString(Params.stopper, null);
List<Dependency> instanceBoundDeps = new ArrayList<>();
if (starter != null) {
// We'll inject two runnables: one that will start or service, when invoked, and the other
// that will stop our service, when invoked. We'll use a shared atomic boolean in order to
// synchronize both runnables.
Log.instance().debug("Setting up a lifecycle controller for service %s", serviceInstance);
String componentName = serviceInstance.getClass().getName();
// Create a toggle service, used to start/stop our service.
ToggleServiceDependency toggle = new ToggleServiceDependency();
AtomicBoolean startFlag = new AtomicBoolean(false);
// Add the toggle to the service.
instanceBoundDeps.add(toggle);
// Inject the runnable that will start our service, when invoked.
setField(serviceInstance, starter, Runnable.class, new ComponentStarter(componentName, toggle, startFlag));
if (stopper != null) {
// Inject the runnable that will stop our service, when invoked.
setField(serviceInstance, stopper, Runnable.class, new ComponentStopper(componentName, toggle, startFlag));
}
}
// Before invoking an optional init method, we have to handle an edge case (FELIX-4050), where
// init may add dependencies using the API and also return a map for configuring some
// named dependencies. We have to add a hidden toggle dependency in the component, which we'll
// active *after* the init method is called, and possibly *after* named dependencies are configured.
ToggleServiceDependency initToggle = null;
if (m_init != null) {
initToggle = new ToggleServiceDependency();
c.add(initToggle);
}
// Invoke component and all composites init methods, and for each one, check if a dependency
// customization map is returned by the method. This map will be used to configure
// some dependency filters (or required flag).
Map<String, String> customization = new HashMap<String, String>();
Object[] composites = c.getInstances();
for (Object composite : composites) {
Object o = invokeMethod(composite, m_init, dm, c);
if (o != null && Map.class.isAssignableFrom(o.getClass())) {
customization.putAll((Map) o);
}
}
Log.instance().debug("ServiceLifecycleHandler.init: invoked init method from service %s " + ", returned map: %s", serviceInstance, customization);
for (MetaData dependency : m_depsMeta) {
// 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.
// Also parse optional pid/propagate flags for named Configuration dependencies
String name = dependency.getString(Params.name, null);
if (name != null) {
String filter = customization.get(name + ".filter");
String required = customization.get(name + ".required");
String pid = customization.get(name + ".pid");
String propagate = customization.get(name + ".propagate");
if (filter != null || required != null || pid != null || propagate != null) {
dependency = (MetaData) dependency.clone();
if (filter != null) {
dependency.setString(Params.filter, filter);
}
if (required != null) {
dependency.setString(Params.required, required);
}
if (pid != null) {
dependency.setString(Params.pid, pid);
}
if (propagate != null) {
dependency.setString(Params.propagate, propagate);
}
}
DependencyBuilder depBuilder = new DependencyBuilder(dependency);
Log.instance().info("ServiceLifecycleHandler.init: adding dependency %s into service %s", dependency, m_srvMeta);
Dependency d = depBuilder.build(m_bundle, dm);
instanceBoundDeps.add(d);
}
}
// Add all extra dependencies in one shot, in order to calculate state changes for all dependencies at a time.
if (instanceBoundDeps.size() > 0) {
Log.instance().info("ServiceLifecycleHandler.init: adding extra/named dependencies %s", instanceBoundDeps);
c.add(instanceBoundDeps.toArray(new Dependency[instanceBoundDeps.size()]));
}
// hidden toggle, and then remove it from the component, because we don't need it anymore.
if (initToggle != null) {
c.remove(initToggle);
}
}
use of org.apache.felix.dm.DependencyManager in project felix by apache.
the class DynamicDependency method init.
/**
* The configuration has been injected and also other required dependencies defined from the Activator.
* Now, define some dynamic dependencies (here we use the configuration injected from our updated method in
* order to configure the filter and required flag for the "Storage" dependency).
*/
public void init(Component c) {
log.log(LogService.LOG_WARNING, "init: storage type=" + storageType + ", storageRequired=" + storageRequired);
DependencyManager dm = c.getDependencyManager();
// all dynamic dependencies must be declared atomically in the Component.add(...) method, which accepts varargs.
c.add(dm.createServiceDependency().setService(Storage.class, "(type=" + storageType + ")").setRequired(storageRequired));
}
use of org.apache.felix.dm.DependencyManager in project felix by apache.
the class DMCommand method showTopComponents.
/**
* Displays components callbacks (init/start/stop/destroy) elapsed time.
* The components are sorted (the most time consuming components are displayed first).
* @param max the max number of components to display (0 means all components)
*/
private void showTopComponents(int max) {
List<Component> components = new ArrayList<>();
for (DependencyManager manager : DependencyManager.getDependencyManagers()) {
components.addAll(manager.getComponents());
}
Collections.sort(components, new Comparator<Component>() {
@Override
public int compare(Component c1, Component c2) {
Map<String, Long> c1Times = c1.getComponentDeclaration().getCallbacksTime();
Map<String, Long> c2Times = c2.getComponentDeclaration().getCallbacksTime();
Long c1Start = c1Times.get("start");
Long c2Start = c2Times.get("start");
if (c1Start != null) {
if (c2Start != null) {
return c1Start > c2Start ? 1 : -1;
} else {
return 1;
}
} else {
if (c2Start != null) {
return -1;
} else {
return 0;
}
}
}
});
Collections.reverse(components);
System.out.printf("%-100s %10s %10s%n%n", "Top components (sorted by start duration time)", "[init time]", "[start time]");
if (components.size() > 0) {
System.out.println();
max = max == 0 ? components.size() : Math.min(components.size(), max);
for (int i = 0; i < components.size() && i < max; i++) {
ComponentDeclaration decl = components.get(i).getComponentDeclaration();
System.out.printf("%-100s %10d %10d%n", decl.getClassName(), decl.getCallbacksTime().get("init"), decl.getCallbacksTime().get("start"));
}
}
}
Aggregations