Search in sources :

Example 6 with DependencyManager

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) {
            }
        }
    }
}
Also used : InputStreamReader(java.io.InputStreamReader) BufferedReader(java.io.BufferedReader) DependencyManager(org.apache.felix.dm.DependencyManager) IOException(java.io.IOException)

Example 7 with DependencyManager

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));
        }
    }
}
Also used : Dictionary(java.util.Dictionary) Enumeration(java.util.Enumeration) HashMap(java.util.HashMap) Hashtable(java.util.Hashtable) DependencyManager(org.apache.felix.dm.DependencyManager) HashMap(java.util.HashMap) Map(java.util.Map)

Example 8 with DependencyManager

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);
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) DependencyManager(org.apache.felix.dm.DependencyManager) Dependency(org.apache.felix.dm.Dependency) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) Map(java.util.Map)

Example 9 with DependencyManager

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));
}
Also used : DependencyManager(org.apache.felix.dm.DependencyManager)

Example 10 with DependencyManager

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"));
        }
    }
}
Also used : ComponentDeclaration(org.apache.felix.dm.ComponentDeclaration) ArrayList(java.util.ArrayList) DependencyManager(org.apache.felix.dm.DependencyManager) Component(org.apache.felix.dm.Component) Map(java.util.Map)

Aggregations

DependencyManager (org.apache.felix.dm.DependencyManager)255 Component (org.apache.felix.dm.Component)226 Ensure (org.apache.felix.dm.itest.util.Ensure)91 DependencyManagerActivator.component (org.apache.felix.dm.lambda.DependencyManagerActivator.component)70 Hashtable (java.util.Hashtable)56 Assert (org.junit.Assert)50 Dictionary (java.util.Dictionary)28 Map (java.util.Map)27 ServiceReference (org.osgi.framework.ServiceReference)24 DependencyManagerActivator.aspect (org.apache.felix.dm.lambda.DependencyManagerActivator.aspect)21 ServiceRegistration (org.osgi.framework.ServiceRegistration)18 DependencyManagerActivator.adapter (org.apache.felix.dm.lambda.DependencyManagerActivator.adapter)15 Bundle (org.osgi.framework.Bundle)15 HashMap (java.util.HashMap)13 ArrayList (java.util.ArrayList)12 ComponentDeclaration (org.apache.felix.dm.ComponentDeclaration)12 ServiceDependency (org.apache.felix.dm.ServiceDependency)11 Properties (java.util.Properties)10 List (java.util.List)9 DependencyGraph (org.apache.felix.dm.diagnostics.DependencyGraph)9