FELIX-4785 : Incompatible SCR API

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1657502 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/bnd.bnd b/scr/bnd.bnd
index d618109..353ec6b 100644
--- a/scr/bnd.bnd
+++ b/scr/bnd.bnd
@@ -10,7 +10,7 @@
                    uses:="org.osgi.service.component";\
                    version:Version="1.3"
 
-Export-Package: org.apache.felix.scr;version=2.0, \
+Export-Package: org.apache.felix.scr;version=1.8.1, \
  org.apache.felix.scr.component;version=1.1.0;mandatory:="status"; status="provisional", \
  org.osgi.service.component;version=1.3;-split-package:=first, \
  org.osgi.service.component.runtime.*;version=1.3, \
diff --git a/scr/src/main/java/org/apache/felix/scr/Component.java b/scr/src/main/java/org/apache/felix/scr/Component.java
new file mode 100644
index 0000000..eb4bc23
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/Component.java
@@ -0,0 +1,403 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.felix.scr;
+
+
+import java.util.Dictionary;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.component.ComponentInstance;
+
+
+/**
+ * The <code>Component</code> interface represents a single component managed
+ * by the Service Component Runtime. Management agents may access the Component
+ * instances through the {@link ScrService}.
+ *
+ * @deprecated Use the ServiceComponentRuntime service.
+ */
+@Deprecated
+public interface Component
+{
+
+    /**
+     * The Component has just been created and is still disabled or it has
+     * been disabled by calling the {@link #disable()} method (value is 1).
+     */
+    static final int STATE_DISABLED = 1;
+
+    /**
+     * The Component is being enabled (value is 512). After the component has
+     * been enabled it enters the {@link #STATE_UNSATISFIED} state.
+     * @since 1.2
+     * @deprecated since 1.8.0
+     */
+    @Deprecated
+    static final int STATE_ENABLING = 512;
+
+    /**
+     * The Component has been enabled and is now going to be activated (value
+     * is 2).
+     * @deprecated as of version 1.2 the enabled state is collapsed into the
+     *      {@link #STATE_UNSATISFIED} state. This status code is never returned
+     *      from the {@link #getState()} method.
+     */
+    @Deprecated
+    static final int STATE_ENABLED = 2;
+
+    /**
+     * The Component activation failed because any dependency is not satisfied
+     * (value is 4).
+     */
+    static final int STATE_UNSATISFIED = 4;
+
+    /**
+     * The Component is currently being activated either because it has been
+     * enabled or because any dependency which was previously unsatisfied has
+     * become satisfied (value is 8).
+     * @deprecated since 1.8.0 transient states are no longer used
+     */
+    @Deprecated
+    static final int STATE_ACTIVATING = 8;
+
+    /**
+     * The Component has successfully been activated and is fully functional
+     * (value is 16). This is the state of immediate components after
+     * successful activation. Delayed and Service Factory Components enter
+     * this state when the service instance has actually been instantiated because
+     * the service has been acquired.
+     */
+    static final int STATE_ACTIVE = 16;
+
+    /**
+     * The Component has successfully been activated but is a Delayed or Service
+     * Factory Component pending instantiation on first use (value is 32).
+     */
+    static final int STATE_REGISTERED = 32;
+
+    /**
+     * The Component is a Component Factory ready to create Component instances
+     * with the <code>ComponentFactory.newInstance(Dictionary)</code> method
+     * or (if enabled with the <code>ds.factory.enabled</code> configuration) to
+     * manage Component instances from configuration data received from the
+     * Configuration Admin Service (value is 64).
+     */
+    static final int STATE_FACTORY = 64;
+
+    /**
+     * The Component is being deactivated either because it is being disabled
+     * or because a dependency is not satisfied any more (value is 128). After
+     * deactivation the Component enters the {@link #STATE_UNSATISFIED} state.
+     * @deprecated since 1.8.0 transient states are no longer used
+     */
+    @Deprecated
+    static final int STATE_DEACTIVATING = 128;
+
+    /**
+     * The Component is being disabled (value is 1024). After the component has
+     * been disabled it enters the {@link #STATE_DISABLED} state.
+     * @since 1.2
+     * @deprecated since 1.8.0 transient states are no longer used
+     */
+    @Deprecated
+    static final int STATE_DISABLING = 1024;
+
+    /**
+     * The Component is being disposed off (value is 2048). After the component
+     * has been disposed off it enters the {@link #STATE_DESTROYED} state.
+     * @since 1.2
+     * @deprecated since 1.8.0 transient states are no longer used
+     */
+    @Deprecated
+    static final int STATE_DISPOSING = 2048;
+
+    /**
+     * The Component has been destroyed and cannot be used any more (value is
+     * 256). This state is only used when the bundle declaring the component
+     * is being stopped and all components have to be removed.
+     * @deprecated as of version 1.2 this constant has been renamed to
+     *      {@link #STATE_DISPOSED}.
+     */
+    @Deprecated
+    static final int STATE_DESTROYED = 256;
+
+    /**
+     * The Component has been disposed off and cannot be used any more (value is
+     * 256). This state is used when the bundle declaring the component
+     * is being stopped and all components have to be removed. This status is
+     * also the final status of a component after the
+     * <code>ComponentInstance.dispose()</code> method has been called.
+     * @since 1.2
+     */
+    static final int STATE_DISPOSED = 256;
+
+
+    /**
+     * Returns the component ID of this component. This ID is managed by the
+     * SCR. If the component is not currently enabled the ID might not be
+     * assigned to the component (yet) and this method will return -1 in this
+     * case.
+     */
+    long getId();
+
+
+    /**
+     * Returns the name of the component, which is also used as the service PID.
+     * This method provides access to the <code>name</code> attribute of the
+     * <code>component</code> element.
+     */
+    String getName();
+
+
+    /**
+     * Returns the current state of the Component, which is one of the
+     * <code>STATE_*</code> constants defined in this interface.
+     */
+    int getState();
+
+
+    /**
+     * Returns the <code>Bundle</code> declaring this component.
+     */
+    Bundle getBundle();
+
+
+    /**
+     * Returns the component factory name or <code>null</code> if this component
+     * is not defined as a component factory. This method provides access to
+     * the <code>factory</code> attribute of the <code>component</code>
+     * element.
+     */
+    String getFactory();
+
+
+    /**
+     * Returns <code>true</code> if this component is a service factory. This
+     * method returns the value of the <code>serviceFactory</code> attribute of
+     * the <code>service</code> element. If the component has no service
+     * element, this method returns <code>false</code>.
+     */
+    boolean isServiceFactory();
+
+
+    /**
+     * Returns the class name of the Component implementation. This method
+     * provides access to the <code>class</code> attribute of the
+     * <code>implementation</code> element.
+     */
+    String getClassName();
+
+
+    /**
+     * Returns whether the Component is declared to be enabled initially. This
+     * method provides access to the <code>enabled</code> attribute of the
+     * <code>component</code> element.
+     */
+    boolean isDefaultEnabled();
+
+
+    /**
+     * Returns whether the Component is an Immediate or a Delayed Component.
+     * This method provides access to the <code>immediate</code> attribute of
+     * the <code>component</code> element.
+     */
+    boolean isImmediate();
+
+
+    /**
+     * Returns an array of service names provided by this Component or
+     * <code>null</code> if the Component is not registered as a service. This
+     * method provides access to the <code>interface</code> attributes of the
+     * <code>provide</code> elements.
+     */
+    String[] getServices();
+
+
+    /**
+     * Returns the properties of the Component. The Dictionary returned is a
+     * private copy of the actual properties and contains the same entries as
+     * are used to register the Component as a service and are returned by
+     * the <code>ComponentContext.getProperties()</code> method.
+     */
+    Dictionary getProperties();
+
+
+    /**
+     * Returns an array of {@link Reference} instances representing the service
+     * references (or dependencies) of this Component. If the Component has no
+     * references, <code>null</code> is returned.
+     */
+    Reference[] getReferences();
+
+
+    /**
+     * Returns the <code>org.osgi.service.component.ComponentInstance</code>
+     * representing this component or <code>null</code> if this component
+     * is not been activated yet.
+     *
+     * @since 1.2
+     */
+    ComponentInstance getComponentInstance();
+
+
+    /**
+     * Returns the name of the method to be called when the component is being
+     * activated.
+     * <p>
+     * This method never returns <code>null</code>, that is, if this method is
+     * not declared in the component descriptor this method returns the
+     * default value <i>activate</i>.
+     *
+     * @since 1.2
+     */
+    String getActivate();
+
+
+    /**
+     * Returns <code>true</code> if the name of the method to be called on
+     * component activation (see {@link #getActivate()} is declared in the
+     * component descriptor or not.
+     * <p>
+     * For a component declared in a Declarative Services 1.0 descriptor, this
+     * method always returns <code>false</code>.
+     *
+     * @since 1.2
+     */
+    boolean isActivateDeclared();
+
+
+    /**
+     * Returns the name of the method to be called when the component is being
+     * deactivated.
+     * <p>
+     * This method never returns <code>null</code>, that is, if this method is
+     * not declared in the component descriptor this method returns the
+     * default value <i>deactivate</i>.
+     *
+     * @since 1.2
+     */
+    String getDeactivate();
+
+
+    /**
+     * Returns <code>true</code> if the name of the method to be called on
+     * component deactivation (see {@link #getDeactivate()} is declared in the
+     * component descriptor or not.
+     * <p>
+     * For a component declared in a Declarative Services 1.0 descriptor, this
+     * method always returns <code>false</code>.
+     *
+     * @since 1.2
+     */
+    boolean isDeactivateDeclared();
+
+
+    /**
+     * Returns the name of the method to be called when the component
+     * configuration has been updated or <code>null</code> if such a method is
+     * not declared in the component descriptor.
+     * <p>
+     * For a component declared in a Declarative Services 1.0 descriptor, this
+     * method always returns <code>null</code>.
+     *
+     * @since 1.2
+     */
+    String getModified();
+
+
+    /**
+     * Returns the configuration policy declared in the component descriptor.
+     * If the component descriptor is a Declarative Services 1.0 descriptor or
+     * no configuration policy has been declared, the default value
+     * <i>optional</i> is returned.
+     * <p>
+     * The returned string is one of the three policies defined in the
+     * Declarative Services specification 1.1:
+     * <dl>
+     * <dt>optional</dt>
+     * <dd>Configuration from the Configuration Admin service is supplied to
+     * the component if available. Otherwise the component is activated without
+     * Configuration Admin configuration. This is the default value reflecting
+     * the behaviour of Declarative Services 1.0</dd>
+     * <dt>require</dt>
+     * <dd>Configuration is required. The component remains unsatisfied until
+     * configuration is available from the Configuration Admin service.</dd>
+     * <dt>ignore</dt>
+     * <dd>Configuration is ignored. No Configuration Admin service
+     * configuration is supplied to the component.</dd>
+     * </dl>
+     *
+     * @since 1.2
+     */
+    String getConfigurationPolicy();
+
+    /**
+     * Returns the configuration pid declared in the component descriptor.
+     * The value is used to retrieve the component configuration from the
+     * OSGi configuration admin service. The value returned by this method
+     * depends on the Declarative Service namespace used by the component:
+     * <p>
+     * <dl>
+     * <dt>DS 1.0</dt>
+     * <dd>The component name is returned.</dd>
+     * <dt>DS 1.1</dt>
+     * <dd>The component name is returned, if it has been specified. If not specified,
+     * then the default component name is returned (that is the fully qualified component
+     * class name).
+     * <dt>DS 1.2</dt>
+     * <dd>The value of the configuration-pid attribute is returned if it has been specified.
+     * If not specified, then the same DS 1.1 rules are applied.</dd>
+     * </dl>
+     *
+     * @since 1.2
+     */
+    String getConfigurationPid();
+
+    /**
+     * Returns whether the configuration-pid has been declared in the descriptor
+     * or not.
+     *
+     * @return whether the configuration-pid has method has been declared in the descriptor
+     *      or not.
+     * @since DS 1.2
+     */
+    boolean isConfigurationPidDeclared();
+
+    /**
+     * Enables this Component if it is disabled. If the Component is not
+     * currently {@link #STATE_DISABLED disabled} this method has no effect. If
+     * the Component is {@link #STATE_DESTROYED destroyed}, this method throws
+     * an <code>IllegalStateException</code>.
+     *
+     * @throws IllegalStateException If the Component is destroyed.
+     */
+    void enable();
+
+
+    /**
+     * Disables this Component if it is enabled. If the Component is already
+     * {@link #STATE_DISABLED disabled} this method has no effect. If the
+     * Component is {@link #STATE_DESTROYED destroyed}, this method throws an
+     * <code>IllegalStateException</code>.
+     *
+     * @throws IllegalStateException If the Component is destroyed.
+     */
+    void disable();
+
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/Reference.java b/scr/src/main/java/org/apache/felix/scr/Reference.java
new file mode 100644
index 0000000..7371bc1
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/Reference.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.felix.scr;
+
+
+import org.osgi.framework.ServiceReference;
+
+
+/**
+ * The <code>Reference</code> interface represents a single reference (or
+ * dependency) to a service used by a Component.
+ *
+ * @deprecated Use the ServiceComponentRuntime service.
+ */
+@Deprecated
+public interface Reference
+{
+
+    /**
+     * Returns the name of this Reference. This method provides access to the
+     * <code>name</code> attribute of the <code>referenec</code> element.
+     */
+    String getName();
+
+
+    /**
+     * Returns the name of the service used by this Reference. This method
+     * provides access to the <code>interface</code> attribute of the
+     * <code>reference</code> element.
+     */
+    String getServiceName();
+
+
+    /**
+     * Returns an array of references to the services bound to this Reference
+     * or <code>null</code> if no services are currently bound.
+     */
+    ServiceReference[] getServiceReferences();
+
+    /**
+     * added by mistake.  Use getServiceReferences();
+     * @return
+     */
+    @Deprecated
+    ServiceReference[] getBoundServiceReferences();
+
+    /**
+     * Returns whether this reference is satisified. A {@link #isOptional() optional}
+     * component is always satsified. Otherwise <code>true</code> is only
+     * returned if at least one service is bound.
+     */
+    boolean isSatisfied();
+
+
+    /**
+     * Returns whether this reference is optional. This method provides access
+     * to the lower bound of the <code>cardinality</code> attribute of the
+     * <code>reference</code> element. In other words, this method returns
+     * <code>true</code> if the cardinality is <em>0..1</em> or <em>0..n</em>.
+     */
+    boolean isOptional();
+
+
+    /**
+     * Returns whether this reference is multiple. This method provides access
+     * to the upper bound of the <code>cardinality</code> attribute of the
+     * <code>reference</code> element. In other words, this method returns
+     * <code>true</code> if the cardinality is <em>0..n</em> or <em>1..n</em>.
+     */
+    boolean isMultiple();
+
+
+    /**
+     * Returns <code>true</code> if the reference is defined with static policy.
+     * This method provides access to the <code>policy</code> element of the
+     * <code>reference</code> element. <code>true</code> is returned if the
+     * policy is defined as <em>static</em>.
+     */
+    boolean isStatic();
+
+    /**
+     * Returns <code>true</code> if the reference is defined with reluctant
+     * policy option.  This method provides access to the <code>policy-option</code>
+     * element of the <code>reference</code> element.  <code>true</code> is
+     * returned if the policy option is defined as <em>reluctant</em>
+     *
+     * @since 1.7
+     */
+    boolean isReluctant();
+
+    /**
+     * Returns the value of the target property of this reference. Initially
+     * (without overwriting configuration) this method provides access to the
+     * <code>target</code> attribute of the <code>reference</code> element. If
+     * configuration overwrites the target property, this method returns the
+     * value of the Component property whose name is derived from the
+     * {@link #getName() reference name} plus the suffix <em>.target</em>. If
+     * no target property exists this method returns <code>null</code>.
+     */
+    String getTarget();
+
+
+    /**
+     * Returns the name of the method called if a service is being bound to
+     * the Component or <code>null</code> if no such method is configued. This
+     * method provides access to the <code>bind</code> attribute of the
+     * <code>reference</code> element.
+     */
+    String getBindMethodName();
+
+
+    /**
+     * Returns the name of the method called if a service is being unbound from
+     * the Component or <code>null</code> if no such method is configued. This
+     * method provides access to the <code>unbind</code> attribute of the
+     * <code>reference</code> element.
+     */
+    String getUnbindMethodName();
+
+
+    /**
+     * Returns the name of the method called if a bound service updates its
+     * service registration properties or <code>null</code> if no such method
+     * is configued. This method provides access to the <code>updated</code>
+     * attribute of the <code>reference</code> element.
+     * <p>
+     * For a component declared in a Declarative Services 1.0 and 1.1
+     * descriptor, this method always returns <code>null</code>.
+     *
+     * @since 1.4
+     */
+    String getUpdatedMethodName();
+
+}
diff --git a/scr/src/main/java/org/apache/felix/scr/ScrService.java b/scr/src/main/java/org/apache/felix/scr/ScrService.java
new file mode 100644
index 0000000..b892917
--- /dev/null
+++ b/scr/src/main/java/org/apache/felix/scr/ScrService.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.felix.scr;
+
+
+import org.osgi.framework.Bundle;
+
+
+/**
+ * The <code>ScrService</code> represents the Declarative Services main
+ * controller also known as the Service Component Runtime or SCR for short.
+ * It provides access to the components managed the SCR.
+ *
+ * @deprecated Use the ServiceComponentRuntime service.
+ */
+@Deprecated
+public interface ScrService
+{
+
+    /**
+     * Returns an array of all components managed by this SCR instance. The
+     * components are returned in ascending order of their component.id. If
+     * there are no components currently managed by the SCR, <code>null</code>
+     * is returned.
+     *
+     * @return The components or <code>null</code> if there are none.
+     */
+    Component[] getComponents();
+
+
+    /**
+     * Returns the component whose component.id matches the given
+     * <code>componentId</code> or <code>null</code> if no component with the
+     * given id is currently managed.
+     *
+     * @param componentId The ID of the component to return
+     *
+     * @return The indicated component or <code>null</code> if no such
+     *      component exists.
+     */
+    Component getComponent( long componentId );
+
+
+    /**
+     * Returns the components whose <code>component.name</code> matches the
+     * given <code>componentName</code> or <code>null</code> if no component
+     * with the given name is currently managed.
+     * <p>
+     * If the component name refers to a component factory component or a
+     * component configured with multiple factory configurations this method
+     * returns multiple component instances.
+     *
+     * @param componentName The name of the component to return
+     *
+     * @return The indicated components or <code>null</code> if no such
+     *      component exists.
+     * @since 1.5 (Apache Felix Declarative Services 1.4.2)
+     */
+    Component[] getComponents( String componentName );
+
+
+    /**
+     * Reuturns an array of all components managed by this SCR instance on
+     * behalf of the given bundle. The components are returned in ascending
+     * order of their component.id. If there are no components managed by the
+     * SCR for the given bundle, <code>null</code> is returned.
+     *
+     * @param bundle The <code>Bundle</code> whose components are to be
+     *      returned.
+     *
+     * @return The bundle's components or <code>null</code> if the bundle
+     *      has none.
+     */
+    Component[] getComponents( Bundle bundle );
+
+}
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 e9389d3..c081f88 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
@@ -76,8 +76,8 @@
 
     //  thread acting upon configurations
     private ComponentActorThread m_componentActor;
-    
-    private ServiceRegistration<ServiceComponentRuntime> m_runtime_reg;
+
+    private ServiceRegistration<?> m_runtime_reg;
 
     private ScrCommand m_scrCommand;
 
@@ -93,6 +93,7 @@
      * @param context The <code>BundleContext</code> of the SCR implementation
      *      bundle.
      */
+    @Override
     public void start( BundleContext context ) throws Exception
     {
         m_context = context;
@@ -103,7 +104,7 @@
         // get the configuration
         m_configuration.start( m_context ); //this will call restart, which calls super.start.
     }
-    
+
     public void restart( boolean globalExtender )
     {
         BundleContext context;
@@ -137,16 +138,19 @@
         {
             log( LogService.LOG_ERROR, m_bundle, "Exception starting during restart", e );
         }
-        
+
     }
 
+    @Override
     protected void doStart() throws Exception {
 
         // 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);
+        m_runtime_reg = m_context.registerService(new String[] {ServiceComponentRuntime.class.getName()},
+                runtime, null);
 
         // log SCR startup
         log( LogService.LOG_INFO, m_bundle, " Version = {0}",
@@ -163,7 +167,8 @@
         m_scrCommand = ScrCommand.register(m_context, runtime, m_configuration);
         m_configuration.setScrCommand( m_scrCommand );
     }
-    
+
+    @Override
     public void stop(BundleContext context) throws Exception
     {
         super.stop(context);
@@ -177,6 +182,7 @@
      * which have been registered during the active life time of the SCR
      * implementation bundle.
      */
+    @Override
     public void doStop() throws Exception
     {
         // stop tracking
@@ -193,7 +199,11 @@
 			m_runtime_reg = null;
 		}
 		// dispose component registry
-        m_componentRegistry.dispose();
+    	if ( m_componentRegistry != null )
+    	{
+    	    m_componentRegistry.dispose();
+    	    m_componentRegistry = null;
+    	}
 
         // terminate the actor thread
         if ( m_componentActor != null )
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 6bc2688..3a48cb3 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
@@ -27,9 +27,10 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.felix.scr.ScrService;
 import org.apache.felix.scr.impl.config.ComponentHolder;
-import org.apache.felix.scr.impl.config.ConfigurationSupport;
 import org.apache.felix.scr.impl.config.ConfigurableComponentHolder;
+import org.apache.felix.scr.impl.config.ConfigurationSupport;
 import org.apache.felix.scr.impl.manager.AbstractComponentManager;
 import org.apache.felix.scr.impl.manager.DependencyManager;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
@@ -40,7 +41,6 @@
 import org.osgi.framework.ServiceEvent;
 import org.osgi.framework.ServiceListener;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.component.ComponentConstants;
 import org.osgi.service.component.ComponentException;
@@ -121,7 +121,7 @@
 
     private final Map<ServiceReference<?>, List<Entry<?, ?>>> m_missingDependencies = new HashMap<ServiceReference<?>, List<Entry<?, ?>>>( );
 
-    protected ComponentRegistry( BundleContext context )
+    protected ComponentRegistry( final BundleContext context )
     {
         m_bundleContext = context;
         m_componentHoldersByName = new HashMap<ComponentRegistryKey, ComponentHolder<?>>();
@@ -144,10 +144,8 @@
         {
             getOrCreateConfigurationSupport();
         }
-
     }
 
-
     public void dispose()
     {
         m_bundleContext.removeServiceListener(this);
@@ -157,10 +155,10 @@
             configurationSupport.dispose();
             configurationSupport = null;
         }
-
     }
 
 
+
     //---------- ComponentManager registration by component Id
 
     /**
@@ -278,7 +276,7 @@
      */
     final void registerComponentHolder( final ComponentRegistryKey key, ComponentHolder<?> componentHolder )
     {
-        Activator.log(LogService.LOG_DEBUG, null, 
+        Activator.log(LogService.LOG_DEBUG, null,
                 "Registering component with pid {0} for bundle {1}",
                 new Object[] {componentHolder.getComponentMetadata().getConfigurationPid(), key.getBundleId()},
                 null);
@@ -314,7 +312,7 @@
                 set.add( componentHolder );
             }
         }
-        
+
         if (configurationSupport != null)
         {
             configurationSupport.configureComponentHolder(componentHolder);
@@ -363,6 +361,18 @@
     }
 
     /**
+     * We only need this for the ScrService implementation
+     * @param componentId
+     * @return
+     */
+    public final AbstractComponentManager<?> getComponentManagerById(final long componentId)
+    {
+        synchronized ( m_componentsById )
+        {
+            return m_componentsById.get( componentId );
+        }
+    }
+    /**
      * Returns an array of all values currently stored in the component holders
      * map. The entries in the array are either String types for component
      * name reservations or {@link ComponentHolder} instances for actual
@@ -428,7 +438,7 @@
         }
 
         if (component != null) {
-            Activator.log(LogService.LOG_DEBUG, null, 
+            Activator.log(LogService.LOG_DEBUG, null,
                     "Unregistering component with pid {0} for bundle {1}",
                     new Object[] {component.getComponentMetadata().getConfigurationPid(), key.getBundleId()}, null);
             synchronized (m_componentHoldersByPid)
@@ -623,5 +633,4 @@
             return trackingCount;
         }
     }
-
 }
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
index 4ea4d91..bc812ad 100644
--- 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
@@ -20,6 +20,7 @@
 
 import java.util.List;
 
+import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.osgi.framework.ServiceReference;
 
 public interface ReferenceManager<S, T> {
@@ -47,4 +48,5 @@
 
     boolean isSatisfied();
 
+    ReferenceMetadata getReferenceMetadata();
 }
\ No newline at end of file
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 07a5a8a..0280ddf 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
@@ -109,6 +109,11 @@
         }
     }
 
+    public ReferenceMetadata getReferenceMetadata()
+    {
+        return this.m_dependencyMetadata;
+    }
+
     private static int defaultMinimumCardinality(ReferenceMetadata dependency)
     {
         return dependency.isOptional()? 0: 1;
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
index 438591a..9fe2b78 100644
--- 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
@@ -21,14 +21,22 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Dictionary;
 import java.util.HashMap;
+import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.felix.scr.Component;
+import org.apache.felix.scr.Reference;
+import org.apache.felix.scr.ScrService;
+import org.apache.felix.scr.impl.BundleComponentActivator;
 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.manager.AbstractComponentManager;
+import org.apache.felix.scr.impl.manager.SingleComponentManager;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.osgi.dto.DTO;
@@ -38,6 +46,7 @@
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.dto.BundleDTO;
 import org.osgi.framework.dto.ServiceReferenceDTO;
+import org.osgi.service.component.ComponentInstance;
 import org.osgi.service.component.runtime.ServiceComponentRuntime;
 import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
 import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
@@ -46,7 +55,7 @@
 import org.osgi.service.component.runtime.dto.UnsatisfiedReferenceDTO;
 import org.osgi.util.promise.Promise;
 
-public class ServiceComponentRuntimeImpl implements ServiceComponentRuntime
+public class ServiceComponentRuntimeImpl implements ServiceComponentRuntime, ScrService
 {
 
 	private static final String[] EMPTY = {};
@@ -344,4 +353,333 @@
 		return b;
 	}
 
+	// ScrService
+
+    /**
+     * @see org.apache.felix.scr.ScrService#getComponents()
+     */
+    public Component[] getComponents()
+    {
+        final List<ComponentHolder<?>> holders = componentRegistry.getComponentHolders();
+        ArrayList<Component> list = new ArrayList<Component>();
+        for ( ComponentHolder<?> holder: holders )
+        {
+            if ( holder != null )
+            {
+                final List<? extends ComponentManager<?>> components = holder.getComponents();
+                for ( ComponentManager<?> component: components )
+                {
+                    list.add( new ComponentWrapper((AbstractComponentManager<?>)component) );
+                }
+            }
+        }
+
+        // nothing to return
+        if ( list.isEmpty() )
+        {
+            return null;
+        }
+
+        return list.toArray( new Component[list.size()] );
+    }
+
+
+    /**
+     * @see org.apache.felix.scr.ScrService#getComponents(org.osgi.framework.Bundle)
+     */
+    public Component[] getComponents( Bundle bundle )
+    {
+        final List<ComponentHolder<?>> holders = componentRegistry.getComponentHolders();
+        ArrayList<Component> list = new ArrayList<Component>();
+        for ( ComponentHolder<?> holder: holders )
+        {
+            if ( holder != null )
+            {
+                BundleComponentActivator activator = holder.getActivator();
+                if ( activator != null && activator.getBundleContext().getBundle() == bundle )
+                {
+                    final List<? extends ComponentManager<?>> components = holder.getComponents();
+                    for ( ComponentManager<?> component: components )
+                    {
+                        list.add( new ComponentWrapper((AbstractComponentManager<?>)component) );
+                    }
+                }
+            }
+        }
+
+        // nothing to return
+        if ( list.isEmpty() )
+        {
+            return null;
+        }
+
+        return list.toArray( new Component[list.size()] );
+    }
+
+
+    /**
+     * @see org.apache.felix.scr.ScrService#getComponent(long)
+     */
+    public Component getComponent( long componentId )
+    {
+        final AbstractComponentManager<?> c = componentRegistry.getComponentManagerById(componentId);
+        if ( c != null )
+        {
+            return new ComponentWrapper(c);
+        }
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.scr.ScrService#getComponents(java.lang.String)
+     */
+    public Component[] getComponents( final String componentName )
+    {
+        final List<Component> list = new ArrayList<Component>();
+        final List<ComponentHolder<?>> holders = componentRegistry.getComponentHolders();
+        for ( ComponentHolder<?> holder: holders )
+        {
+            if ( holder.getComponentMetadata().getName().equals(componentName) )
+            {
+                final List<? extends ComponentManager<?>> components = holder.getComponents();
+                for ( ComponentManager<?> component: components )
+                {
+                    list.add( new ComponentWrapper((AbstractComponentManager<?>)component) );
+                }
+            }
+        }
+
+        return ( list.isEmpty() ) ? null : list.toArray( new Component[list.size()] );
+    }
+
+
+    private static final class ComponentWrapper implements Component
+    {
+        private final AbstractComponentManager<?> mgr;
+
+        public ComponentWrapper(final AbstractComponentManager<?> mgr)
+        {
+            this.mgr = mgr;
+        }
+
+        public long getId()
+        {
+            return mgr.getId();
+        }
+
+        public String getName()
+        {
+            return mgr.getComponentMetadata().getName();
+        }
+
+        public int getState()
+        {
+            return mgr.getState();
+        }
+
+        public Bundle getBundle()
+        {
+            return mgr.getBundle();
+        }
+
+        public String getFactory()
+        {
+            return mgr.getComponentMetadata().getFactoryIdentifier();
+        }
+
+        public boolean isServiceFactory()
+        {
+            return mgr.getComponentMetadata().isFactory();
+        }
+
+        public String getClassName()
+        {
+            return mgr.getComponentMetadata().getImplementationClassName();
+        }
+
+        public boolean isDefaultEnabled()
+        {
+            return mgr.getComponentMetadata().isEnabled();
+        }
+
+        public boolean isImmediate()
+        {
+            return mgr.getComponentMetadata().isImmediate();
+        }
+
+        public String[] getServices()
+        {
+            if ( mgr.getComponentMetadata().getServiceMetadata() != null )
+            {
+                return mgr.getComponentMetadata().getServiceMetadata().getProvides();
+            }
+
+            return null;
+        }
+
+        public Dictionary getProperties()
+        {
+            return new Hashtable<String, Object>(mgr.getComponentMetadata().getProperties());
+        }
+
+        public Reference[] getReferences()
+        {
+            final List<? extends ReferenceManager<?, ?>> refs = mgr.getReferenceManagers();
+            if ( refs != null && refs.size() > 0 )
+            {
+                final List<Reference> list = new ArrayList<Reference>();
+                for(final ReferenceManager<?, ?> rm : refs)
+                {
+                    list.add(new ReferenceWrapper(rm));
+                }
+                return list.toArray(
+                        new Reference[list.size()] );
+            }
+
+            return null;
+        }
+
+        public ComponentInstance getComponentInstance()
+        {
+            if ( mgr instanceof SingleComponentManager<?> )
+            {
+                return ((SingleComponentManager<?>)mgr).getComponentInstance();
+            }
+
+            return null;
+        }
+
+        public String getActivate()
+        {
+            return mgr.getComponentMetadata().getActivate();
+        }
+
+        public boolean isActivateDeclared()
+        {
+            return mgr.getComponentMetadata().isActivateDeclared();
+        }
+
+        public String getDeactivate()
+        {
+            return mgr.getComponentMetadata().getDeactivate();
+        }
+
+        public boolean isDeactivateDeclared()
+        {
+            return mgr.getComponentMetadata().isDeactivateDeclared();
+        }
+
+        public String getModified()
+        {
+            return mgr.getComponentMetadata().getModified();
+        }
+
+        public String getConfigurationPolicy()
+        {
+            return mgr.getComponentMetadata().getConfigurationPolicy();
+        }
+
+        public String getConfigurationPid()
+        {
+            final List<String> pids = mgr.getComponentMetadata().getConfigurationPid();
+            if ( pids != null && pids.size() > 0 )
+            {
+                return pids.get(0);
+            }
+            return null;
+        }
+
+        public boolean isConfigurationPidDeclared()
+        {
+            return mgr.getComponentMetadata().isConfigurationPidDeclared();
+        }
+
+        public void enable()
+        {
+            mgr.enable(false);
+        }
+
+        public void disable()
+        {
+            mgr.disable(false);
+        }
+    }
+
+    private static final class ReferenceWrapper implements Reference
+    {
+        private final ReferenceManager<?, ?> mgr;
+
+        public ReferenceWrapper(final ReferenceManager<?, ?> mgr)
+        {
+            this.mgr = mgr;
+        }
+
+        public String getName()
+        {
+            return mgr.getReferenceMetadata().getName();
+        }
+
+        public String getServiceName()
+        {
+            return mgr.getReferenceMetadata().getInterface();
+        }
+
+        public ServiceReference[] getServiceReferences()
+        {
+            final List<ServiceReference<?>> refs = this.mgr.getServiceReferences();
+            return refs.toArray(new ServiceReference<?>[refs.size()]);
+        }
+
+        public ServiceReference<?>[] getBoundServiceReferences()
+        {
+            final List<ServiceReference<?>> refs = this.mgr.getServiceReferences();
+            return refs.toArray(new ServiceReference<?>[refs.size()]);
+        }
+
+        public boolean isSatisfied()
+        {
+            return mgr.isSatisfied();
+        }
+
+        public boolean isOptional()
+        {
+            return this.mgr.getReferenceMetadata().isOptional();
+        }
+
+        public boolean isMultiple()
+        {
+            return this.mgr.getReferenceMetadata().isMultiple();
+        }
+
+        public boolean isStatic()
+        {
+            return this.mgr.getReferenceMetadata().isStatic();
+        }
+
+        public boolean isReluctant()
+        {
+            return this.mgr.getReferenceMetadata().isReluctant();
+        }
+
+        public String getTarget()
+        {
+            return this.mgr.getTarget();
+        }
+
+        public String getBindMethodName()
+        {
+            return this.mgr.getReferenceMetadata().getBind();
+        }
+
+        public String getUnbindMethodName()
+        {
+            return this.mgr.getReferenceMetadata().getUnbind();
+        }
+
+        public String getUpdatedMethodName()
+        {
+            return this.mgr.getReferenceMetadata().getUpdated();
+        }
+
+    }
 }