FELIX-3524: added support for new OSGi 4.3 configuration-pid attribute.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1345185 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java b/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
index 6ab57b6..8aadf20 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
@@ -22,8 +22,11 @@
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import org.apache.felix.scr.Component;
import org.apache.felix.scr.ScrService;
@@ -77,6 +80,25 @@
private final Map m_componentHoldersByName;
/**
+ * The map of known components indexed by component configuration pid. The values are
+ * Sets of the {@link ComponentHolder} interface. Normally, the configuration pid
+ * is the component name, but since DS 1.2 (OSGi 4.3), a component may specify a specific
+ * pid, and it is possible that different components refer to the same pid. That's why
+ * the values of this map are Sets of ComponentHolders, allowing to lookup all components
+ * which are using a given configuration pid.
+ * This map is used when the ConfigurationSupport detects that a CM pid is updated. When
+ * a PID is updated, the ConfigurationSupport listener class invokes the
+ * {@link #getComponentHoldersByPid(String)} method which returns an iterator over all
+ * components that are using the given pid for configuration.
+ * <p>
+ *
+ * @see #registerComponentHolder(String, ComponentHolder)
+ * @see #unregisterComponentHolder(String)
+ * @see ConfigurationSupport#configurationEvent(org.osgi.service.cm.ConfigurationEvent)
+ */
+ private final Map m_componentHoldersByPid;
+
+ /**
* Map of components by component ID. This map indexed by the component
* ID number (<code>java.lang.Long</code>) contains the actual
* {@link AbstractComponentManager} instances existing in the system.
@@ -107,6 +129,7 @@
{
m_bundleContext = context;
m_componentHoldersByName = new HashMap();
+ m_componentHoldersByPid = new HashMap();
m_componentsById = new HashMap();
m_componentCounter = -1;
@@ -355,8 +378,24 @@
m_componentHoldersByName.put( name, component );
}
- }
+ synchronized (m_componentHoldersByPid)
+ {
+ // See if the component declares a specific configuration pid (112.4.4 configuration-pid)
+ String configurationPid = component.getComponentMetadata().getConfigurationPid();
+
+ // Since several components may refer to the same configuration pid, we have to
+ // store the component holder in a Set, in order to be able to lookup every
+ // components from a given pid.
+ Set set = (Set) m_componentHoldersByPid.get(configurationPid);
+ if (set == null)
+ {
+ set = new HashSet();
+ m_componentHoldersByPid.put(configurationPid, set);
+ }
+ set.add(component);
+ }
+ }
/**
* Returns the component registered under the given name or <code>null</code>
@@ -379,6 +418,27 @@
return null;
}
+ /**
+ * Returns the list of ComponentHolder instances whose configuration pids are matching
+ * the given pid.
+ * @param pid the pid candidate
+ * @return a iterator of ComponentHolder, or an empty iterator if no ComponentHolders
+ * are found
+ */
+ public final Iterator getComponentHoldersByPid(String pid)
+ {
+ Set componentHoldersUsingPid = new HashSet();
+ synchronized (m_componentHoldersByPid)
+ {
+ Set set = (Set) m_componentHoldersByPid.get(pid);
+ // only return the entry if non-null and not a reservation
+ if (set != null)
+ {
+ componentHoldersUsingPid.addAll(set);
+ }
+ }
+ return componentHoldersUsingPid.iterator();
+ }
/**
* Returns an array of all values currently stored in the component holders
@@ -403,13 +463,29 @@
*/
final void unregisterComponentHolder( String name )
{
+ Object component;
synchronized ( m_componentHoldersByName )
{
- m_componentHoldersByName.remove( name );
+ component = m_componentHoldersByName.remove(name);
+ }
+
+ if (component instanceof ComponentHolder) {
+ synchronized (m_componentHoldersByPid)
+ {
+ String configurationPid = ((ComponentHolder) component).getComponentMetadata().getConfigurationPid();
+ Set componentsForPid = (Set) m_componentHoldersByPid.get(configurationPid);
+ if (componentsForPid != null)
+ {
+ componentsForPid.remove(component);
+ if (componentsForPid.size() == 0)
+ {
+ m_componentHoldersByPid.remove(configurationPid);
+ }
+ }
+ }
}
}
-
//---------- base configuration support
/**
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationSupport.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationSupport.java
index f158643..d60fb52 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationSupport.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurationSupport.java
@@ -21,6 +21,7 @@
import java.io.IOException;
import java.util.Dictionary;
import java.util.Hashtable;
+import java.util.Iterator;
import org.apache.felix.scr.impl.Activator;
import org.apache.felix.scr.impl.BundleComponentActivator;
@@ -76,7 +77,7 @@
{
final BundleContext bundleContext = holder.getActivator().getBundleContext();
final String bundleLocation = bundleContext.getBundle().getLocation();
- final String name = holder.getComponentMetadata().getName();
+ final String confPid = holder.getComponentMetadata().getConfigurationPid();
final ServiceReference caRef = bundleContext.getServiceReference(ComponentRegistry.CONFIGURATION_ADMIN);
if (caRef != null)
@@ -86,7 +87,7 @@
{
try
{
- final Configuration[] factory = findFactoryConfigurations(ca, name);
+ final Configuration[] factory = findFactoryConfigurations(ca, confPid);
if (factory != null)
{
for (int i = 0; i < factory.length; i++)
@@ -99,11 +100,11 @@
else
{
// check for configuration and configure the holder
- final Configuration singleton = findSingletonConfiguration(ca, name);
+ final Configuration singleton = findSingletonConfiguration(ca, confPid);
if (singleton != null)
{
- final Dictionary props = getConfiguration(ca, name, bundleLocation);
- holder.configurationUpdated(name, props);
+ final Dictionary props = getConfiguration(ca, confPid, bundleLocation);
+ holder.configurationUpdated(confPid, props);
}
}
}
@@ -164,24 +165,29 @@
final String pid = event.getPid();
final String factoryPid = event.getFactoryPid();
- final ComponentHolder cm;
+ // 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)
+ Iterator it;
+
if (factoryPid == null)
{
- cm = this.m_registry.getComponentHolder(pid);
+ it = this.m_registry.getComponentHoldersByPid(pid);
}
else
{
- cm = this.m_registry.getComponentHolder(factoryPid);
+ it = this.m_registry.getComponentHoldersByPid(factoryPid);
}
Activator.log(LogService.LOG_DEBUG, null, "configurationEvent: Handling "
- + ((event.getType() == ConfigurationEvent.CM_DELETED) ? "DELETE" : "UPDATE") + " of Configuration PID="
- + pid, null);
+ + ((event.getType() == ConfigurationEvent.CM_DELETED) ? "DELETE" : "UPDATE")
+ + " of Configuration PID=" + pid, null);
- if (cm != null && !cm.getComponentMetadata().isConfigurationIgnored())
+ while (it.hasNext())
{
- switch (event.getType())
+ final ComponentHolder cm = (ComponentHolder) it.next();
+ if (!cm.getComponentMetadata().isConfigurationIgnored())
{
+ switch (event.getType()) {
case ConfigurationEvent.CM_DELETED:
cm.configurationDeleted(pid);
break;
@@ -235,6 +241,7 @@
default:
Activator.log(LogService.LOG_WARNING, null, "Unknown ConfigurationEvent type " + event.getType(),
null);
+ }
}
}
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ImmediateComponentHolder.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ImmediateComponentHolder.java
index a627314..398d73d 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/config/ImmediateComponentHolder.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ImmediateComponentHolder.java
@@ -26,6 +26,7 @@
import org.apache.felix.scr.Component;
import org.apache.felix.scr.impl.BundleComponentActivator;
+import org.apache.felix.scr.impl.manager.ComponentFactoryImpl;
import org.apache.felix.scr.impl.manager.DelayedComponentManager;
import org.apache.felix.scr.impl.manager.ImmediateComponentManager;
import org.apache.felix.scr.impl.manager.ServiceFactoryComponentManager;
@@ -185,7 +186,7 @@
return;
}
- if ( pid.equals( getComponentMetadata().getName() ) )
+ if ( pid.equals( getComponentMetadata().getConfigurationPid() ) )
{
// singleton configuration deleted
m_singleComponent.obtainStateLock();
@@ -269,7 +270,7 @@
return;
}
- if ( pid.equals( getComponentMetadata().getName() ) )
+ if ( pid.equals( getComponentMetadata().getConfigurationPid() ) )
{
m_singleComponent.obtainStateLock();
try
@@ -444,6 +445,39 @@
}
}
+ /**
+ * Compares this {@code ImmediateComponentHolder} object to another object.
+ *
+ * <p>
+ * A ImmediateComponentHolder is considered to be <b>equal to </b> another
+ * ImmediateComponentHolder if the component names are equal(using
+ * {@code String.equals}).
+ *
+ * @param object The {@code ImmediateComponentHolder} object to be compared.
+ * @return {@code true} if {@code object} is a
+ * {@code ImmediateComponentHolder} and is equal to this object;
+ * {@code false} otherwise.
+ */
+ public boolean equals(Object object)
+ {
+ if (!(object instanceof ImmediateComponentHolder))
+ {
+ return false;
+ }
+
+ ImmediateComponentHolder other = (ImmediateComponentHolder) object;
+ return getComponentMetadata().getName().equals(other.getComponentMetadata().getName());
+ }
+
+ /**
+ * Returns a hash code value for the object.
+ *
+ * @return An integer which is a hash code value for this object.
+ */
+ public int hashCode()
+ {
+ return getComponentMetadata().getName().hashCode();
+ }
//---------- internal
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
index 2724a4d..524fb27 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
@@ -124,13 +124,13 @@
{
log(
LogService.LOG_DEBUG,
- "Component {0} created: DS={1}, implementation={2}, immediate={3}, default-enabled={4}, factory={5}, configuration-policy={6}, activate={7}, deactivate={8}, modified={9}",
+ "Component {0} created: DS={1}, implementation={2}, immediate={3}, default-enabled={4}, factory={5}, configuration-policy={6}, activate={7}, deactivate={8}, modified={9} configuration-pid={10}",
new Object[]
{ metadata.getName(), new Integer( metadata.getNamespaceCode() ),
metadata.getImplementationClassName(), Boolean.valueOf( metadata.isImmediate() ),
Boolean.valueOf( metadata.isEnabled() ), metadata.getFactoryIdentifier(),
metadata.getConfigurationPolicy(), metadata.getActivate(), metadata.getDeactivate(),
- metadata.getModified() }, null );
+ metadata.getModified(), metadata.getConfigurationPid() }, null );
if ( metadata.getServiceMetadata() != null )
{
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
index c7c5fad..1a7df82 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
@@ -140,6 +140,38 @@
return instance;
}
+ /**
+ * Compares this {@code ComponentFactoryImpl} object to another object.
+ *
+ * <p>
+ * A component factory impl is considered to be <b>equal to </b> another component
+ * factory impl if the component names are equal(using {@code String.equals}).
+ *
+ * @param object The {@code ComponentFactoryImpl} object to be compared.
+ * @return {@code true} if {@code object} is a
+ * {@code ComponentFactoryImpl} and is equal to this object;
+ * {@code false} otherwise.
+ */
+ public boolean equals(Object object)
+ {
+ if (!(object instanceof ComponentFactoryImpl))
+ {
+ return false;
+ }
+
+ ComponentFactoryImpl other = (ComponentFactoryImpl) object;
+ return getComponentMetadata().getName().equals(other.getComponentMetadata().getName());
+ }
+
+ /**
+ * Returns a hash code value for the object.
+ *
+ * @return An integer which is a hash code value for this object.
+ */
+ public int hashCode()
+ {
+ return getComponentMetadata().getName().hashCode();
+ }
/**
* The component factory does not have a component to create.
@@ -264,7 +296,7 @@
public void configurationDeleted( String pid )
{
- if ( pid.equals( getComponentMetadata().getName() ) )
+ if ( pid.equals( getComponentMetadata().getConfigurationPid() ) )
{
// deleting configuration of a component factory is like
// providing an empty configuration
@@ -299,7 +331,7 @@
public void configurationUpdated( String pid, Dictionary configuration )
{
- if ( pid.equals( getComponentMetadata().getName() ) )
+ if ( pid.equals( getComponentMetadata().getConfigurationPid() ) )
{
m_configuration = configuration;
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java b/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
index 3b524a7..2469c9d 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
@@ -94,6 +94,9 @@
// 112.4.3 configuration-policy (since DS 1.1)
private String m_configurationPolicy = null;
+ // 112.4.4 configuration-pid (since DS 1.2)
+ private String m_configurationPid;
+
// Associated properties (0..*)
private Dictionary m_properties = new Hashtable();
@@ -129,6 +132,19 @@
/////////////////////////////////////////// SETTERS //////////////////////////////////////
/**
+ * Setter for the configuration-pid component (since DS 1.2)
+ * @param configurationPid
+ */
+ public void setConfigirationPid(String configurationPid)
+ {
+ if ( m_validated )
+ {
+ return;
+ }
+ m_configurationPid = configurationPid;
+ }
+
+ /**
* Setter for the name
*
* @param name
@@ -418,6 +434,20 @@
return getImplementationClassName();
}
+ /**
+ * Returns the configuration pid for the component. The pid is the one specified in the
+ * component's configuration-pid DS 1.2 attribute, if specified. Else the component name is used
+ * as the pid by default.
+ */
+ public String getConfigurationPid()
+ {
+ if (m_configurationPid != null)
+ {
+ return m_configurationPid;
+ }
+ return getName();
+ }
+
/**
* Returns the value of the enabled flag
@@ -714,6 +744,12 @@
throw validationFailure( "modified method declaration requires DS 1.1 or later namespace " );
}
+ // 112.4.4 configuration-pid can be specified since DS 1.2
+ if ( m_configurationPid != null && m_namespaceCode < XmlHandler.DS_VERSION_1_2 )
+ {
+ throw validationFailure( "configuration-pid attribute requires DS 1.2 or later namespace " );
+ }
+
// Next check if the properties are valid (and extract property values)
Iterator propertyIterator = m_propertyMetaData.iterator();
while ( propertyIterator.hasNext() )