use of org.apache.felix.dm.Dependency in project felix by apache.
the class ComponentImpl method add.
@Override
public Component add(final Dependency... dependencies) {
getExecutor().execute(() -> {
List<DependencyContext> instanceBoundDeps = new ArrayList<>();
for (Dependency d : dependencies) {
DependencyContext dc = (DependencyContext) d;
if (dc.getComponentContext() != null) {
m_logger.err("%s can't be added to %s (dependency already added to component %s).", dc, ComponentImpl.this, dc.getComponentContext());
continue;
}
m_dependencyEvents.put(dc, new ConcurrentSkipListSet<Event>());
m_dependencies.add(dc);
generateNameBasedOnServiceAndProperties();
dc.setComponentContext(ComponentImpl.this);
if (!(m_state == ComponentState.INACTIVE)) {
dc.setInstanceBound(true);
instanceBoundDeps.add(dc);
}
}
startDependencies(instanceBoundDeps);
handleChange();
});
return this;
}
use of org.apache.felix.dm.Dependency in project felix by apache.
the class DependencyBuilder method createServiceDependency.
private Dependency createServiceDependency(Bundle b, DependencyManager dm) throws ClassNotFoundException {
String service = m_metaData.getString(Params.service, null);
Class<?> serviceClass = service != null ? b.loadClass(service) : null;
String serviceFilter = m_metaData.getString(Params.filter, null);
String defaultServiceImpl = m_metaData.getString(Params.defaultImpl, null);
Class<?> defaultServiceImplClass = (defaultServiceImpl != null) ? b.loadClass(defaultServiceImpl) : null;
String added = m_metaData.getString(Params.added, null);
long timeout = m_metaData.getLong(Params.timeout, -1L);
String changed = timeout != -1 ? null : m_metaData.getString(Params.changed, null);
String removed = timeout != -1 ? null : m_metaData.getString(Params.removed, null);
String swap = m_metaData.getString(Params.swap, null);
String autoConfigField = m_metaData.getString(Params.autoConfig, null);
boolean required = "true".equals(m_metaData.getString(Params.required, "true"));
boolean propagate = "true".equals(m_metaData.getString(Params.propagate, "false"));
boolean dereference = "true".equals(m_metaData.getString(Params.dereference, "true"));
Dependency dp = createServiceDependency(dm, serviceClass, serviceFilter, defaultServiceImplClass, added, changed, removed, swap, autoConfigField, timeout, required, propagate, dereference);
return dp;
}
use of org.apache.felix.dm.Dependency in project felix by apache.
the class DependencyBuilder method createResourceDependency.
private Dependency createResourceDependency(DependencyManager dm) {
String added = m_metaData.getString(Params.added, null);
String changed = m_metaData.getString(Params.changed, null);
String removed = m_metaData.getString(Params.removed, null);
String filter = m_metaData.getString(Params.filter, null);
boolean required = "true".equals(m_metaData.getString(Params.required, "true"));
boolean propagate = "true".equals(m_metaData.getString(Params.propagate, "false"));
String autoConfigField = m_metaData.getString(Params.autoConfig, null);
Dependency dp = createResourceDependency(dm, added, changed, removed, required, filter, propagate, autoConfigField);
return dp;
}
use of org.apache.felix.dm.Dependency 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.Dependency in project felix by apache.
the class AbstractDecorator method addDependency.
/**
* Add a Dependency to all already instantiated services.
*/
public void addDependency(Dependency... dependencies) {
for (Component component : m_services.values()) {
Dependency[] copy = Stream.of(dependencies).map(d -> (DependencyContext) d).map(dc -> dc.createCopy()).toArray(Dependency[]::new);
for (int i = 0; i < dependencies.length; i++) {
m_depclones.put(dependencies[i], copy[i]);
}
component.add(copy);
}
}
Aggregations