Search in sources :

Example 1 with TargetedPID

use of org.apache.felix.scr.impl.metadata.TargetedPID in project felix by apache.

the class RegionConfigurationSupport method configurationEvent.

// ---------- ConfigurationListener
/**
 * Called by the Configuration Admin service if a configuration is updated
 * or removed.
 * <p>
 * This method is really only called upon configuration changes; it is not
 * called for existing configurations upon startup of the Configuration
 * Admin service. To bridge this gap, the
 * {@link ComponentRegistry#serviceChanged(org.osgi.framework.ServiceEvent)} method called when the
 * Configuration Admin service is registered calls #configureComponentHolders which calls this method for all
 * existing configurations to be able to forward existing configurations to
 * components.
 *
 * @param event The configuration change event
 */
public void configurationEvent(ConfigurationEvent event) {
    final TargetedPID pid = new TargetedPID(event.getPid());
    String rawFactoryPid = event.getFactoryPid();
    final TargetedPID factoryPid = rawFactoryPid == null ? null : new TargetedPID(rawFactoryPid);
    // iterate over all components which must be configured with this pid
    // (since DS 1.2, components may specify a specific configuration PID (112.4.4 configuration-pid)
    Collection<ComponentHolder<?>> holders = getComponentHolders(factoryPid != null ? factoryPid : pid);
    logger.log(LogService.LOG_DEBUG, "configurationEvent: Handling {0} of Configuration PID={1} for component holders {2}", new Object[] { getEventType(event), pid, holders }, null);
    for (ComponentHolder<?> componentHolder : holders) {
        if (!componentHolder.getComponentMetadata().isConfigurationIgnored()) {
            switch(event.getType()) {
                case ConfigurationEvent.CM_DELETED:
                    if (factoryPid != null || !configureComponentHolder(componentHolder)) {
                        componentHolder.configurationDeleted(pid, factoryPid);
                    }
                    break;
                case ConfigurationEvent.CM_UPDATED:
                    {
                        final ComponentActivator activator = componentHolder.getActivator();
                        if (activator == null) {
                            break;
                        }
                        final BundleContext bundleContext = activator.getBundleContext();
                        if (bundleContext == null) {
                            break;
                        }
                        TargetedPID targetedPid = factoryPid == null ? pid : factoryPid;
                        TargetedPID oldTargetedPID = componentHolder.getConfigurationTargetedPID(pid, factoryPid);
                        if (factoryPid != null || targetedPid.equals(oldTargetedPID) || targetedPid.bindsStronger(oldTargetedPID)) {
                            final ConfigurationInfo configInfo = getConfigurationInfo(pid, targetedPid, componentHolder, bundleContext);
                            if (configInfo != null) {
                                if (checkBundleLocation(configInfo.getBundleLocation(), bundleContext.getBundle())) {
                                    // The below seems to be unnecessary - and if put in, the behaviour is not spec compliant anymore:
                                    // if a component has a required configuration and a modified method, the component must not be
                                    // reactivated
                                    // If this is replacing a weaker targetedPID delete the old one.
                                    // if ( factoryPid == null && !targetedPid.equals(oldTargetedPID) && oldTargetedPID != null)
                                    // {
                                    // componentHolder.configurationDeleted( pid, factoryPid );
                                    // }
                                    componentHolder.configurationUpdated(pid, factoryPid, configInfo.getProps(), configInfo.getChangeCount());
                                }
                            }
                        }
                        break;
                    }
                case ConfigurationEvent.CM_LOCATION_CHANGED:
                    {
                        // TODO is this logic correct for factory pids????
                        final ComponentActivator activator = componentHolder.getActivator();
                        if (activator == null) {
                            break;
                        }
                        final BundleContext bundleContext = activator.getBundleContext();
                        if (bundleContext == null) {
                            break;
                        }
                        TargetedPID targetedPid = factoryPid == null ? pid : factoryPid;
                        TargetedPID oldTargetedPID = componentHolder.getConfigurationTargetedPID(pid, factoryPid);
                        if (targetedPid.equals(oldTargetedPID)) {
                            // this sets the location to this component's bundle if not already set.  OK here
                            // since it used to be set to this bundle, ok to reset it
                            final ConfigurationInfo configInfo = getConfigurationInfo(pid, targetedPid, componentHolder, bundleContext);
                            if (configInfo != null) {
                                logger.log(LogService.LOG_DEBUG, "LocationChanged event, same targetedPID {0}, location now {1}, change count {2}", new Object[] { targetedPid, configInfo.getBundleLocation(), configInfo.getChangeCount() }, null);
                                if (configInfo.getProps() == null) {
                                    throw new IllegalStateException("Existing Configuration with pid " + pid + " has had its properties set to null and location changed.  We expected a delete event first.");
                                }
                                // this config was used on this component.  Does it still match?
                                if (!checkBundleLocation(configInfo.getBundleLocation(), bundleContext.getBundle())) {
                                    // no, delete it
                                    componentHolder.configurationDeleted(pid, factoryPid);
                                    // maybe there's another match
                                    configureComponentHolder(componentHolder);
                                }
                            // else still matches
                            }
                            break;
                        }
                        boolean better = targetedPid.bindsStronger(oldTargetedPID);
                        if (better) {
                            // this sets the location to this component's bundle if not already set.  OK here
                            // because if it is set to this bundle we will use it.
                            final ConfigurationInfo configInfo = getConfigurationInfo(pid, targetedPid, componentHolder, bundleContext);
                            if (configInfo != null) {
                                logger.log(LogService.LOG_DEBUG, "LocationChanged event, better targetedPID {0} compared to {1}, location now {2}, change count {3}", new Object[] { targetedPid, oldTargetedPID, configInfo.getBundleLocation(), configInfo.getChangeCount() }, null);
                                if (configInfo.getProps() == null) {
                                    // location has been changed before any properties are set.  We don't care.  Wait for an updated event with the properties
                                    break;
                                }
                                // this component was not configured with this config.  Should it be now?
                                if (checkBundleLocation(configInfo.getBundleLocation(), bundleContext.getBundle())) {
                                    if (oldTargetedPID != null) {
                                        // this is a better match, delete old before setting new
                                        componentHolder.configurationDeleted(pid, factoryPid);
                                    }
                                    componentHolder.configurationUpdated(pid, factoryPid, configInfo.getProps(), configInfo.getChangeCount());
                                }
                            }
                        } else // else worse match, do nothing
                        {
                            logger.log(LogService.LOG_DEBUG, "LocationChanged event, worse targetedPID {0} compared to {1}, do nothing", new Object[] { targetedPid, oldTargetedPID }, null);
                        }
                        break;
                    }
                default:
                    logger.log(LogService.LOG_WARNING, "Unknown ConfigurationEvent type {0}", new Object[] { event.getType() }, null);
            }
        }
    }
}
Also used : TargetedPID(org.apache.felix.scr.impl.metadata.TargetedPID) BundleContext(org.osgi.framework.BundleContext)

Example 2 with TargetedPID

use of org.apache.felix.scr.impl.metadata.TargetedPID in project felix by apache.

the class ConfiguredComponentHolderTest method test_singleton.

public void test_singleton() {
    // setup a holder
    final String name = "test.singleton";
    final ComponentMetadata cm = createComponentMetadata(name);
    final TestingConfiguredComponentHolder holder = new TestingConfiguredComponentHolder(cm);
    holder.enableComponents(false);
    // assert single component and no map
    final SingleComponentManager cmgr = getSingleManager(holder);
    assertNotNull("Expect single component manager", cmgr);
    assertEquals("Expect no other component manager list", 1, getComponentManagers(holder).size());
    // configure with the singleton configuration
    final Dictionary config = new Hashtable();
    config.put("value", name);
    TargetedPID targetedPid = new TargetedPID(name);
    holder.configurationUpdated(targetedPid, null, config, 0);
    // assert single component and no map
    final SingleComponentManager cmgrAfterConfig = getSingleManager(holder);
    assertNotNull("Expect single component manager", cmgrAfterConfig);
    assertEquals("Expect no other component manager list", 1, getComponentManagers(holder).size());
    // // assert configuration of single component
    final Map componentConfig = ((MockImmediateComponentManager) cmgrAfterConfig).getConfiguration();
    assertEquals("Expect exact configuration set", config, componentConfig);
    // unconfigure singleton
    holder.configurationDeleted(targetedPid, null);
    // assert single component and no map
    final SingleComponentManager cmgrAfterUnconfig = getSingleManager(holder);
    assertNotNull("Expect single component manager", cmgrAfterUnconfig);
    assertEquals("Expect no other component manager list", 1, getComponentManagers(holder).size());
// assert no configuration of single component
// TODO multipids fix, correct assertion        assertFalse( "Expect no configuration", cmgrAfterUnconfig.hasConfiguration() );
}
Also used : Dictionary(java.util.Dictionary) Hashtable(java.util.Hashtable) ComponentMetadata(org.apache.felix.scr.impl.metadata.ComponentMetadata) TargetedPID(org.apache.felix.scr.impl.metadata.TargetedPID) Map(java.util.Map)

Example 3 with TargetedPID

use of org.apache.felix.scr.impl.metadata.TargetedPID in project felix by apache.

the class RegionConfigurationSupport method configureComponentHolder.

/**
 * The return value is only relevant for the call from {@link #configurationEvent(ConfigurationEvent)}
 * in the case of a deleted configuration which is not a factory configuration!
 */
public boolean configureComponentHolder(final ComponentHolder<?> holder) {
    // 112.7 configure unless configuration not required
    if (!holder.getComponentMetadata().isConfigurationIgnored()) {
        final BundleContext bundleContext = holder.getActivator().getBundleContext();
        if (bundleContext == null) {
            // bundle was stopped concurrently with configuration deletion
            return false;
        }
        final List<String> confPids = holder.getComponentMetadata().getConfigurationPid();
        final ConfigurationAdmin ca = getConfigAdmin(bundleContext);
        try {
            for (final String confPid : confPids) {
                final Collection<Configuration> factory = findFactoryConfigurations(ca, confPid, bundleContext.getBundle());
                if (!factory.isEmpty()) {
                    boolean created = false;
                    for (Configuration config : factory) {
                        logger.log(LogService.LOG_DEBUG, "Configuring holder {0} with factory configuration {1}, change count {2}", new Object[] { holder, config, config.getChangeCount() }, null);
                        if (checkBundleLocation(config, bundleContext.getBundle())) {
                            long changeCount = config.getChangeCount();
                            created |= holder.configurationUpdated(new TargetedPID(config.getPid()), new TargetedPID(config.getFactoryPid()), config.getProperties(), changeCount);
                        }
                    }
                    if (!created) {
                        return false;
                    }
                } else {
                    // check for configuration and configure the holder
                    Configuration singleton = findSingletonConfiguration(ca, confPid, bundleContext.getBundle());
                    if (singleton != null) {
                        logger.log(LogService.LOG_DEBUG, "Configuring holder {0} with configuration {1}, change count {2}", new Object[] { holder, singleton, singleton.getChangeCount() }, null);
                        if (singleton != null && checkBundleLocation(singleton, bundleContext.getBundle())) {
                            long changeCount = singleton.getChangeCount();
                            holder.configurationUpdated(new TargetedPID(singleton.getPid()), null, singleton.getProperties(), changeCount);
                        } else {
                            return false;
                        }
                    } else {
                        return false;
                    }
                }
            }
            return !confPids.isEmpty();
        } finally {
            try {
                bundleContext.ungetService(caReference);
            } catch (IllegalStateException e) {
            // ignore, bundle context was shut down during the above.
            }
        }
    }
    return false;
}
Also used : Configuration(org.osgi.service.cm.Configuration) ConfigurationAdmin(org.osgi.service.cm.ConfigurationAdmin) TargetedPID(org.apache.felix.scr.impl.metadata.TargetedPID) BundleContext(org.osgi.framework.BundleContext)

Example 4 with TargetedPID

use of org.apache.felix.scr.impl.metadata.TargetedPID in project felix by apache.

the class ConfiguredComponentHolderTest method test_factory.

public void test_factory() {
    // setup a holder
    final String name = "test.factory";
    final ComponentMetadata cm = createComponentMetadata(name);
    final TestingConfiguredComponentHolder holder = new TestingConfiguredComponentHolder(cm);
    holder.enableComponents(false);
    // assert single component and no map
    final SingleComponentManager cmgr = getSingleManager(holder);
    assertNotNull("Expect single component manager", cmgr);
    assertEquals("Expect no other component manager list", 1, getComponentManagers(holder).size());
    // configure with configuration
    final String pid1 = "test.factory.0001";
    final Dictionary config1 = new Hashtable();
    config1.put("value", pid1);
    TargetedPID targetedFactoryPid = new TargetedPID(name);
    TargetedPID targetedPid1 = new TargetedPID(pid1);
    holder.configurationUpdated(targetedPid1, targetedFactoryPid, config1, 0);
    // assert single component and single-entry map
    final SingleComponentManager cmgrAfterConfig = getSingleManager(holder);
    final List<SingleComponentManager> cmgrsAfterConfig = getComponentManagers(holder);
    assertNotNull("Expect single component manager", cmgrAfterConfig);
    assertNotNull("Expect component manager list", cmgrsAfterConfig);
    assertEquals("Expect one component manager in list", 1, cmgrsAfterConfig.size());
    // add another configuration
    final String pid2 = "test.factory.0002";
    final Dictionary config2 = new Hashtable();
    config1.put("value", pid2);
    TargetedPID targetedPid2 = new TargetedPID(pid2);
    holder.configurationUpdated(targetedPid2, targetedFactoryPid, config2, 1);
    final List<SingleComponentManager> cmgrsAfterConfig2 = getComponentManagers(holder);
    assertNotNull("Expect component manager list", cmgrsAfterConfig2);
    assertEquals("Expect two component manager in list", 2, cmgrsAfterConfig2.size());
    // remove second configuration
    holder.configurationDeleted(targetedPid2, targetedFactoryPid);
    final List<SingleComponentManager> cmgrsAfterUnConfig2 = getComponentManagers(holder);
    assertNotNull("Expect component manager list", cmgrsAfterUnConfig2);
    // TODO Multipids fix correct assertion        assertEquals( "Expect one component manager in list", 1, cmgrsAfterUnConfig2.size() );
    // add second config again and remove first config -> replace singleton component
    holder.configurationUpdated(targetedPid2, targetedFactoryPid, config2, 2);
    holder.configurationDeleted(targetedPid1, targetedFactoryPid);
    // assert single component and single-entry map
    final List<SingleComponentManager> cmgrsAfterConfigUnconfig = getComponentManagers(holder);
    assertNotNull("Expect component manager list", cmgrsAfterConfigUnconfig);
    // TODO Multipids fix correct assertion        assertEquals( "Expect one component manager in list", 1, cmgrsAfterConfigUnconfig.size() );
    // remove second configuration (leaving no configurations)
    holder.configurationDeleted(targetedPid2, targetedFactoryPid);
    // assert single component and single-entry map
    final List<SingleComponentManager> cmgrsAfterAllUnconfig = getComponentManagers(holder);
    assertNotNull("Expect single component manager", cmgrsAfterAllUnconfig);
// TODO Multipids fix correct assertion        assertEquals( "Expect no component manager list", 1, cmgrsAfterAllUnconfig.size() );
}
Also used : Dictionary(java.util.Dictionary) Hashtable(java.util.Hashtable) ComponentMetadata(org.apache.felix.scr.impl.metadata.ComponentMetadata) TargetedPID(org.apache.felix.scr.impl.metadata.TargetedPID)

Example 5 with TargetedPID

use of org.apache.felix.scr.impl.metadata.TargetedPID in project felix by apache.

the class ConfigurableComponentHolder method enableComponents.

public Promise<Void> enableComponents(final boolean async) {
    synchronized (enableLock) {
        if (m_enablePromise != null) {
            return m_enablePromise;
        }
        wait(m_disablePromise);
        List<AbstractComponentManager<S>> cms = new ArrayList<AbstractComponentManager<S>>();
        synchronized (m_components) {
            if (isSatisfied()) {
                if (m_factoryPidIndex == null || (m_componentMetadata.isObsoleteFactoryComponentFactory() && !m_componentMetadata.isConfigurationRequired())) {
                    m_singleComponent = createComponentManager(false);
                    cms.add(m_singleComponent);
                    m_singleComponent.reconfigure(mergeProperties(null), false, null);
                }
                if (m_factoryPidIndex != null) {
                    for (String pid : m_factoryConfigurations.keySet()) {
                        AbstractComponentManager<S> scm = createComponentManager(true);
                        m_components.put(pid, scm);
                        scm.reconfigure(mergeProperties(pid), false, new TargetedPID(pid));
                        cms.add(scm);
                    }
                }
            }
            m_enabled = true;
        }
        List<Promise<Void>> promises = new ArrayList<Promise<Void>>();
        for (AbstractComponentManager<S> cm : cms) {
            promises.add(cm.enable(async));
        }
        m_enablePromise = new Deferred<List<Void>>().resolveWith(Promises.<Void, Void>all(promises));
        m_disablePromise = null;
        return m_enablePromise;
    }
}
Also used : Promise(org.osgi.util.promise.Promise) Deferred(org.osgi.util.promise.Deferred) ArrayList(java.util.ArrayList) TargetedPID(org.apache.felix.scr.impl.metadata.TargetedPID)

Aggregations

TargetedPID (org.apache.felix.scr.impl.metadata.TargetedPID)6 Dictionary (java.util.Dictionary)2 Hashtable (java.util.Hashtable)2 Map (java.util.Map)2 ComponentMetadata (org.apache.felix.scr.impl.metadata.ComponentMetadata)2 BundleContext (org.osgi.framework.BundleContext)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Configuration (org.osgi.service.cm.Configuration)1 ConfigurationAdmin (org.osgi.service.cm.ConfigurationAdmin)1 Deferred (org.osgi.util.promise.Deferred)1 Promise (org.osgi.util.promise.Promise)1