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);
}
}
}
}
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() );
}
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;
}
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() );
}
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;
}
}
Aggregations