FELIX-4401 Temporarily add runtime spec packages to source
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1602632 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/Activator.java b/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
index 9ab6180..7166530 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
@@ -27,12 +27,15 @@
import java.util.concurrent.TimeUnit;
import org.apache.felix.scr.impl.config.ScrConfiguration;
+import org.apache.felix.scr.impl.runtime.ServiceComponentRuntimeImpl;
import org.apache.felix.utils.extender.AbstractExtender;
import org.apache.felix.utils.extender.Extension;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentConstants;
+import org.osgi.service.component.runtime.ServiceComponentRuntime;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
@@ -73,6 +76,8 @@
// thread acting upon configurations
private ComponentActorThread m_componentActor;
+
+ private ServiceRegistration<ServiceComponentRuntime> m_runtime_reg;
public Activator() {
m_configuration = new ScrConfiguration( this );
@@ -136,7 +141,8 @@
// prepare component registry
m_componentBundles = new HashMap<Long, BundleComponentActivator>();
m_componentRegistry = new ComponentRegistry( m_context );
-
+ ServiceComponentRuntime runtime = new ServiceComponentRuntimeImpl(m_context, m_componentRegistry);
+ m_runtime_reg = m_context.registerService(ServiceComponentRuntime.class, runtime, null);
// log SCR startup
log( LogService.LOG_INFO, m_bundle, " Version = {0}",
@@ -150,9 +156,10 @@
super.doStart();
+ //TODO register runtime. Possibly register obsolete stuff too.
// register the Gogo and old Shell commands
- ScrCommand scrCommand = ScrCommand.register(m_context, m_componentRegistry, m_configuration);
- m_configuration.setScrCommand( scrCommand );
+// ScrCommand scrCommand = ScrCommand.register(m_context, m_componentRegistry, m_configuration);
+// m_configuration.setScrCommand( scrCommand );
}
public void stop(BundleContext context) throws Exception
@@ -173,7 +180,12 @@
// stop tracking
super.doStop();
- // dispose component registry
+ if (m_runtime_reg != null)
+ {
+ m_runtime_reg.unregister();
+ m_runtime_reg = null;
+ }
+ // dispose component registry
m_componentRegistry.dispose();
// terminate the actor thread
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 bd665f1..a667462 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
@@ -60,7 +60,7 @@
* registers itself as the {@link ScrService} to support access to the
* registered components.
*/
-public class ComponentRegistry implements ScrService, ServiceListener
+public class ComponentRegistry implements ServiceListener
{
// the name of the ConfigurationAdmin service
@@ -84,7 +84,7 @@
* @see #registerComponentHolder(String, ComponentHolder)
* @see #unregisterComponentHolder(String)
*/
- private final Map<ComponentRegistryKey, ComponentHolder> m_componentHoldersByName;
+ private final Map<ComponentRegistryKey, ComponentHolder<?>> m_componentHoldersByName;
/**
* The map of known components indexed by component configuration pid. The values are
@@ -103,7 +103,7 @@
* @see #unregisterComponentHolder(String)
* @see ConfigurationSupport#configurationEvent(org.osgi.service.cm.ConfigurationEvent)
*/
- private final Map<String, Set<ComponentHolder>> m_componentHoldersByPid;
+ private final Map<String, Set<ComponentHolder<?>>> m_componentHoldersByPid;
/**
* Map of components by component ID. This map indexed by the component
@@ -137,8 +137,8 @@
protected ComponentRegistry( BundleContext context )
{
m_bundleContext = context;
- m_componentHoldersByName = new HashMap<ComponentRegistryKey, ComponentHolder>();
- m_componentHoldersByPid = new HashMap<String, Set<ComponentHolder>>();
+ m_componentHoldersByName = new HashMap<ComponentRegistryKey, ComponentHolder<?>>();
+ m_componentHoldersByPid = new HashMap<String, Set<ComponentHolder<?>>>();
m_componentsById = new HashMap<Long, AbstractComponentManager<?>>();
// keep me informed on ConfigurationAdmin state changes
@@ -159,11 +159,11 @@
}
// register as ScrService
- Dictionary props = new Hashtable();
- props.put( Constants.SERVICE_DESCRIPTION, "Declarative Services Management Agent" );
- props.put( Constants.SERVICE_VENDOR, "The Apache Software Foundation" );
- m_registration = context.registerService( new String[]
- { ScrService.class.getName(), }, this, props );
+// Dictionary<String, Object> props = new Hashtable<String, Object>();
+// props.put( Constants.SERVICE_DESCRIPTION, "Declarative Services Management Agent" );
+// props.put( Constants.SERVICE_VENDOR, "The Apache Software Foundation" );
+// m_registration = context.registerService( new String[]
+// { ScrService.class.getName(), }, this, props );
}
@@ -187,79 +187,79 @@
//---------- ScrService interface
- public Component[] getComponents()
- {
- ComponentHolder[] holders = getComponentHolders();
- ArrayList<Component> list = new ArrayList<Component>();
- for ( ComponentHolder holder: holders )
- {
- if ( holder != null )
- {
- list.addAll(holder.getComponents());
- }
- }
-
- // nothing to return
- if ( list.isEmpty() )
- {
- return null;
- }
-
- return ( Component[] ) list.toArray( new Component[list.size()] );
- }
+// public Component[] getComponents()
+// {
+// List<ComponentHolder<?>> holders = getComponentHolders();
+// ArrayList<Component> list = new ArrayList<Component>();
+// for ( ComponentHolder holder: holders )
+// {
+// if ( holder != null )
+// {
+// list.addAll(holder.getComponents());
+// }
+// }
+//
+// // nothing to return
+// if ( list.isEmpty() )
+// {
+// return null;
+// }
+//
+// return ( Component[] ) list.toArray( new Component[list.size()] );
+// }
- public Component[] getComponents( Bundle bundle )
- {
- ComponentHolder[] holders = getComponentHolders();
- List<Component> list = new ArrayList<Component>();
- for ( ComponentHolder<?> holder: holders )
- {
- if ( holder != null )
- {
- BundleComponentActivator activator = holder.getActivator();
- if ( activator != null && activator.getBundleContext().getBundle() == bundle )
- {
- list.addAll(holder.getComponents());
- }
- }
- }
-
- // nothing to return
- if ( list.isEmpty() )
- {
- return null;
- }
-
- return list.toArray( new Component[list.size()] );
- }
+// public Component[] getComponents( Bundle bundle )
+// {
+// List<ComponentHolder<?>> holders = getComponentHolders();
+// List<Component> list = new ArrayList<Component>();
+// for ( ComponentHolder<?> holder: holders )
+// {
+// if ( holder != null )
+// {
+// BundleComponentActivator activator = holder.getActivator();
+// if ( activator != null && activator.getBundleContext().getBundle() == bundle )
+// {
+// list.addAll(holder.getComponents());
+// }
+// }
+// }
+//
+// // nothing to return
+// if ( list.isEmpty() )
+// {
+// return null;
+// }
+//
+// return list.toArray( new Component[list.size()] );
+// }
+//
+//
+// public Component getComponent( long componentId )
+// {
+// synchronized ( m_componentsById )
+// {
+// return m_componentsById.get( componentId );
+// }
+// }
- public Component getComponent( long componentId )
- {
- synchronized ( m_componentsById )
- {
- return m_componentsById.get( componentId );
- }
- }
-
-
- public Component[] getComponents( String componentName )
- {
- List<Component> list = new ArrayList<Component>();
- synchronized ( m_componentHoldersByName )
- {
- for ( ComponentHolder<?> c: m_componentHoldersByName.values() )
- {
- if ( c.getComponentMetadata().getName().equals( componentName ) )
- {
- list.addAll( c.getComponents() );
- }
- }
- }
-
- return ( list.isEmpty() ) ? null : list.toArray( new Component[list.size()] );
- }
+// public Component[] getComponents( String componentName )
+// {
+// List<Component> list = new ArrayList<Component>();
+// synchronized ( m_componentHoldersByName )
+// {
+// for ( ComponentHolder<?> c: m_componentHoldersByName.values() )
+// {
+// if ( c.getComponentMetadata().getName().equals( componentName ) )
+// {
+// list.addAll( c.getComponents() );
+// }
+// }
+// }
+//
+// return ( list.isEmpty() ) ? null : list.toArray( new Component[list.size()] );
+// }
//---------- ComponentManager registration by component Id
@@ -406,10 +406,10 @@
// 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<ComponentHolder> set = m_componentHoldersByPid.get( configurationPid );
+ Set<ComponentHolder<?>> set = m_componentHoldersByPid.get( configurationPid );
if ( set == null )
{
- set = new HashSet<ComponentHolder>();
+ set = new HashSet<ComponentHolder<?>>();
m_componentHoldersByPid.put( configurationPid, set );
}
set.add( componentHolder );
@@ -441,13 +441,13 @@
* @param pid the pid candidate
* @return the set of ComponentHolders matching the singleton pid supplied
*/
- public final Collection<ComponentHolder> getComponentHoldersByPid(TargetedPID targetedPid)
+ public final Collection<ComponentHolder<?>> getComponentHoldersByPid(TargetedPID targetedPid)
{
String pid = targetedPid.getServicePid();
- Set<ComponentHolder> componentHoldersUsingPid = new HashSet<ComponentHolder>();
+ Set<ComponentHolder<?>> componentHoldersUsingPid = new HashSet<ComponentHolder<?>>();
synchronized (m_componentHoldersByPid)
{
- Set<ComponentHolder> set = m_componentHoldersByPid.get(pid);
+ Set<ComponentHolder<?>> set = m_componentHoldersByPid.get(pid);
// only return the entry if non-null and not a reservation
if (set != null)
{
@@ -469,12 +469,36 @@
* name reservations or {@link ComponentHolder} instances for actual
* holders of components.
*/
- private ComponentHolder[] getComponentHolders()
+ public final List<ComponentHolder<?>> getComponentHolders()
{
+ List<ComponentHolder<?>> all = new ArrayList<ComponentHolder<?>>();
synchronized ( m_componentHoldersByName )
{
- return m_componentHoldersByName.values().toArray( new ComponentHolder[ m_componentHoldersByName.size() ]);
+ all.addAll(m_componentHoldersByName.values());
}
+ return all;
+ }
+
+ public final List<ComponentHolder<?>> getComponentHolders(Bundle...bundles)
+ {
+ List<ComponentHolder<?>> all =getComponentHolders();
+ List<ComponentHolder<?>> holders = new ArrayList<ComponentHolder<?>>();
+ for ( ComponentHolder<?> holder: all)
+ {
+ BundleComponentActivator activator = holder.getActivator();
+ if (activator != null)
+ {
+ Bundle holderBundle = activator.getBundleContext().getBundle();
+ for (Bundle b: bundles)
+ {
+ if (b == holderBundle)
+ {
+ holders.add(holder);
+ }
+ }
+ }
+ }
+ return holders;
}
@@ -498,7 +522,7 @@
*/
final void unregisterComponentHolder( final ComponentRegistryKey key )
{
- ComponentHolder component;
+ ComponentHolder<?> component;
synchronized ( m_componentHoldersByName )
{
component = m_componentHoldersByName.remove( key );
@@ -513,7 +537,7 @@
List<String> configurationPids = component.getComponentMetadata().getConfigurationPid();
for ( String configurationPid: configurationPids )
{
- Set<ComponentHolder> componentsForPid = m_componentHoldersByPid.get( configurationPid );
+ Set<ComponentHolder<?>> componentsForPid = m_componentHoldersByPid.get( configurationPid );
if ( componentsForPid != null )
{
componentsForPid.remove( component );
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java
index d91bd49..d2e3722 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentHolder.java
@@ -61,14 +61,15 @@
* Configuration Admin service.
*
* @param pid The PID of the deleted configuration
+ * @param factoryPid TODO
*/
- void configurationDeleted( String pid );
+ void configurationDeleted( TargetedPID pid, TargetedPID factoryPid );
/**
* Configure a component with configuration from the given PID.
* @param targetedPid Targeted PID for the configuration
- * @param factoryTargetedPid TODO
+ * @param factoryTargetedPid the (targeted) factory pid or null for a singleton pid
* @param props the property dictionary from the configuration.
* @param changeCount change count of the configuration, or R4 imitation.
*
@@ -79,10 +80,11 @@
/**
* Change count (or fake R4 imitation)
- * @param pid PID of the component we are interested in.
+ * @param pid a PID for the component we are interested in.
+ * @param targetedPid For a singleton pid, same as "pid"; for a factory pid, the factory pid.
* @return the last change count from a configurationUpdated call for the given pid.
*/
- long getChangeCount( TargetedPID pid );
+ long getChangeCount( TargetedPID pid, TargetedPID targetedPid );
/**
* Returns the targeted PID used to configure this component
@@ -95,7 +97,7 @@
/**
* Returns all <code>Component</code> instances held by this holder.
*/
- List<? extends Component> getComponents();
+ List<? extends ComponentManager<?>> getComponents();
/**
* Enables all components of this holder and if satisifed activates
@@ -114,6 +116,12 @@
* asynchronously or not.
*/
void disableComponents( boolean async );
+
+ /**
+ * whether the component is currently enabled
+ * @return whether the component is enabled
+ */
+ boolean isEnabled();
/**
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentManager.java
new file mode 100644
index 0000000..f773090
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ComponentManager.java
@@ -0,0 +1,27 @@
+package org.apache.felix.scr.impl.config;
+
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+
+
+public interface ComponentManager<S> {
+
+ int STATE_SATISFIED = ComponentConfigurationDTO.SATISFIED;
+ int STATE_UNSATISFIED = ComponentConfigurationDTO.UNSATISFIED;
+ int STATE_ACTIVE = ComponentConfigurationDTO.ACTIVE;
+ int STATE_FACTORY = 8;
+ int STATE_FACTORY_INSTANCE = 16;
+ int STATE_DISPOSED = 32;
+ int STATE_DISABLED = 64; //TODO????
+
+ Map<String, Object> getProperties();
+
+ long getId();
+
+ int getState();
+
+ List<? extends ReferenceManager<S, ?>> getReferenceManagers();
+
+}
\ No newline at end of file
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurableComponentHolder.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurableComponentHolder.java
index 2e51102..5aa27ed 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurableComponentHolder.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ConfigurableComponentHolder.java
@@ -74,9 +74,9 @@
/** the targeted pids corresponding to the pids specified in the config metadata, except possibly for the single
* factory pid
*/
- private final List<TargetedPID> m_targetedPids;
+ private final TargetedPID[] m_targetedPids;
- private final List<Long> m_changeCount;
+ private final Long[] m_changeCount;
private final Map<String, Long> m_factoryChangeCount = new HashMap<String, Long>();
@@ -89,7 +89,7 @@
/**
* the non-factory configurations shared between all instances.
*/
- private final List<Dictionary<String, Object>> m_configurations;
+ private final Dictionary<String, Object>[] m_configurations;
/**
* the factory configurations indexed by pid (which cannot be a TargetedPID since it's generated by CA). We have to track these since
@@ -143,15 +143,9 @@
this.m_activator = activator;
this.m_componentMetadata = metadata;
int pidCount = metadata.getConfigurationPid().size();
- this.m_targetedPids = new ArrayList<TargetedPID>(pidCount);
- this.m_configurations = new ArrayList<Dictionary<String, Object>>(pidCount);
- this.m_changeCount = new ArrayList<Long>(pidCount);
- for (int i = 0; i < pidCount; i++)
- {
- m_targetedPids.add(null);
- m_configurations.add(null);
- m_changeCount.add(null);
- }
+ this.m_targetedPids = new TargetedPID[pidCount];
+ this.m_configurations = new Dictionary[pidCount];
+ this.m_changeCount = new Long[pidCount];
this.m_components = new HashMap<String, SingleComponentManager<S>>();
this.m_componentMethods = new ComponentMethods();
this.m_enabled = false;
@@ -182,6 +176,10 @@
manager = new SingleComponentManager<S>( m_activator, this, m_componentMetadata, m_componentMethods );
}
+ if ( m_enabled )
+ {
+ manager.enable( false );
+ }
return manager;
}
@@ -218,75 +216,67 @@
* simply disposed off and removed from the internal map.</li>
* </ul>
*/
- public void configurationDeleted( final String pid )
+ public void configurationDeleted( final TargetedPID pid, TargetedPID factoryPid )
{
log( LogService.LOG_DEBUG, "ImmediateComponentHolder configuration deleted for pid {0}",
new Object[] {pid}, null);
// component to deconfigure or dispose of
- final SingleComponentManager icm;
+ final SingleComponentManager<S> icm;
boolean deconfigure = false;
synchronized ( m_components )
{
- // FELIX-2231: nothing to do any more, all components have been disposed off
- if (m_singleComponent == null)
- {
- return;
- }
-
- if ( pid.equals( getComponentMetadata().getConfigurationPid() ) )
- {
- // singleton configuration has pid equal to component name
- icm = m_singleComponent;
- deconfigure = true;
- }
- else
- {
- // remove the component configured with the deleted configuration
- icm = m_components.remove( pid );
- if ( icm == null )
- {
- // we already removed the component with the deleted configuration
- return;
- }
-
- // special casing if the single component is deconfigured
- if ( m_singleComponent == icm )
- {
-
- // if the single component is the last remaining, deconfig
- if ( m_components.isEmpty() )
- {
-
- // if the single component is the last remaining
- // deconfigure it
- deconfigure = true;
-
- }
- else
- {
-
- // replace the single component field with another
- // entry from the map
- m_singleComponent = m_components.values().iterator().next();
-
- }
- }
- }
+// // FELIX-2231: nothing to do any more, all components have been disposed off
+// if (m_singleComponent == null)
+// {
+// return;
+// }
+ if (factoryPid != null) {
+ checkFactoryPidIndex(factoryPid);
+ String servicePid = pid.getServicePid();
+ icm = m_components.remove(servicePid);
+ if (icm == null)
+ {
+ return;
+ }
+ m_factoryTargetedPids.remove(servicePid);
+ m_factoryChangeCount.remove(servicePid);
+ m_factoryConfigurations.remove(servicePid);
+ deconfigure = m_componentMetadata.isConfigurationOptional() && m_components.isEmpty();
+ if ( deconfigure )
+ {
+ m_singleComponent = icm;
+ }
+ if ( m_components.isEmpty() )
+ {
+ m_factoryPidIndex = null;
+ }
+ }
+ else
+ {
+ //singleton pid
+ int index = getSingletonPidIndex(pid);
+ m_targetedPids[index] = null;
+ m_changeCount[index] = null;
+ m_configurations[index] = null;
+ icm = m_singleComponent;
+ deconfigure = m_componentMetadata.isConfigurationOptional();
+ if ( !deconfigure )
+ {
+ m_singleComponent = null;
+ }
+ }
}
- // icm may be null if the last configuration deleted was the
- // single component's configuration. Otherwise the component
- // is not the "last" and has to be disposed off
- if ( deconfigure )
+ if ( icm != null )
{
- icm.reconfigure( null );
- }
- else
- {
- icm.dispose( ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED );
- }
+ if ( deconfigure ) {
+ icm.reconfigure(null);
+ } else {
+ icm.dispose(ComponentConstants.DEACTIVATION_REASON_CONFIGURATION_DELETED);
+ }
+ }
}
@@ -310,7 +300,7 @@
new Object[] {pid, props}, null);
// component to update or create
- final SingleComponentManager scm;
+ final SingleComponentManager<S> scm;
final String message;
Object[] notEnabledArguments = null;
boolean created = false;
@@ -320,34 +310,7 @@
synchronized (m_components) {
//Find or create the component manager, or return if not satisfied.
if (factoryPid != null) {
- int index = m_componentMetadata.getPidIndex(factoryPid);
- if (index == -1) {
- log(LogService.LOG_ERROR,
- "Unrecognized factory pid {0], expected one of {1}",
- new Object[] { factoryPid,
- m_componentMetadata.getConfigurationPid() },
- null);
- throw new IllegalArgumentException(
- "Unrecognized factory pid " + factoryPid);
- }
- if (m_configurations.get(index) != null) {
- log(LogService.LOG_ERROR,
- "factory pid {0], but this pids already supplied as a singleton: {1}",
- new Object[] { factoryPid, m_targetedPids }, null);
- throw new IllegalStateException(
- "Factory pid supplied after all non-factory configurations supplied "
- + factoryPid);
- }
- if (m_factoryPidIndex == null) {
- m_factoryPidIndex = index;
- } else if (index != m_factoryPidIndex) {
- log(LogService.LOG_ERROR,
- "factory pid {0] supplied for index {1}, but a factory pid previously supplied at index {2}",
- new Object[] { factoryPid, index, m_factoryPidIndex },
- null);
- throw new IllegalStateException(
- "Factory pid supplied at wrong index " + factoryPid);
- }
+ checkFactoryPidIndex(factoryPid);
m_factoryConfigurations.put(pid.getServicePid(), props);
m_factoryTargetedPids.put(pid.getServicePid(), factoryPid);
m_factoryChangeCount.put(pid.getServicePid(), changeCount);
@@ -369,27 +332,10 @@
} else {
//singleton pid
- int index = m_componentMetadata.getPidIndex(pid);
- if (index == -1) {
- log(LogService.LOG_ERROR,
- "Unrecognized pid {0], expected one of {1}",
- new Object[] { pid,
- m_componentMetadata.getConfigurationPid() },
- null);
- throw new IllegalArgumentException("Unrecognized pid "
- + pid);
- }
- if (m_factoryPidIndex != null && index == m_factoryPidIndex) {
- log(LogService.LOG_ERROR,
- "singleton pid {0] supplied, but matches an existing factory pid at index: {1}",
- new Object[] { pid, m_factoryPidIndex }, null);
- throw new IllegalStateException(
- "Singleton pid supplied matching a previous factory pid "
- + pid);
- }
- m_targetedPids.set(index, pid);
- m_changeCount.set(index, changeCount);
- m_configurations.set(index, props);
+ int index = getSingletonPidIndex(pid);
+ m_targetedPids[index] = pid;
+ m_changeCount[index] = changeCount;
+ m_configurations[index] = props;
if (isSatisfied()) {
if (m_singleComponent != null) {
scm = m_singleComponent;
@@ -403,17 +349,16 @@
}
}
- properties = new HashMap<String, Object>();
- copyTo(properties, m_componentMetadata.getProperties());
- for (int i = 0; i < m_configurations.size(); i++)
+ properties = new HashMap<String, Object>(m_componentMetadata.getProperties());
+ for (int i = 0; i < m_configurations.length; i++)
{
if ( m_factoryPidIndex != null && i == m_factoryPidIndex)
{
copyTo(properties, props);
}
- else if ( m_configurations.get(i) != null )
+ else if ( m_configurations[i] != null )
{
- copyTo(properties, m_configurations.get(i));
+ copyTo(properties, m_configurations[i]);
}
}
@@ -502,6 +447,60 @@
return created;
}
+ private int getSingletonPidIndex(TargetedPID pid) {
+ int index = m_componentMetadata.getPidIndex(pid);
+ if (index == -1) {
+ log(LogService.LOG_ERROR,
+ "Unrecognized pid {0], expected one of {1}",
+ new Object[] { pid,
+ m_componentMetadata.getConfigurationPid() },
+ null);
+ throw new IllegalArgumentException("Unrecognized pid "
+ + pid);
+ }
+ if (m_factoryPidIndex != null && index == m_factoryPidIndex) {
+ log(LogService.LOG_ERROR,
+ "singleton pid {0] supplied, but matches an existing factory pid at index: {1}",
+ new Object[] { pid, m_factoryPidIndex }, null);
+ throw new IllegalStateException(
+ "Singleton pid supplied matching a previous factory pid "
+ + pid);
+ }
+ return index;
+ }
+
+ //TODO update error messages so they make sense for deleting config too.
+ private void checkFactoryPidIndex(TargetedPID factoryPid) {
+ int index = m_componentMetadata.getPidIndex(factoryPid);
+ if (index == -1) {
+ log(LogService.LOG_ERROR,
+ "Unrecognized factory pid {0], expected one of {1}",
+ new Object[] { factoryPid,
+ m_componentMetadata.getConfigurationPid() },
+ null);
+ throw new IllegalArgumentException(
+ "Unrecognized factory pid " + factoryPid);
+ }
+ if (m_configurations[index] != null) {
+ log(LogService.LOG_ERROR,
+ "factory pid {0], but this pids already supplied as a singleton: {1}",
+ new Object[] { factoryPid, m_targetedPids }, null);
+ throw new IllegalStateException(
+ "Factory pid supplied after all non-factory configurations supplied "
+ + factoryPid);
+ }
+ if (m_factoryPidIndex == null) {
+ m_factoryPidIndex = index;
+ } else if (index != m_factoryPidIndex) {
+ log(LogService.LOG_ERROR,
+ "factory pid {0] supplied for index {1}, but a factory pid previously supplied at index {2}",
+ new Object[] { factoryPid, index, m_factoryPidIndex },
+ null);
+ throw new IllegalStateException(
+ "Factory pid supplied at wrong index " + factoryPid);
+ }
+ }
+
protected static void copyTo( Map<String, Object> target, Dictionary<String, ?> source )
{
@@ -522,10 +521,9 @@
{
return true;
}
- boolean satisfied = true;
for ( int i = 0; i < m_componentMetadata.getConfigurationPid().size(); i++)
{
- if ( m_configurations.get(i) != null)
+ if ( m_configurations[i] != null)
{
continue;
}
@@ -540,11 +538,12 @@
/**
* @param pid the Targeted PID we need the change count for
+ * @param targetedPid the targeted factory pid for a factory configuration or the pid for a singleton configuration
* @return pid for this service pid.
*/
- public long getChangeCount( TargetedPID pid)
+ public long getChangeCount( TargetedPID pid, TargetedPID targetedPid)
{
- int index = m_componentMetadata.getPidIndex(pid);
+ int index = m_componentMetadata.getPidIndex(targetedPid);
Long result;
if ( index == -1 )
{
@@ -556,13 +555,13 @@
}
else
{
- result = m_changeCount.get(index);
+ result = m_changeCount[index];
}
return result == null? -1: result;
}
- public List<? extends Component> getComponents()
+ public List<? extends ComponentManager<?>> getComponents()
{
synchronized ( m_components )
{
@@ -571,6 +570,10 @@
}
+ public boolean isEnabled() {
+ return m_enabled;
+ }
+
public void enableComponents( final boolean async )
{
List<SingleComponentManager<S>> cms;
@@ -619,21 +622,21 @@
{
cms = getComponentManagers( true );
}
- for ( SingleComponentManager cm : cms )
+ for ( SingleComponentManager<S> cm : cms )
{
cm.dispose( reason );
}
}
- public void disposed( SingleComponentManager component )
+ public void disposed( SingleComponentManager<S> component )
{
// ensure the component is removed from the components map
synchronized ( m_components )
{
if ( !m_components.isEmpty() )
{
- for ( Iterator vi = m_components.values().iterator(); vi.hasNext(); )
+ for ( Iterator<SingleComponentManager<S>> vi = m_components.values().iterator(); vi.hasNext(); )
{
if ( component == vi.next() )
{
@@ -643,20 +646,9 @@
}
}
- // if the component is the single component, we have to replace it
- // by another entry in the map
if ( component == m_singleComponent )
{
- if ( m_components.isEmpty() )
- {
- // now what ??
- // is it correct to create a new manager ???
- m_singleComponent = createComponentManager();
- }
- else
- {
- m_singleComponent = m_components.values().iterator().next();
- }
+ m_singleComponent = null;
}
}
}
@@ -681,7 +673,7 @@
return false;
}
- ConfigurableComponentHolder other = (ConfigurableComponentHolder) object;
+ ConfigurableComponentHolder<S> other = (ConfigurableComponentHolder<S>) object;
return m_activator == other.m_activator
&& getName().equals(other.getName());
}
@@ -774,7 +766,7 @@
int index = m_componentMetadata.getPidIndex(pid);
if (index != -1)
{
- return m_targetedPids.get(index);
+ return m_targetedPids[index];
}
return null;
}
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 f6081e6..8d59979 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
@@ -19,19 +19,13 @@
package org.apache.felix.scr.impl.config;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Hashtable;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import org.apache.felix.scr.impl.Activator;
import org.apache.felix.scr.impl.BundleComponentActivator;
@@ -58,7 +52,7 @@
ChangeCount cc = null;
try
{
- Configuration.class.getMethod( "getChangeCount", null );
+ Configuration.class.getMethod( "getChangeCount", (Class<?>[]) null );
cc = new R5ChangeCount();
}
catch ( SecurityException e )
@@ -78,14 +72,14 @@
private final ComponentRegistry m_registry;
// the service m_registration of the ConfigurationListener service
- private ServiceRegistration m_registration;
+ private ServiceRegistration<?> m_registration;
public ConfigurationSupport(final BundleContext bundleContext, final ComponentRegistry registry)
{
this.m_registry = registry;
// register as listener for configurations
- Dictionary props = new Hashtable();
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put(Constants.SERVICE_DESCRIPTION, "Declarative Services Configuration Support Listener");
props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
this.m_registration = bundleContext.registerService(new String[]
@@ -103,7 +97,7 @@
// ---------- BaseConfigurationSupport overwrites
- public boolean configureComponentHolder(final ComponentHolder holder)
+ public boolean configureComponentHolder(final ComponentHolder<?> holder)
{
// 112.7 configure unless configuration not required
@@ -246,7 +240,7 @@
// 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;
+ Collection<ComponentHolder<?>> holders;
if (factoryPid == null)
{
@@ -261,7 +255,7 @@
new Object[] {getEventType(event), pid, holders},
null);
- for ( ComponentHolder componentHolder: holders )
+ for ( ComponentHolder<?> componentHolder: holders )
{
if (!componentHolder.getComponentMetadata().isConfigurationIgnored())
{
@@ -269,7 +263,7 @@
case ConfigurationEvent.CM_DELETED:
if ( factoryPid != null || !configureComponentHolder( componentHolder ) )
{
- componentHolder.configurationDeleted( pid.getServicePid() );
+ componentHolder.configurationDeleted( pid, factoryPid );
}
break;
@@ -291,13 +285,13 @@
TargetedPID oldTargetedPID = componentHolder.getConfigurationTargetedPID(pid, factoryPid);
if ( factoryPid != null || targetedPid.equals(oldTargetedPID) || targetedPid.bindsStronger( oldTargetedPID ))
{
- final ConfigurationInfo configInfo = getConfigurationInfo( pid, componentHolder, bundleContext );
+ final ConfigurationInfo configInfo = getConfigurationInfo( pid, targetedPid, componentHolder, bundleContext );
if ( checkBundleLocation( configInfo.getBundleLocation(), bundleContext.getBundle() ) )
{
//If this is replacing a weaker targetedPID delete the old one.
if ( factoryPid == null && !targetedPid.equals(oldTargetedPID) && oldTargetedPID != null)
{
- componentHolder.configurationDeleted( pid.getServicePid() );
+ componentHolder.configurationDeleted( pid, factoryPid );
}
componentHolder.configurationUpdated( pid, factoryPid, configInfo.getProps(), configInfo.getChangeCount() );
}
@@ -326,7 +320,7 @@
{
//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, componentHolder, bundleContext );
+ final ConfigurationInfo configInfo = getConfigurationInfo( pid, targetedPid, componentHolder, bundleContext );
Activator.log(LogService.LOG_DEBUG, null, "LocationChanged event, same targetedPID {0}, location now {1}",
new Object[] {targetedPid, configInfo.getBundleLocation()},
null);
@@ -339,7 +333,7 @@
if (!checkBundleLocation( configInfo.getBundleLocation(), bundleContext.getBundle() ))
{
//no, delete it
- componentHolder.configurationDeleted( pid.getServicePid() );
+ componentHolder.configurationDeleted( pid, factoryPid );
//maybe there's another match
configureComponentHolder(componentHolder);
@@ -352,7 +346,7 @@
{
//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, componentHolder, bundleContext );
+ final ConfigurationInfo configInfo = getConfigurationInfo( pid, targetedPid, componentHolder, bundleContext );
Activator.log(LogService.LOG_DEBUG, null, "LocationChanged event, better targetedPID {0} compared to {1}, location now {2}",
new Object[] {targetedPid, oldTargetedPID, configInfo.getBundleLocation()},
null);
@@ -367,7 +361,7 @@
if ( oldTargetedPID != null )
{
//this is a better match, delete old before setting new
- componentHolder.configurationDeleted( pid.getServicePid() );
+ componentHolder.configurationDeleted( pid, factoryPid );
}
componentHolder.configurationUpdated( pid, factoryPid,
configInfo.getProps(), configInfo.getChangeCount() );
@@ -448,12 +442,13 @@
* are ungot. Extracting the info we need into "configInfo" solves this problem.
*
* @param pid TargetedPID for the desired configuration
+ * @param targetedPid the targeted factory pid for a factory configuration or the pid for a singleton configuration
* @param componentHolder ComponentHolder that holds the old change count (for r4 fake change counting)
* @param bundleContext BundleContext to get the CA from
* @return ConfigurationInfo object containing the info we need from the configuration.
*/
- private ConfigurationInfo getConfigurationInfo(final TargetedPID pid, ComponentHolder componentHolder,
- final BundleContext bundleContext)
+ private ConfigurationInfo getConfigurationInfo(final TargetedPID pid, TargetedPID targetedPid,
+ ComponentHolder<?> componentHolder, final BundleContext bundleContext)
{
final ServiceReference caRef = bundleContext
.getServiceReference(ComponentRegistry.CONFIGURATION_ADMIN);
@@ -471,7 +466,7 @@
final ConfigurationAdmin ca = ( ConfigurationAdmin ) cao;
final Configuration config = getConfiguration( ca, pid.getRawPid() );
return new ConfigurationInfo(config.getProperties(), config.getBundleLocation(),
- changeCounter.getChangeCount( config, true, componentHolder.getChangeCount( pid ) ) );
+ changeCounter.getChangeCount( config, true, componentHolder.getChangeCount( pid, targetedPid ) ) );
}
else
{
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/config/ReferenceManager.java b/scr/src/main/java/org/apache/felix/scr/impl/config/ReferenceManager.java
new file mode 100644
index 0000000..1bd963a
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/config/ReferenceManager.java
@@ -0,0 +1,30 @@
+package org.apache.felix.scr.impl.config;
+
+import java.util.List;
+
+import org.osgi.framework.ServiceReference;
+
+public interface ReferenceManager<S, T> {
+
+ /**
+ * Returns an array of <code>ServiceReference</code> instances of all
+ * services this instance is bound to or <code>null</code> if no services
+ * are actually bound.
+ */
+ List<ServiceReference<?>> getServiceReferences();
+
+ /**
+ * Returns the name of the service reference.
+ */
+ String getName();
+
+ /**
+ * Returns the target filter of this dependency as a string or
+ * <code>null</code> if this dependency has no target filter set.
+ *
+ * @return The target filter of this dependency or <code>null</code> if
+ * none is set.
+ */
+ String getTarget();
+
+}
\ No newline at end of file
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/ReadOnlyDictionary.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/ReadOnlyDictionary.java
index 03e97fb..f426cc6 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/ReadOnlyDictionary.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/ReadOnlyDictionary.java
@@ -45,7 +45,7 @@
* Creates a wrapper for the given delegate dictionary providing read
* only access to the data.
*/
- public ReadOnlyDictionary( final Dictionary<S, T> delegate )
+ public ReadOnlyDictionary( final Map<S, T> delegate )
{
if ( delegate instanceof Hashtable )
{
@@ -54,10 +54,9 @@
else
{
this.m_delegate = new Hashtable<S, T>();
- for ( Enumeration<S> ke = delegate.keys(); ke.hasMoreElements(); )
+ for ( Map.Entry<S, T> entry: delegate.entrySet() )
{
- S key = ke.nextElement();
- this.m_delegate.put( key, delegate.get( key ) );
+ this.m_delegate.put( entry.getKey(), entry.getValue() );
}
}
}
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 f952c51..0c551e2 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
@@ -24,26 +24,26 @@
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
-import org.apache.felix.scr.Component;
-import org.apache.felix.scr.Reference;
import org.apache.felix.scr.impl.Activator;
import org.apache.felix.scr.impl.BundleComponentActivator;
+import org.apache.felix.scr.impl.config.ComponentManager;
+import org.apache.felix.scr.impl.config.ReferenceManager;
import org.apache.felix.scr.impl.config.ScrConfiguration;
import org.apache.felix.scr.impl.helper.ComponentMethods;
import org.apache.felix.scr.impl.helper.MethodResult;
@@ -54,7 +54,6 @@
import org.apache.felix.scr.impl.metadata.ServiceMetadata.Scope;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
@@ -67,7 +66,7 @@
* implementation object's lifecycle.
*
*/
-public abstract class AbstractComponentManager<S> implements Component, SimpleLogger
+public abstract class AbstractComponentManager<S> implements SimpleLogger, ComponentManager<S>
{
//useful text for deactivation reason numbers
static final String[] REASONS = {"Unspecified",
@@ -388,20 +387,20 @@
//---------- Asynchronous frontend to state change methods ----------------
private static final AtomicLong taskCounter = new AtomicLong( );
- /**
- * Enables this component and - if satisfied - also activates it. If
- * enabling the component fails for any reason, the component ends up
- * disabled.
- * <p>
- * This method ignores the <i>enabled</i> flag of the component metadata
- * and just enables as requested.
- * <p>
- * This method enables and activates the component immediately.
- */
- public final void enable()
- {
- enable( true );
- }
+// /**
+// * Enables this component and - if satisfied - also activates it. If
+// * enabling the component fails for any reason, the component ends up
+// * disabled.
+// * <p>
+// * This method ignores the <i>enabled</i> flag of the component metadata
+// * and just enables as requested.
+// * <p>
+// * This method enables and activates the component immediately.
+// */
+// public final void enable()
+// {
+// enable( true );
+// }
public final void enable( final boolean async )
@@ -645,17 +644,6 @@
return m_componentMetadata.getFactoryIdentifier();
}
- public Reference[] getReferences()
- {
- if ( m_dependencyManagers != null && m_dependencyManagers.size() > 0 )
- {
- return (Reference[]) m_dependencyManagers.toArray(
- new Reference[m_dependencyManagers.size()] );
- }
-
- return null;
- }
-
public boolean isImmediate()
{
return m_componentMetadata.isImmediate();
@@ -782,7 +770,7 @@
null );
return;
}
- if ( !isEnabled())
+ if ( !isInternalEnabled())
{
log( LogService.LOG_DEBUG, "Component is not enabled; not activating component",
null );
@@ -829,7 +817,7 @@
null );
return;
}
- if ( !isEnabled() )
+ if ( !isInternalEnabled() )
{
log( LogService.LOG_DEBUG, "Component is not enabled; not activating component",
null );
@@ -1259,7 +1247,7 @@
return depMgrList;
}
- final void updateTargets(Dictionary<String, Object> properties)
+ final void updateTargets(Map<String, Object> properties)
{
for ( DependencyManager<S, ?> dm: getDependencyManagers() )
{
@@ -1312,6 +1300,11 @@
{
return m_dependencyManagers;
}
+
+ public List<? extends ReferenceManager<S, ?>> getReferenceManagers()
+ {
+ return m_dependencyManagers;
+ }
/**
* Returns an iterator over the {@link DependencyManager} objects
@@ -1327,11 +1320,11 @@
DependencyManager<S, ?> getDependencyManager(String name)
{
- for ( DependencyManager<S, ?> dm: getDependencyManagers() )
+ for ( ReferenceManager<S, ?> dm: getDependencyManagers() )
{
if ( name.equals(dm.getName()) )
{
- return dm;
+ return (DependencyManager<S, ?>) dm;
}
}
@@ -1360,7 +1353,10 @@
public abstract boolean hasConfiguration();
- public abstract Dictionary<String, Object> getProperties();
+ /* (non-Javadoc)
+ * @see org.apache.felix.scr.impl.manager.ComponentManager#getProperties()
+ */
+ public abstract Map<String, Object> getProperties();
public abstract void setServiceProperties( Dictionary<String, Object> serviceProperties );
@@ -1377,25 +1373,6 @@
/**
* Copies the properties from the <code>source</code> <code>Dictionary</code>
- * into the <code>target</code> <code>Dictionary</code>.
- *
- * @param target The <code>Dictionary</code> into which to copy the
- * properties. If <code>null</code> a new <code>Hashtable</code> is
- * created.
- * @param source The <code>Dictionary</code> providing the properties to
- * copy. If <code>null</code> or empty, nothing is copied.
- *
- * @return The <code>target</code> is returned, which may be empty if
- * <code>source</code> is <code>null</code> or empty and
- * <code>target</code> was <code>null</code>.
- */
- protected static Dictionary<String, Object> copyTo( Dictionary<String, Object> target, Dictionary<String, ?> source )
- {
- return copyTo( target, source, true );
- }
-
- /**
- * Copies the properties from the <code>source</code> <code>Dictionary</code>
* into the <code>target</code> <code>Dictionary</code> except for private
* properties (whose name has a leading dot) which are only copied if the
* <code>allProps</code> parameter is <code>true</code>.
@@ -1413,7 +1390,7 @@
* <code>target</code> was <code>null</code> or all properties are
* private and had not to be copied
*/
- protected static Dictionary<String, Object> copyTo( Dictionary<String, Object> target, final Dictionary<String, ?> source, final boolean allProps )
+ protected static Dictionary<String, Object> copyTo( Dictionary<String, Object> target, final Map<String, ?> source, final boolean allProps )
{
if ( target == null )
{
@@ -1422,10 +1399,65 @@
if ( source != null && !source.isEmpty() )
{
- for ( Enumeration ce = source.keys(); ce.hasMoreElements(); )
+ for ( Map.Entry<String, ?> entry: source.entrySet() )
{
// cast is save, because key must be a string as per the spec
- String key = ( String ) ce.nextElement();
+ String key = entry.getKey();
+ if ( allProps || key.charAt( 0 ) != '.' )
+ {
+ target.put( key, entry.getValue() );
+ }
+ }
+ }
+
+ return target;
+ }
+
+ /**
+ * Copies the properties from the <code>source</code> <code>Dictionary</code>
+ * into the <code>target</code> <code>Dictionary</code> except for private
+ * properties (whose name has a leading dot) which are only copied if the
+ * <code>allProps</code> parameter is <code>true</code>.
+ * @param source The <code>Dictionary</code> providing the properties to
+ * copy. If <code>null</code> or empty, nothing is copied.
+ * @param allProps Whether all properties (<code>true</code>) or only the
+ * public properties (<code>false</code>) are to be copied.
+ *
+ * @return The <code>target</code> is returned, which may be empty if
+ * <code>source</code> is <code>null</code> or empty and
+ * <code>target</code> was <code>null</code> or all properties are
+ * private and had not to be copied
+ */
+ protected static Map<String, Object> copyToMap( final Dictionary<String, ?> source, final boolean allProps )
+ {
+ Map<String, Object> target = new HashMap<String, Object>();
+
+ if ( source != null && !source.isEmpty() )
+ {
+ for ( Enumeration<String> ce = source.keys(); ce.hasMoreElements(); )
+ {
+ // cast is save, because key must be a string as per the spec
+ String key = ce.nextElement();
+ if ( allProps || key.charAt( 0 ) != '.' )
+ {
+ target.put( key, source.get( key ) );
+ }
+ }
+ }
+
+ return target;
+ }
+
+ protected static Dictionary<String, Object> copyToDictionary( final Dictionary<String, ?> source, final boolean allProps )
+ {
+ Hashtable<String, Object> target = new Hashtable<String, Object>();
+
+ if ( source != null && !source.isEmpty() )
+ {
+ for ( Enumeration<String> ce = source.keys(); ce.hasMoreElements(); )
+ {
+ // cast is save, because key must be a string as per the spec
+ String key = ce.nextElement();
if ( allProps || key.charAt( 0 ) != '.' )
{
target.put( key, source.get( key ) );
@@ -1445,29 +1477,32 @@
return m_componentMetadata;
}
+ /**
+ * TODO now returning bizarre mix of values!!
+ */
public int getState()
{
if (m_disposed)
{
- return Component.STATE_DISPOSED;
+ return STATE_DISPOSED;
}
if ( !m_internalEnabled)
{
- return Component.STATE_DISABLED;
+ return STATE_DISABLED;
}
if ( getServiceRegistration() == null && (getProvidedServices() != null || !hasInstance()))
{
- return Component.STATE_UNSATISFIED;
+ return STATE_UNSATISFIED;
}
if ( isFactory() && !m_factoryInstance )
{
- return Component.STATE_FACTORY;
+ return STATE_FACTORY;
}
if ( hasInstance() )
{
- return Component.STATE_ACTIVE;
+ return STATE_ACTIVE;
}
- return Component.STATE_REGISTERED;
+ return STATE_SATISFIED;
}
abstract boolean hasInstance();
@@ -1481,7 +1516,7 @@
}
}
- boolean isEnabled()
+ boolean isInternalEnabled()
{
return m_internalEnabled;
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
index 0ead123..9a1db51 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
@@ -89,8 +89,7 @@
public final Dictionary<String, Object> getProperties()
{
// 112.12.3.5 The Dictionary is read-only and cannot be modified
- Dictionary<String, Object> ctxProperties = m_componentManager.getProperties();
- return new ReadOnlyDictionary<String, Object>( ctxProperties );
+ return new ReadOnlyDictionary<String, Object>( m_componentManager.getProperties() );
}
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 9ad605e..0372077 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
@@ -32,6 +32,7 @@
import org.apache.felix.scr.impl.BundleComponentActivator;
import org.apache.felix.scr.impl.TargetedPID;
import org.apache.felix.scr.impl.config.ComponentHolder;
+import org.apache.felix.scr.impl.config.ComponentManager;
import org.apache.felix.scr.impl.helper.ComponentMethods;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
@@ -252,9 +253,13 @@
}
- public Dictionary<String, Object> getProperties()
+ /**
+ * For ComponentFactoryImpl, this is used only for updating targets on the dependency managers, so we don't need any other
+ * properties.
+ */
+ public Map<String, Object> getProperties()
{
- Dictionary<String, Object> props = getServiceProperties();
+ Map<String, Object> props = new HashMap<String, Object>();
// add target properties of references
List<ReferenceMetadata> depMetaData = getComponentMetadata().getDependencies();
@@ -332,7 +337,7 @@
//---------- ComponentHolder interface
- public void configurationDeleted( String pid )
+ public void configurationDeleted( TargetedPID pid, TargetedPID factoryPid )
{
m_targetedPID = null;
if ( pid.equals( getComponentMetadata().getConfigurationPid() ) )
@@ -451,18 +456,13 @@
}
- public synchronized long getChangeCount( TargetedPID pid)
+ public synchronized long getChangeCount( TargetedPID pid, TargetedPID targetedPid)
{
return m_changeCount;
}
- public List<? extends Component> getComponents()
- {
- return getComponentList();
- }
-
- protected List<AbstractComponentManager<S>> getComponentList()
+ public List<? extends ComponentManager<S>> getComponents()
{
List<AbstractComponentManager<S>> cms = new ArrayList<AbstractComponentManager<S>>( );
cms.add( this );
@@ -557,4 +557,9 @@
}
+ public boolean isEnabled() {
+ return isInternalEnabled();
+ }
+
+
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurationComponentFactoryImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurationComponentFactoryImpl.java
index b3270c5..82b1778 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurationComponentFactoryImpl.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurationComponentFactoryImpl.java
@@ -29,6 +29,7 @@
import org.apache.felix.scr.impl.BundleComponentActivator;
import org.apache.felix.scr.impl.TargetedPID;
import org.apache.felix.scr.impl.config.ComponentHolder;
+import org.apache.felix.scr.impl.config.ComponentManager;
import org.apache.felix.scr.impl.helper.ComponentMethods;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.osgi.framework.Constants;
@@ -117,11 +118,11 @@
//---------- ComponentHolder interface
- public void configurationDeleted( String pid )
+ public void configurationDeleted( TargetedPID pid, TargetedPID factoryPid )
{
if ( pid.equals( getComponentMetadata().getConfigurationPid() ) )
{
- super.configurationDeleted( pid );
+ super.configurationDeleted( pid, factoryPid );
}
else
{
@@ -189,9 +190,9 @@
}
- public List<? extends Component> getComponents()
+ public List<? extends ComponentManager<S>> getComponents()
{
- List<AbstractComponentManager<S>> cms = getComponentList();
+ List<AbstractComponentManager<S>> cms = (List<AbstractComponentManager<S>>) super.getComponents();
getComponentManagers( m_configuredServices, cms );
return cms;
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
index 061bfec..c359e4a 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
@@ -39,6 +39,7 @@
import org.apache.felix.scr.Component;
import org.apache.felix.scr.Reference;
import org.apache.felix.scr.impl.BundleComponentActivator;
+import org.apache.felix.scr.impl.config.ReferenceManager;
import org.apache.felix.scr.impl.helper.BindMethod;
import org.apache.felix.scr.impl.helper.BindMethods;
import org.apache.felix.scr.impl.helper.Coercions;
@@ -60,7 +61,7 @@
* declared by a single <code><reference></code element in component
* descriptor.
*/
-public class DependencyManager<S, T> implements Reference
+public class DependencyManager<S, T> implements ReferenceManager<S, T>
{
// mask of states ok to send events
private static final int STATE_MASK =
@@ -1303,37 +1304,21 @@
//---------- bound services maintenance -----------------------------------
- /**
- * Returns an array of <code>ServiceReference</code> instances of all
- * services this instance is bound to or <code>null</code> if no services
- * are actually bound.
- */
- public ServiceReference<T>[] getServiceReferences()
+ /* (non-Javadoc)
+ * @see org.apache.felix.scr.impl.manager.ReferenceManager#getServiceReferences()
+ */
+ public List<ServiceReference<?>> getServiceReferences()
{
Collection<RefPair<T>> bound = m_customizer.getRefs( new AtomicInteger( ) );
- if ( bound.isEmpty() )
- {
- return null;
- }
- ServiceReference<T>[] result = new ServiceReference[bound.size()];
- int i = 0;
+ List<ServiceReference<?>> result = new ArrayList<ServiceReference<?>>(bound.size());
for (RefPair<T> ref: bound)
{
- result[i++] = ref.getRef();
+ result.add(ref.getRef());
}
return result;
}
/**
- * a mistake, use getServiceReferences instead
- */
- @Deprecated
- public ServiceReference[] getBoundServiceReferences()
- {
- return getServiceReferences();
- }
-
- /**
* Returns the RefPair containing the given service reference and the bound service
* or <code>null</code> if this is instance is not currently bound to that
* service.
@@ -1424,9 +1409,9 @@
//---------- DependencyManager core ---------------------------------------
- /**
- * Returns the name of the service reference.
- */
+ /* (non-Javadoc)
+ * @see org.apache.felix.scr.impl.manager.ReferenceManager#getName()
+ */
public String getName()
{
return m_dependencyMetadata.getName();
@@ -1785,7 +1770,7 @@
* apply.</li>
* </ol>
*/
- boolean canUpdateDynamically( Dictionary<String, Object> properties )
+ boolean canUpdateDynamically( Map<String, Object> properties )
{
// 1. no target filter change
final String newTarget = ( String ) properties.get( m_dependencyMetadata.getTargetPropertyName() );
@@ -1845,14 +1830,14 @@
* @param properties The properties containing the optional target service
* filter property
*/
- void setTargetFilter( Dictionary<String, Object> properties )
+ void setTargetFilter( Map<String, Object> properties )
{
Integer minimumCardinality = getMinimumCardinality( properties );
setTargetFilter( ( String ) properties.get( m_dependencyMetadata.getTargetPropertyName() ),
minimumCardinality);
}
- private int getMinimumCardinality(Dictionary<String, Object> properties)
+ private int getMinimumCardinality(Map<String, Object> properties)
{
Integer minimumCardinality = null;
try
@@ -2043,13 +2028,9 @@
}
- /**
- * Returns the target filter of this dependency as a string or
- * <code>null</code> if this dependency has no target filter set.
- *
- * @return The target filter of this dependency or <code>null</code> if
- * none is set.
- */
+ /* (non-Javadoc)
+ * @see org.apache.felix.scr.impl.manager.ReferenceManager#getTarget()
+ */
public String getTarget()
{
return m_target;
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java b/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
index 1f76587..fadc1e5 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
@@ -22,6 +22,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
+import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
@@ -31,6 +32,8 @@
import org.apache.felix.scr.impl.BundleComponentActivator;
import org.apache.felix.scr.impl.TargetedPID;
import org.apache.felix.scr.impl.config.ComponentHolder;
+import org.apache.felix.scr.impl.config.ComponentManager;
+import org.apache.felix.scr.impl.config.ReferenceManager;
import org.apache.felix.scr.impl.helper.ActivateMethod.ActivatorParameter;
import org.apache.felix.scr.impl.helper.ComponentMethods;
import org.apache.felix.scr.impl.helper.MethodResult;
@@ -66,10 +69,10 @@
private Map<String, Object> m_configurationProperties;
// optional properties provided in the ComponentFactory.newInstance method
- private Dictionary<String, Object> m_factoryProperties;
+ private Map<String, Object> m_factoryProperties;
// the component properties, also used as service properties
- private Dictionary<String, Object> m_properties;
+ private Map<String, Object> m_properties;
// properties supplied ot ExtComponentContext.updateProperties
// null if properties are not to be overwritten
@@ -265,7 +268,7 @@
// 4. Bind the target services
- DependencyManager<S, ?> failedDm = null;
+ ReferenceManager<S, ?> failedDm = null;
for ( DependencyManager<S, ?> dm: getDependencyManagers())
{
if ( failedDm == null )
@@ -406,7 +409,7 @@
protected void setFactoryProperties( Dictionary<String, ?> dictionary )
{
- m_factoryProperties = copyTo( null, dictionary );
+ m_factoryProperties = copyToMap( dictionary, true );
}
@@ -437,9 +440,9 @@
* Method implements the Component Properties provisioning as described
* in 112.6, Component Properties.
*
- * @return a private Hashtable of component properties
+ * @return a private map of component properties
*/
- public Dictionary<String, Object> getProperties()
+ public Map<String, Object> getProperties()
{
if ( m_properties == null )
@@ -447,14 +450,14 @@
// 1. Merge all the config properties
- Hashtable<String, Object> props = new Hashtable<String, Object>();
+ Map<String, Object> props = new HashMap<String, Object>();
if ( m_configurationProperties != null )
{
props.putAll(m_configurationProperties);
}
if ( m_factoryProperties != null)
{
- copyTo(props, m_factoryProperties);
+ props.putAll(m_factoryProperties);
}
// 2. set component.name and component.id
@@ -475,7 +478,7 @@
}
else
{
- m_serviceProperties = copyTo( null, serviceProperties, false );
+ m_serviceProperties = copyToDictionary( serviceProperties, false );
// set component.name and component.id
m_serviceProperties.put( ComponentConstants.COMPONENT_NAME, getComponentMetadata().getName() );
m_serviceProperties.put( ComponentConstants.COMPONENT_ID, getId() );
@@ -679,7 +682,7 @@
// 3. check whether we can dynamically apply the configuration if
// any target filters influence the bound services
- final Dictionary<String, Object> props = getProperties();
+ final Map<String, Object> props = getProperties();
for ( DependencyManager dm: getDependencyManagers() )
{
if ( !dm.canUpdateDynamically( props ) )
@@ -867,7 +870,7 @@
private S getService()
{
//should be write locked
- if (!isEnabled())
+ if (!isInternalEnabled())
{
return null;
}
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 bbace44..8ff781c 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
@@ -23,10 +23,12 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
@@ -102,7 +104,7 @@
private List<String> m_configurationPid;
// Associated properties (0..*)
- private Dictionary<String, Object> m_properties = new Hashtable<String, Object>();
+ private Map<String, Object> m_properties = new HashMap<String, Object>();
// List of Property metadata - used while building the meta data
// while validating the properties contained in the PropertyMetadata
@@ -520,7 +522,11 @@
{
throw new IllegalStateException("not yet validated");
}
- return m_configurationPid == null? -1: m_configurationPid.indexOf(pid.getServicePid());
+ if (m_configurationPid == null )
+ {
+ throw new IllegalStateException( "Apparently trying to configure a component " + m_name + " without a configurationPid using " + pid);
+ }
+ return m_configurationPid.indexOf(pid.getServicePid());
}
/**
@@ -695,7 +701,7 @@
*
* @return the properties as a Dictionary
*/
- public Dictionary<String, Object> getProperties()
+ public Map<String, Object> getProperties()
{
return m_properties;
}
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java b/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java
new file mode 100644
index 0000000..163d525
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java
@@ -0,0 +1,207 @@
+package org.apache.felix.scr.impl.runtime;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.felix.scr.impl.ComponentRegistry;
+import org.apache.felix.scr.impl.config.ComponentHolder;
+import org.apache.felix.scr.impl.config.ComponentManager;
+import org.apache.felix.scr.impl.config.ReferenceManager;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
+import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.dto.BundleDTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+import org.osgi.service.component.runtime.ServiceComponentRuntime;
+import org.osgi.service.component.runtime.dto.BoundReferenceDTO;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
+import org.osgi.service.component.runtime.dto.ReferenceDTO;
+
+public class ServiceComponentRuntimeImpl implements ServiceComponentRuntime {
+
+ private static final String[] EMPTY = {};
+
+ private final BundleContext context;
+ private final ComponentRegistry componentRegistry;
+
+
+ public ServiceComponentRuntimeImpl(BundleContext context,
+ ComponentRegistry componentRegistry) {
+ this.context = context;
+ this.componentRegistry = componentRegistry;
+ }
+
+ public Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(
+ Bundle... bundles) {
+ List<ComponentHolder<?>> holders;
+ if (bundles == null || bundles.length == 0)
+ {
+ holders = componentRegistry.getComponentHolders();
+ }
+ else
+ {
+ holders = componentRegistry.getComponentHolders(bundles);
+ }
+
+ List<ComponentDescriptionDTO> result = new ArrayList<ComponentDescriptionDTO>(holders.size());
+ for (ComponentHolder<?> holder: holders)
+ {
+ result.add(holderToDescription(holder));
+ }
+ return result;
+ }
+
+ public ComponentDescriptionDTO getComponentDescriptionDTO(Bundle bundle,
+ String name) {
+ ComponentHolder<?> holder = componentRegistry.getComponentHolder(bundle, name);
+ return holderToDescription(holder);
+ }
+
+ public Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(
+ ComponentDescriptionDTO description) {
+ ComponentHolder<?> holder = getHolderFromDescription( description);
+ //Get a fully filled out valid description DTO
+ description = holderToDescription(holder);
+ List<? extends ComponentManager<?>> managers = holder.getComponents();
+ List<ComponentConfigurationDTO> result = new ArrayList<ComponentConfigurationDTO>(managers.size());
+ for (ComponentManager<?> manager: managers)
+ {
+ result.add(managerToConfiguration(manager, description));
+ }
+ return result;
+ }
+
+ public boolean isComponentEnabled(ComponentDescriptionDTO description) {
+ ComponentHolder<?> holder = getHolderFromDescription( description);
+ return holder.isEnabled();
+ }
+
+ public void enableComponent(ComponentDescriptionDTO description) {
+ ComponentHolder<?> holder = getHolderFromDescription( description);
+ holder.enableComponents(false); //synchronous
+ }
+
+ public void disableComponent(ComponentDescriptionDTO description) {
+ ComponentHolder<?> holder = getHolderFromDescription( description);
+ holder.disableComponents(false); //synchronous
+ }
+
+ private ComponentConfigurationDTO managerToConfiguration(
+ ComponentManager<?> manager, ComponentDescriptionDTO description) {
+ ComponentConfigurationDTO dto = new ComponentConfigurationDTO();
+ dto.boundReferences = refManagersToDTO(manager.getReferenceManagers());
+ dto.description = description;
+ dto.id = manager.getId();
+ dto.properties = new HashMap<String, Object>(manager.getProperties());//TODO deep copy?
+ dto.state = manager.getState();
+ return dto;
+ }
+
+ private BoundReferenceDTO[] refManagersToDTO(List<? extends ReferenceManager<?, ?>> referenceManagers) {
+ BoundReferenceDTO[] dtos = new BoundReferenceDTO[referenceManagers.size()];
+ for (ReferenceManager<?, ?> ref: referenceManagers)
+ {
+ BoundReferenceDTO dto = new BoundReferenceDTO();
+ dto.name = ref.getName();
+ dto.target = ref.getTarget();
+ List<ServiceReference<?>> serviceRefs = ref.getServiceReferences();
+ ServiceReferenceDTO[] srDTOs = new ServiceReferenceDTO[serviceRefs.size()];
+ int i = 0;
+ for (ServiceReference<?> serviceRef: serviceRefs)
+ {
+ srDTOs[i++] = serviceReferenceToDTO(serviceRef);
+ }
+ dto.serviceReferences = srDTOs;
+ }
+ return dtos;
+ }
+
+ private ServiceReferenceDTO serviceReferenceToDTO(
+ ServiceReference<?> serviceRef) {
+ ServiceReferenceDTO dto = new ServiceReferenceDTO();
+ dto.bundle = serviceRef.getBundle().getBundleId();
+ dto.id = (Long) serviceRef.getProperty("service.id"); //TODO use proper constant
+ //TODO service properties, using bundles
+ return dto;
+ }
+
+ private ComponentHolder getHolderFromDescription(
+ ComponentDescriptionDTO description) {
+ if (description.bundle == null)
+ {
+ throw new IllegalArgumentException("No bundle supplied in ComponentDescriptionDTO named " + description.name);
+ }
+ long bundleId = description.bundle.id;
+ Bundle b = context.getBundle(bundleId);
+ String name = description.name;
+ return componentRegistry.getComponentHolder(b, name);
+ }
+
+ private ComponentDescriptionDTO holderToDescription( ComponentHolder<?> holder )
+ {
+ ComponentDescriptionDTO dto = new ComponentDescriptionDTO();
+ ComponentMetadata m = holder.getComponentMetadata();
+ dto.activate = m.getActivate();
+ dto.bundle = bundleToDTO(holder.getActivator().getBundleContext());
+ dto.configurationPid = m.getConfigurationPid().toArray(new String[m.getConfigurationPid().size()]);
+ dto.configurationPolicy = m.getConfigurationPolicy();
+ dto.deactivate = m.getDeactivate();
+ dto.defaultEnabled = m.isEnabled();
+ dto.factory = m.getFactoryIdentifier();
+ dto.immediate = m.isImmediate();
+ dto.implementationClass = m.getImplementationClassName();
+ dto.modified = m.getModified();
+ dto.name = m.getName();
+ dto.properties = new HashMap<String, Object>(m.getProperties());// TODO deep copy of arrays
+ dto.references = refsToDTO(m.getDependencies());
+ dto.scope = m.getServiceMetadata() == null? null: m.getServiceMetadata().getScope().name();
+ dto.serviceInterfaces = m.getServiceMetadata() == null? EMPTY: m.getServiceMetadata().getProvides();
+ return dto;
+ }
+
+ private ReferenceDTO[] refsToDTO(List<ReferenceMetadata> dependencies) {
+ ReferenceDTO[] dtos = new ReferenceDTO[dependencies.size()];
+ int i = 0;
+ for (ReferenceMetadata r: dependencies)
+ {
+ ReferenceDTO dto = new ReferenceDTO();
+ dto.bind = r.getBind();
+ dto.cardinality = r.getCardinality();
+ dto.interfaceName = r.getInterface();
+ dto.name = r.getName();
+ dto.policy = r.getPolicy();
+ dto.policyOption = r.getPolicyOption();
+ dto.scope = r.getScope().name();
+ dto.target = r.getTarget();
+ dto.unbind = r.getUnbind();
+ dto.updated = r.getUpdated();
+ dtos[i] = dto;
+ }
+ return dtos;
+ }
+
+ private BundleDTO bundleToDTO(BundleContext bundleContext) {
+ if (bundleContext == null)
+ {
+ return null;
+ }
+ Bundle bundle = bundleContext.getBundle();
+ if (bundle == null)
+ {
+ return null;
+ }
+ BundleDTO b = new BundleDTO();
+ b.id = bundle.getBundleId();
+ b.lastModified = bundle.getLastModified();
+ b.state = bundle.getState();
+ b.symbolicName = bundle.getSymbolicName();
+ b.version = bundle.getVersion().toString();
+ return b;
+ }
+
+}
diff --git a/scr/src/main/java/org/osgi/dto/DTO.java b/scr/src/main/java/org/osgi/dto/DTO.java
new file mode 100644
index 0000000..acb9dd3
--- /dev/null
+++ b/scr/src/main/java/org/osgi/dto/DTO.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) OSGi Alliance (2012). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.dto;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Super type for Data Transfer Objects.
+ *
+ * All data transfer objects are easily serializable having only public fields
+ * of primitive types and their wrapper classes, Strings, and DTOs. List, Set,
+ * Map and array aggregates may also be used. The aggregates must only hold
+ * objects of the listed types or aggregates.
+ *
+ * @author $Id: 36dd2d0b9df1b8a6f67c74eeaad1cc9e20e19574 $
+ * @NotThreadSafe
+ */
+public abstract class DTO {
+
+ /**
+ * Return a string representation of this DTO suitable for use when
+ * debugging.
+ *
+ * <p>
+ * The format of the string representation is not specified and subject to
+ * change.
+ *
+ * @return A string representation of this DTO suitable for use when
+ * debugging.
+ */
+ @Override
+ public String toString() {
+ return appendValue(new StringBuilder(), new IdentityHashMap<Object, String>(), "#", this).toString();
+ }
+
+ /**
+ * Append the specified DTO's string representation to the specified
+ * StringBuilder.
+ *
+ * <p>
+ * This method handles circular DTO references.
+ *
+ * @param result StringBuilder to which the string representation is
+ * appended.
+ * @param objectRefs References to "seen" objects.
+ * @param refpath The reference path of the specified DTO.
+ * @param dto The DTO whose string representation is to be appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendDTO(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final DTO dto) {
+ result.append("{");
+ String delim = "";
+ for (Field field : dto.getClass().getFields()) {
+ if (Modifier.isStatic(field.getModifiers())) {
+ continue;
+ }
+ result.append(delim);
+ final String name = field.getName();
+ appendString(result, name);
+ result.append(":");
+ Object value = null;
+ try {
+ value = field.get(dto);
+ } catch (IllegalAccessException e) {
+ // use null value;
+ }
+ appendValue(result, objectRefs, refpath + "/" + name, value);
+ delim = ", ";
+ }
+ result.append("}");
+ return result;
+ }
+
+ /**
+ * Append the specified value's string representation to the specified
+ * StringBuilder.
+ *
+ * @param result StringBuilder to which the string representation is
+ * appended.
+ * @param objectRefs References to "seen" objects.
+ * @param refpath The reference path of the specified value.
+ * @param value The object whose string representation is to be appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendValue(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Object value) {
+ if (value == null) {
+ return result.append("null");
+ }
+ // Simple Java types
+ if (value instanceof String || value instanceof Character) {
+ return appendString(result, compress(value.toString()));
+ }
+ if (value instanceof Number || value instanceof Boolean) {
+ return result.append(value.toString());
+ }
+
+ // Complex types
+ final String path = objectRefs.get(value);
+ if (path != null) {
+ result.append("{\"$ref\":");
+ appendString(result, path);
+ result.append("}");
+ return result;
+ }
+ objectRefs.put(value, refpath);
+
+ if (value instanceof DTO) {
+ return appendDTO(result, objectRefs, refpath, (DTO) value);
+ }
+ if (value instanceof Map) {
+ return appendMap(result, objectRefs, refpath, (Map<?, ?>) value);
+ }
+ if (value instanceof List || value instanceof Set) {
+ return appendIterable(result, objectRefs, refpath, (Iterable<?>) value);
+ }
+ if (value.getClass().isArray()) {
+ return appendArray(result, objectRefs, refpath, value);
+ }
+ return appendString(result, compress(value.toString()));
+ }
+
+ /**
+ * Append the specified array's string representation to the specified
+ * StringBuilder.
+ *
+ * @param result StringBuilder to which the string representation is
+ * appended.
+ * @param objectRefs References to "seen" objects.
+ * @param refpath The reference path of the specified array.
+ * @param array The array whose string representation is to be appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendArray(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Object array) {
+ result.append("[");
+ final int length = Array.getLength(array);
+ for (int i = 0; i < length; i++) {
+ if (i > 0) {
+ result.append(",");
+ }
+ appendValue(result, objectRefs, refpath + "/" + i, Array.get(array, i));
+ }
+ result.append("]");
+ return result;
+ }
+
+ /**
+ * Append the specified iterable's string representation to the specified
+ * StringBuilder.
+ *
+ * @param result StringBuilder to which the string representation is
+ * appended.
+ * @param objectRefs References to "seen" objects.
+ * @param refpath The reference path of the specified list.
+ * @param iterable The iterable whose string representation is to be
+ * appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendIterable(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Iterable<?> iterable) {
+ result.append("[");
+ int i = 0;
+ for (Object item : iterable) {
+ if (i > 0) {
+ result.append(",");
+ }
+ appendValue(result, objectRefs, refpath + "/" + i, item);
+ i++;
+ }
+ result.append("]");
+ return result;
+ }
+
+ /**
+ * Append the specified map's string representation to the specified
+ * StringBuilder.
+ *
+ * @param result StringBuilder to which the string representation is
+ * appended.
+ * @param objectRefs References to "seen" objects.
+ * @param refpath The reference path of the specified map.
+ * @param map The map whose string representation is to be appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendMap(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Map<?, ?> map) {
+ result.append("{");
+ String delim = "";
+ for (Map.Entry<?, ?> entry : map.entrySet()) {
+ result.append(delim);
+ final String name = String.valueOf(entry.getKey());
+ appendString(result, name);
+ result.append(":");
+ final Object value = entry.getValue();
+ appendValue(result, objectRefs, refpath + "/" + name, value);
+ delim = ", ";
+ }
+ result.append("}");
+ return result;
+ }
+
+ /**
+ * Append the specified string to the specified StringBuilder.
+ *
+ * @param result StringBuilder to which the string is appended.
+ * @param string The string to be appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendString(final StringBuilder result, final CharSequence string) {
+ result.append("\"");
+ int i = result.length();
+ result.append(string);
+ while (i < result.length()) { // escape if necessary
+ char c = result.charAt(i);
+ if ((c == '"') || (c == '\\')) {
+ result.insert(i, '\\');
+ i = i + 2;
+ continue;
+ }
+ if (c < 0x20) {
+ result.insert(i + 1, Integer.toHexString(c | 0x10000));
+ result.replace(i, i + 2, "\\u");
+ i = i + 6;
+ continue;
+ }
+ i++;
+ }
+ result.append("\"");
+ return result;
+ }
+
+ /**
+ * Compress, in length, the specified string.
+ *
+ * @param in The string to potentially compress.
+ * @return The string compressed, if necessary.
+ */
+ private static CharSequence compress(final CharSequence in) {
+ final int length = in.length();
+ if (length <= 21) {
+ return in;
+ }
+ StringBuilder result = new StringBuilder(21);
+ result.append(in, 0, 9);
+ result.append("...");
+ result.append(in, length - 9, length);
+ return result;
+ }
+}
diff --git a/scr/src/main/java/org/osgi/dto/package-info.java b/scr/src/main/java/org/osgi/dto/package-info.java
new file mode 100644
index 0000000..c3010b3
--- /dev/null
+++ b/scr/src/main/java/org/osgi/dto/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2013). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * OSGi Data Transfer Object Package Version 1.0.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. This package has two types of
+ * users: the consumers that use the API in this package and the providers that
+ * implement the API in this package.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.dto; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.dto; version="[1.0,1.1)"}
+ *
+ * @author $Id: 1209bb5e60e6b6fc8239119a2dd4a2c15b9a40f2 $
+ */
+
+//@Version("1.0")
+package org.osgi.dto;
+
+//import org.osgi.annotation.versioning.Version;
+
diff --git a/scr/src/main/java/org/osgi/dto/packageinfo b/scr/src/main/java/org/osgi/dto/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/scr/src/main/java/org/osgi/dto/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/scr/src/main/java/org/osgi/framework/dto/BundleDTO.java b/scr/src/main/java/org/osgi/framework/dto/BundleDTO.java
new file mode 100644
index 0000000..6b83401
--- /dev/null
+++ b/scr/src/main/java/org/osgi/framework/dto/BundleDTO.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.dto;
+
+import org.osgi.dto.DTO;
+import org.osgi.framework.Bundle;
+
+/**
+ * Data Transfer Object for a Bundle.
+ *
+ * <p>
+ * A Bundle can be adapted to provide a {@code BundleDTO} for the Bundle.
+ *
+ * @author $Id: aa30709351d8fe70b19c9ea99456ebd15ecab7c3 $
+ * @NotThreadSafe
+ */
+public class BundleDTO extends DTO {
+ /**
+ * The bundle's unique identifier.
+ *
+ * @see Bundle#getBundleId()
+ */
+ public long id;
+
+ /**
+ * The time when the bundle was last modified.
+ *
+ * @see Bundle#getLastModified()
+ */
+ public long lastModified;
+
+ /**
+ * The bundle's state.
+ *
+ * @see Bundle#getState()
+ */
+ public int state;
+
+ /**
+ * The bundle's symbolic name.
+ *
+ * @see Bundle#getSymbolicName()
+ */
+ public String symbolicName;
+
+ /**
+ * The bundle's version.
+ *
+ * @see Bundle#getVersion()
+ */
+ public String version;
+}
diff --git a/scr/src/main/java/org/osgi/framework/dto/FrameworkDTO.java b/scr/src/main/java/org/osgi/framework/dto/FrameworkDTO.java
new file mode 100644
index 0000000..7b32f93
--- /dev/null
+++ b/scr/src/main/java/org/osgi/framework/dto/FrameworkDTO.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.dto;
+
+import java.util.List;
+import java.util.Map;
+import org.osgi.dto.DTO;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Data Transfer Object for a Framework.
+ *
+ * <p>
+ * The System Bundle can be adapted to provide a {@code FrameworkDTO} for the
+ * framework of the system bundle. A {@code FrameworkDTO} obtained from a
+ * framework will contain only the launch properties of the framework. These
+ * properties will not include the System properties.
+ *
+ * @author $Id: 7c525727cbe877e888b460cd14d8f9054f99ee0c $
+ * @NotThreadSafe
+ */
+public class FrameworkDTO extends DTO {
+ /**
+ * The bundles that are installed in the framework.
+ *
+ * @see BundleContext#getBundles()
+ */
+ public List<BundleDTO> bundles;
+
+ /**
+ * The launch properties of the framework.
+ *
+ * The value type must be a numerical type, Boolean, String, DTO or an array
+ * of any of the former.
+ *
+ * @see BundleContext#getProperty(String)
+ */
+ public Map<String, Object> properties;
+
+ /**
+ * The services that are registered in the framework.
+ *
+ * @see BundleContext#getServiceReferences(String, String)
+ */
+ public List<ServiceReferenceDTO> services;
+}
diff --git a/scr/src/main/java/org/osgi/framework/dto/ServiceReferenceDTO.java b/scr/src/main/java/org/osgi/framework/dto/ServiceReferenceDTO.java
new file mode 100644
index 0000000..d08e2e3
--- /dev/null
+++ b/scr/src/main/java/org/osgi/framework/dto/ServiceReferenceDTO.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.dto;
+
+import java.util.Map;
+import org.osgi.dto.DTO;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Data Transfer Object for a ServiceReference.
+ *
+ * <p>
+ * {@code ServiceReferenceDTO}s for all registered services can be obtained from
+ * a {@link FrameworkDTO}. An installed Bundle can be adapted to provide a
+ * {@code ServiceReferenceDTO[]} of the services registered by the Bundle. A
+ * {@code ServiceReferenceDTO} obtained from a framework must convert service
+ * property values which are not valid value types for DTOs to type
+ * {@code String} using {@code String.valueOf(Object)}.
+ *
+ * @author $Id: 2c70b84f28c41fb51c488cb03950a46188ea209f $
+ * @NotThreadSafe
+ */
+public class ServiceReferenceDTO extends DTO {
+ /**
+ * The id of the service.
+ *
+ * @see Constants#SERVICE_ID
+ */
+ public long id;
+
+ /**
+ * The id of the bundle that registered the service.
+ *
+ * @see ServiceReference#getBundle()
+ */
+ public long bundle;
+
+ /**
+ * The properties for the service.
+ *
+ * The value type must be a numerical type, Boolean, String, DTO or an array
+ * of any of the former.
+ *
+ * @see ServiceReference#getProperty(String)
+ */
+ public Map<String, Object> properties;
+
+ /**
+ * The ids of the bundles that are using the service.
+ *
+ * @see ServiceReference#getUsingBundles()
+ */
+ public long[] usingBundles;
+}
diff --git a/scr/src/main/java/org/osgi/framework/dto/package-info.java b/scr/src/main/java/org/osgi/framework/dto/package-info.java
new file mode 100644
index 0000000..5c0bffc
--- /dev/null
+++ b/scr/src/main/java/org/osgi/framework/dto/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * OSGi Data Transfer Object Framework Package Version 1.8.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. This package has two types of
+ * users: the consumers that use the API in this package and the providers that
+ * implement the API in this package.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.framework.dto; version="[1.8,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.framework.dto; version="[1.8,1.9)"}
+ *
+ * @author $Id: 2acfb6f1633e18f1ceedd27c04e70131cae4f293 $
+ */
+
+//@Version("1.8")
+package org.osgi.framework.dto;
+
+//import org.osgi.annotation.versioning.Version;
+
diff --git a/scr/src/main/java/org/osgi/framework/dto/packageinfo b/scr/src/main/java/org/osgi/framework/dto/packageinfo
new file mode 100644
index 0000000..ed9885d
--- /dev/null
+++ b/scr/src/main/java/org/osgi/framework/dto/packageinfo
@@ -0,0 +1 @@
+version 1.8
diff --git a/scr/src/main/java/org/osgi/service/component/runtime/ServiceComponentRuntime.java b/scr/src/main/java/org/osgi/service/component/runtime/ServiceComponentRuntime.java
new file mode 100755
index 0000000..45db87df
--- /dev/null
+++ b/scr/src/main/java/org/osgi/service/component/runtime/ServiceComponentRuntime.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime;
+
+import java.util.Collection;
+//import org.osgi.annotation.versioning.ProviderType;
+import org.osgi.framework.Bundle;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
+
+/**
+ * The {@code ServiceComponentRuntime} service represents the Declarative
+ * Services main controller also known as the Service Component Runtime or SCR
+ * for short. It provides access to the components managed by the Service
+ * Component Runtime.
+ *
+ * <p>
+ * This service differentiates between a {@link ComponentDescriptionDTO} and a
+ * {@link ComponentConfigurationDTO}. A {@link ComponentDescriptionDTO} is a
+ * representation of a declared component description. A
+ * {@link ComponentConfigurationDTO} is a representation of an actual instance of a
+ * declared component description parameterized by component properties.
+ * <p>
+ *
+ * Access to this service requires the
+ * {@code ServicePermission[ServiceComponentRuntime, GET]} permission. It is
+ * intended that only administrative bundles should be granted this permission
+ * to limit access to the potentially intrusive methods provided by this
+ * service.
+ *
+ * @ThreadSafe
+ * @since 1.3
+ * @author $Id: 0b736eb18ed9ae337ef04765d1c006049a246c56 $
+ */
+//@ProviderType
+public interface ServiceComponentRuntime {
+
+ /**
+ * Returns the component descriptions declared by the specified active
+ * bundles.
+ *
+ * <p>
+ * Only component descriptions from active bundles are returned. If the
+ * specified bundles have no declared components or are not active, an empty
+ * collection is returned.
+ *
+ * @param bundles The bundles whose declared component descriptions are to
+ * be returned. Specifying no bundles, or the equivalent of an empty
+ * {@code Bundle} array, will return the declared component
+ * descriptions from all active bundles.
+ * @return The declared component descriptions of the specified active
+ * {@code bundles}. An empty collection is returned if there are no
+ * component descriptions for the specified active bundles.
+ */
+ Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(Bundle... bundles);
+
+ /**
+ * Returns the {@link ComponentDescriptionDTO} declared with the specified name
+ * by the specified bundle.
+ *
+ * <p>
+ * Only component descriptions from active bundles are returned.
+ * {@code null} if no such component is declared by the given {@code bundle}
+ * or the bundle is not active.
+ *
+ * @param bundle The bundle declaring the component description. Must not be
+ * {@code null}.
+ * @param name The name of the component description. Must not be
+ * {@code null}.
+ * @return The declared component description or {@code null} if the
+ * specified bundle is not active or does not declare a component
+ * description with the specified name.
+ */
+ ComponentDescriptionDTO getComponentDescriptionDTO(Bundle bundle, String name);
+
+ /**
+ * Returns the component configurations for the specified component
+ * description.
+ *
+ * @param description The component description. Must not be {@code null}.
+ * @return A collection containing a snapshot of the current component
+ * configurations for the specified component description. An empty
+ * collection is returned if there are none.
+ */
+ Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(ComponentDescriptionDTO description);
+
+ /**
+ * Returns whether the specified component description is currently enabled.
+ *
+ * <p>
+ * The enabled state of a component description is initially set by the
+ * {@link ComponentDescriptionDTO#defaultEnabled enabled} attribute of the
+ * component description.
+ *
+ * @param description The component description. Must not be {@code null}.
+ * @return {@code true} if the specified component description is currently
+ * enabled. Otherwise, {@code false}.
+ * @see #enableComponent(ComponentDescriptionDTO)
+ * @see #disableComponent(ComponentDescriptionDTO)
+ * @see ComponentContext#disableComponent(String)
+ * @see ComponentContext#enableComponent(String)
+ */
+ boolean isComponentEnabled(ComponentDescriptionDTO description);
+
+ /**
+ * Enables the specified component description.
+ *
+ * <p>
+ * If the specified component description is currently enabled, this method
+ * has no effect.
+ *
+ * @param description The component description to enable. Must not be
+ * {@code null}.
+ * @see #isComponentEnabled(ComponentDescriptionDTO)
+ */
+ void enableComponent(ComponentDescriptionDTO description);
+
+ /**
+ * Disables the specified component description.
+ *
+ * <p>
+ * If the specified component description is currently disabled, this method
+ * has no effect.
+ *
+ * @param description The component description to disable. Must not be
+ * {@code null}.
+ * @see #isComponentEnabled(ComponentDescriptionDTO)
+ */
+ void disableComponent(ComponentDescriptionDTO description);
+}
diff --git a/scr/src/main/java/org/osgi/service/component/runtime/dto/BoundReferenceDTO.java b/scr/src/main/java/org/osgi/service/component/runtime/dto/BoundReferenceDTO.java
new file mode 100755
index 0000000..b843280
--- /dev/null
+++ b/scr/src/main/java/org/osgi/service/component/runtime/dto/BoundReferenceDTO.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime.dto;
+
+import org.osgi.dto.DTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+
+/**
+ * A representation of a bound reference to a service.
+ *
+ * @since 1.3
+ * @NotThreadSafe
+ * @author $Id: 1ba28863312f0c0784e4a5596f991a6a6a68c147 $
+ */
+public class BoundReferenceDTO extends DTO {
+ /**
+ * The name of the declared reference.
+ *
+ * <p>
+ * This is declared in the {@code name} attribute of the {@code reference}
+ * element of the component description.
+ *
+ * @see ComponentDescriptionDTO#name
+ */
+ public String name;
+
+ /**
+ * The target property of the bound reference.
+ *
+ * <p>
+ * This is the value of the {@link ComponentConfigurationDTO#properties
+ * component property} whose name is the concatenation of the
+ * {@link ReferenceDTO#name declared reference name} and
+ * ".target". This will be {@code null} if no target property is
+ * set for the reference.
+ */
+ public String target;
+
+ /**
+ * The bound services.
+ *
+ * <p>
+ * Each {@link ServiceReferenceDTO} in the array represents a service bound
+ * to the component configuration.
+ */
+ public ServiceReferenceDTO[] serviceReferences;
+}
diff --git a/scr/src/main/java/org/osgi/service/component/runtime/dto/ComponentConfigurationDTO.java b/scr/src/main/java/org/osgi/service/component/runtime/dto/ComponentConfigurationDTO.java
new file mode 100755
index 0000000..fbed36d
--- /dev/null
+++ b/scr/src/main/java/org/osgi/service/component/runtime/dto/ComponentConfigurationDTO.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime.dto;
+
+import java.util.Map;
+import org.osgi.dto.DTO;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * A representation of an actual instance of a declared component description
+ * parameterized by component properties.
+ *
+ * @since 1.3
+ * @NotThreadSafe
+ * @author $Id: b3f49d694f497e55dc7ffed0e7d910fb3bab83da $
+ */
+public class ComponentConfigurationDTO extends DTO {
+ /**
+ * The component configuration is unsatisfied.
+ *
+ * <p>
+ * This is the initial state of a component configuration. When the
+ * component configuration becomes satisfied it enters the
+ * {@link #SATISFIED} state.
+ */
+ public static final int UNSATISFIED = 1;
+
+ /**
+ * The component configuration is satisfied.
+ *
+ * <p>
+ * Any {@link ComponentDescriptionDTO#serviceInterfaces services} declared by
+ * the component description are registered.
+ *
+ * If the component configuration becomes unsatisfied for any reason, any
+ * declared services must be unregistered and the component configuration
+ * returns to the {@link #UNSATISFIED} state.
+ */
+ public static final int SATISFIED = 2;
+
+ /**
+ * The component configuration is active.
+ *
+ * <p>
+ * This is the normal operational state of a component configuration. The
+ * component configuration will move to the {@link #SATISFIED} state when it
+ * is deactivated.
+ */
+ public static final int ACTIVE = 4;
+
+ /**
+ * The representation of the component configuration's component
+ * description.
+ */
+ public ComponentDescriptionDTO description;
+
+ /**
+ * The current state of the component configuration.
+ *
+ * <p>
+ * This is one of {@link #UNSATISFIED}, {@link #SATISFIED} or
+ * {@link #ACTIVE}.
+ */
+ public int state;
+
+ /**
+ * The component properties for the component configuration.
+ *
+ * @see ComponentContext#getProperties()
+ */
+ public Map<String, Object> properties;
+
+ /**
+ * The currently bound references.
+ *
+ * <p>
+ * Each {@link BoundReferenceDTO} in the array represents a service bound to a
+ * reference of the component configuration. The array will be empty if the
+ * component configuration has no bound references.
+ */
+ public BoundReferenceDTO[] boundReferences;
+
+ /**
+ * The id of the component description.
+ *
+ * <p>
+ * The id is a non-persistent, unique value assigned at runtime. The id is
+ * also available as the {@code component.id} component property.
+ */
+ public long id;
+}
diff --git a/scr/src/main/java/org/osgi/service/component/runtime/dto/ComponentDescriptionDTO.java b/scr/src/main/java/org/osgi/service/component/runtime/dto/ComponentDescriptionDTO.java
new file mode 100755
index 0000000..986d463
--- /dev/null
+++ b/scr/src/main/java/org/osgi/service/component/runtime/dto/ComponentDescriptionDTO.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime.dto;
+
+import java.util.Map;
+import org.osgi.dto.DTO;
+import org.osgi.framework.dto.BundleDTO;
+
+/**
+ * A representation of a declared component description.
+ *
+ * @since 1.3
+ * @NotThreadSafe
+ * @author $Id: f0bf3f3036179db049645595e631489455affe8a $
+ */
+public class ComponentDescriptionDTO extends DTO {
+ /**
+ * The name of the component.
+ *
+ * <p>
+ * This is declared in the {@code name} attribute of the {@code component}
+ * element. This will be the default name if the component description does
+ * not declare a name.
+ */
+ public String name;
+
+ /**
+ * The bundle declaring the component description.
+ */
+ public BundleDTO bundle;
+
+ /**
+ * The component factory name.
+ *
+ * <p>
+ * This is declared in the {@code factory} attribute of the
+ * {@code component} element. This will be {@code null} if the component
+ * description is not declared as a component factory.
+ */
+ public String factory;
+
+ /**
+ * The service scope.
+ *
+ * <p>
+ * This is declared in the {@code scope} attribute of the {@code service}
+ * element.
+ */
+ public String scope;
+
+ /**
+ * The fully qualified name of the implementation class.
+ *
+ * <p>
+ * This is declared in the {@code class} attribute of the
+ * {@code implementation} element.
+ */
+ public String implementationClass;
+
+ /**
+ * The initial enabled state.
+ *
+ * <p>
+ * This is declared in the {@code enabled} attribute of the
+ * {@code component} element.
+ */
+ public boolean defaultEnabled;
+
+ /**
+ * The immediate state.
+ *
+ * <p>
+ * This is declared in the {@code immediate} attribute of the
+ * {@code component} element.
+ */
+ public boolean immediate;
+
+ /**
+ * The fully qualified names of the service interfaces.
+ *
+ * <p>
+ * These are declared in the {@code interface} attribute of the
+ * {@code provide} elements. The array will be empty if the component
+ * description does not declare any service interfaces.
+ */
+ public String[] serviceInterfaces;
+
+ /**
+ * The declared component properties.
+ *
+ * <p>
+ * These are declared in the {@code property} and {@code properties}
+ * elements.
+ */
+ public Map<String, Object> properties;
+
+ /**
+ * The referenced services.
+ *
+ * <p>
+ * These are declared in the {@code reference} elements. The array will be
+ * empty if the component description does not declare references to any
+ * services.
+ */
+ public ReferenceDTO[] references;
+
+ /**
+ * The name of the activate method.
+ *
+ * <p>
+ * This is declared in the {@code activate} attribute of the
+ * {@code component} element. This will be {@code null} if the component
+ * description does not declare an activate method name.
+ */
+ public String activate;
+
+ /**
+ * The name of the deactivate method.
+ *
+ * <p>
+ * This is declared in the {@code deactivate} attribute of the
+ * {@code component} element. This will be {@code null} if the component
+ * description does not declare a deactivate method name.
+ */
+ public String deactivate;
+
+ /**
+ * The name of the modified method.
+ *
+ * <p>
+ * This is declared in the {@code modified} attribute of the
+ * {@code component} element. This will be {@code null} if the component
+ * description does not declare a modified method name.
+ */
+ public String modified;
+
+ /**
+ * The configuration policy.
+ *
+ * <p>
+ * This is declared in the {@code configuration-policy} attribute of the
+ * {@code component} element. This will be the default configuration policy
+ * if the component description does not declare a configuration policy.
+ */
+ public String configurationPolicy;
+
+ /**
+ * The configuration pid.
+ *
+ * <p>
+ * This is declared in the {@code configuration-pid} attribute of the
+ * {@code component} element. This will be the default configuration pid if
+ * the component description does not declare a configuration pid.
+ */
+ public String[] configurationPid;
+
+}
diff --git a/scr/src/main/java/org/osgi/service/component/runtime/dto/ReferenceDTO.java b/scr/src/main/java/org/osgi/service/component/runtime/dto/ReferenceDTO.java
new file mode 100755
index 0000000..33fec8b
--- /dev/null
+++ b/scr/src/main/java/org/osgi/service/component/runtime/dto/ReferenceDTO.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) OSGi Alliance (2013, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.service.component.runtime.dto;
+
+import org.osgi.dto.DTO;
+
+/**
+ * A representation of a declared reference to a service.
+ *
+ * @since 1.3
+ * @NotThreadSafe
+ * @author $Id: 2fc8a3deac2ece6b9fff4878dbe3f082faadd5f8 $
+ */
+public class ReferenceDTO extends DTO {
+ /**
+ * The name of the reference.
+ *
+ * <p>
+ * This is declared in the {@code name} attribute of the {@code reference}
+ * element. This will be the default name if the component description does
+ * not declare a name for the reference.
+ */
+ public String name;
+
+ /**
+ * The service interface of the reference.
+ *
+ * <p>
+ * This is declared in the {@code interface} attribute of the
+ * {@code reference} element.
+ */
+ public String interfaceName;
+
+ /**
+ * The cardinality of the reference.
+ *
+ * <p>
+ * This is declared in the {@code cardinality} attribute of the
+ * {@code reference} element. This will be the default cardinality if the
+ * component description does not declare a cardinality for the reference.
+ */
+ public String cardinality;
+
+ /**
+ * The policy of the reference.
+ *
+ * <p>
+ * This is declared in the {@code policy} attribute of the {@code reference}
+ * element. This will be the default policy if the component description
+ * does not declare a policy for the reference.
+ */
+ public String policy;
+
+ /**
+ * The policy option of the reference.
+ *
+ * <p>
+ * This is declared in the {@code policy-option} attribute of the
+ * {@code reference} element. This will be the default policy option if the
+ * component description does not declare a policy option for the reference.
+ */
+ public String policyOption;
+
+ /**
+ * The target of the reference.
+ *
+ * <p>
+ * This is declared in the {@code target} attribute of the {@code reference}
+ * element. This will be {@code null} if the component description does not
+ * declare a target for the reference.
+ */
+ public String target;
+
+ /**
+ * The name of the bind method of the reference.
+ *
+ * <p>
+ * This is declared in the {@code bind} attribute of the {@code reference}
+ * element. This will be {@code null} if the component description does not
+ * declare a bind method for the reference.
+ */
+ public String bind;
+
+ /**
+ * The name of the unbind method of the reference.
+ *
+ * <p>
+ * This is declared in the {@code unbind} attribute of the {@code reference}
+ * element. This will be {@code null} if the component description does not
+ * declare an unbind method for the reference.
+ */
+ public String unbind;
+
+ /**
+ * The name of the updated method of the reference.
+ *
+ * <p>
+ * This is declared in the {@code updated} attribute of the
+ * {@code reference} element. This will be {@code null} if the component
+ * description does not declare an updated method for the reference.
+ */
+ public String updated;
+
+ /**
+ * The scope of the reference.
+ *
+ * <p>
+ * This is declared in the {@code scope} attribute of the {@code reference}
+ * element. This will be the default scope if the component description does
+ * not declare a scope for the reference.
+ */
+ public String scope;
+}
diff --git a/scr/src/main/java/org/osgi/service/component/runtime/dto/package-info.java b/scr/src/main/java/org/osgi/service/component/runtime/dto/package-info.java
new file mode 100644
index 0000000..bc806dd
--- /dev/null
+++ b/scr/src/main/java/org/osgi/service/component/runtime/dto/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service Component Runtime Data Transfer Objects Package Version 1.3.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. This package has two types of
+ * users: the consumers that use the API in this package and the providers that
+ * implement the API in this package.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.component.runtime.dto; version="[1.3,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.component.runtime.dto; version="[1.3,1.4)"}
+ *
+ * @author $Id: d7d82da09d67a3ce4274ad8554966c1952a2b4de $
+ */
+
+//@Version("1.3")
+package org.osgi.service.component.runtime.dto;
+
+//import org.osgi.annotation.versioning.Version;
+
diff --git a/scr/src/main/java/org/osgi/service/component/runtime/dto/packageinfo b/scr/src/main/java/org/osgi/service/component/runtime/dto/packageinfo
new file mode 100644
index 0000000..0117a56
--- /dev/null
+++ b/scr/src/main/java/org/osgi/service/component/runtime/dto/packageinfo
@@ -0,0 +1 @@
+version 1.3
diff --git a/scr/src/main/java/org/osgi/service/component/runtime/package-info.java b/scr/src/main/java/org/osgi/service/component/runtime/package-info.java
new file mode 100644
index 0000000..55a20c1
--- /dev/null
+++ b/scr/src/main/java/org/osgi/service/component/runtime/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2013). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service Component Runtime Package Version 1.3.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. This package has two types of
+ * users: the consumers that use the API in this package and the providers that
+ * implement the API in this package.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.component.runtime; version="[1.3,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.component.runtime; version="[1.3,1.4)"}
+ *
+ * @author $Id: 3d4fa42ce33a4682cbaeee3f094b558e6ea6080f $
+ */
+
+//@Version("1.3")
+package org.osgi.service.component.runtime;
+
+//import org.osgi.annotation.versioning.Version;
+
diff --git a/scr/src/main/java/org/osgi/service/component/runtime/packageinfo b/scr/src/main/java/org/osgi/service/component/runtime/packageinfo
new file mode 100644
index 0000000..0117a56
--- /dev/null
+++ b/scr/src/main/java/org/osgi/service/component/runtime/packageinfo
@@ -0,0 +1 @@
+version 1.3
diff --git a/scr/src/test/java/org/apache/felix/scr/impl/manager/AbstractComponentManagerTest.java b/scr/src/test/java/org/apache/felix/scr/impl/manager/AbstractComponentManagerTest.java
index 5d34b99..3733c22 100644
--- a/scr/src/test/java/org/apache/felix/scr/impl/manager/AbstractComponentManagerTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/impl/manager/AbstractComponentManagerTest.java
@@ -19,6 +19,8 @@
package org.apache.felix.scr.impl.manager;
import java.util.Hashtable;
+import java.util.Map;
+
import junit.framework.TestCase;
public class AbstractComponentManagerTest extends TestCase
@@ -30,7 +32,7 @@
ht.put( "p1", "v1" );
ht.put( "p.2", "v2" );
ht.put( ".p3", "v3" );
- final Hashtable dict = (Hashtable) AbstractComponentManager.copyTo( null, ht, true );
+ final Map dict = AbstractComponentManager.copyToMap( ht, true );
assertNotNull( "Copy result is not null", dict );
assertEquals( "Number of items", 3, dict.size() );
assertEquals( "Value for key p1", "v1", dict.get( "p1" ) );
@@ -44,7 +46,7 @@
ht.put( "p1", "v1" );
ht.put( "p.2", "v2" );
ht.put( ".p3", "v3" );
- final Hashtable dict = (Hashtable) AbstractComponentManager.copyTo( null, ht, false );
+ final Map dict = AbstractComponentManager.copyToMap( ht, false );
assertNotNull( "Copy result is not null", dict );
assertEquals( "Number of items", 2, dict.size() );
assertEquals( "Value for key p1", "v1", dict.get( "p1" ) );