FELIX-4785 : Incompatible SCR API

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1660095 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr-compat/src/main/java/org/apache/felix/scr/impl/compat/Activator.java b/scr-compat/src/main/java/org/apache/felix/scr/impl/compat/Activator.java
new file mode 100644
index 0000000..fe1416c
--- /dev/null
+++ b/scr-compat/src/main/java/org/apache/felix/scr/impl/compat/Activator.java
@@ -0,0 +1,107 @@
+/*
+ * 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.impl.compat;
+
+
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.felix.scr.ScrInfo;
+import org.apache.felix.scr.ScrService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.runtime.ServiceComponentRuntime;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+
+public class Activator
+{
+    // tracker of the runtime service
+    private volatile ServiceTracker<ServiceComponentRuntime, ServiceComponentRuntime> runtimeTracker;
+
+    // the service registrations
+    private final Map<Long, ServiceRegistration<ScrService>> scrServiceRegMap = new ConcurrentHashMap<Long, ServiceRegistration<ScrService>>();
+
+    // the service registrations
+    private final Map<Long, ServiceRegistration<ScrInfo>> scrCommandRegMap = new ConcurrentHashMap<Long, ServiceRegistration<ScrInfo>>();
+
+    public void start( final BundleContext context ) throws Exception
+    {
+        this.runtimeTracker = new ServiceTracker<ServiceComponentRuntime, ServiceComponentRuntime>(context, ServiceComponentRuntime.class,
+                new ServiceTrackerCustomizer<ServiceComponentRuntime, ServiceComponentRuntime>()
+                {
+
+                    public ServiceComponentRuntime addingService(
+                            final ServiceReference<ServiceComponentRuntime> reference)
+                    {
+                        final ServiceComponentRuntime runtime = context.getService(reference);
+                        if ( runtime != null )
+                        {
+                            Hashtable props = new Hashtable();
+                            props.put(Constants.SERVICE_DESCRIPTION, "Apache Felix Compat ScrService");
+                            props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+
+                            final ScrService service = new ScrServiceImpl(context, runtime);
+                            scrServiceRegMap.put((Long)reference.getProperty(Constants.SERVICE_ID),
+                                    context.registerService(ScrService.class, service, props));
+
+                            props = new Hashtable();
+                            props.put(Constants.SERVICE_DESCRIPTION, "Apache Felix Compat SCR Info service");
+                            props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
+                            final ScrInfo info = new ScrCommand(context, service);
+                            scrCommandRegMap.put((Long)reference.getProperty(Constants.SERVICE_ID),
+                                    context.registerService(ScrInfo.class, info, props));
+                        }
+                        return runtime;
+                    }
+
+                    public void modifiedService(
+                            final ServiceReference<ServiceComponentRuntime> reference,
+                            final ServiceComponentRuntime service) {
+                        // nothing to do
+                    }
+
+                    public void removedService(
+                            final ServiceReference<ServiceComponentRuntime> reference,
+                            final ServiceComponentRuntime service) {
+                        final ServiceRegistration<ScrService> reg =  scrServiceRegMap.remove(reference.getProperty(Constants.SERVICE_ID));
+                        if ( reg != null )
+                        {
+                            reg.unregister();
+                        }
+                        final ServiceRegistration<ScrInfo> reg2 =  scrCommandRegMap.remove(reference.getProperty(Constants.SERVICE_ID));
+                        if ( reg2 != null )
+                        {
+                            reg2.unregister();
+                        }
+                        context.ungetService(reference);
+                    }
+        });
+        this.runtimeTracker.open();
+    }
+
+    public void stop(final BundleContext context) throws Exception
+    {
+        this.runtimeTracker.close();
+    }
+}
\ No newline at end of file
diff --git a/scr-compat/src/main/java/org/apache/felix/scr/impl/compat/ScrCommand.java b/scr-compat/src/main/java/org/apache/felix/scr/impl/compat/ScrCommand.java
new file mode 100644
index 0000000..785c344
--- /dev/null
+++ b/scr-compat/src/main/java/org/apache/felix/scr/impl/compat/ScrCommand.java
@@ -0,0 +1,477 @@
+/*
+ * 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.impl.compat;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Dictionary;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+
+import org.apache.felix.scr.Component;
+import org.apache.felix.scr.Reference;
+import org.apache.felix.scr.ScrInfo;
+import org.apache.felix.scr.ScrService;
+import org.apache.felix.scr.impl.config.ScrConfiguration;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * The <code>ScrCommand</code> class provides the implementations for the
+ * Apache Felix Gogo and legacy Apache Felix Shell commands. The
+ * {@link #register(BundleContext, ScrService, ScrConfiguration)} method
+ * instantiates and registers the Gogo and Shell commands as possible.
+ */
+public class ScrCommand implements ScrInfo
+{
+
+    private final BundleContext bundleContext;
+    private final ScrService scrService;
+
+    public ScrCommand(final BundleContext bundleContext, final  ScrService scrService)
+    {
+        this.scrService = scrService;
+        this.bundleContext = bundleContext;
+
+    }
+
+    static boolean isBundleActive( final Bundle bundle )
+    {
+        if ( bundle != null )
+        {
+            if ( bundle.getState() == Bundle.ACTIVE )
+            {
+                return true;
+            }
+
+            if ( bundle.getState() == Bundle.STARTING )
+            {
+                // according to the spec the activationPolicy header is only
+                // set to request a bundle to be lazily activated. So in this
+                // simple check we just verify the header is set to assume
+                // the bundle is considered a lazily activated bundle
+                return bundle.getHeaders().get( Constants.BUNDLE_ACTIVATIONPOLICY ) != null;
+            }
+        }
+
+        // fall back: bundle is not considered active
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.felix.scr.impl.ScrInfo#list(java.lang.String, java.io.PrintStream, java.io.PrintStream)
+     */
+    public void list(final String bundleIdentifier, final PrintWriter out)
+    {
+        Component[] components;
+
+        if (bundleIdentifier != null)
+        {
+            Bundle bundle = null;
+            try
+            {
+                long bundleId = Long.parseLong(bundleIdentifier);
+                bundle = bundleContext.getBundle(bundleId);
+            }
+            catch (NumberFormatException nfe)
+            {
+                // might be a bundle symbolic name
+                Bundle[] bundles = bundleContext.getBundles();
+                for (int i = 0; i < bundles.length; i++)
+                {
+                    if (bundleIdentifier.equals(bundles[i].getSymbolicName()))
+                    {
+                        bundle = bundles[i];
+                        break;
+                    }
+                }
+            }
+
+            if (bundle == null)
+            {
+                throw new IllegalArgumentException("Missing bundle with ID " + bundleIdentifier);
+            }
+            if (isBundleActive(bundle))
+            {
+                components = scrService.getComponents(bundle);
+                if (components == null)
+                {
+                    out.println("Bundle " + bundleIdentifier + " declares no components");
+                    return;
+                }
+            }
+            else
+            {
+                out.println("Bundle " + bundleIdentifier + " is not active");
+                return;
+            }
+        }
+        else
+        {
+            components = scrService.getComponents();
+            if (components == null)
+            {
+                out.println("No components registered");
+                return;
+            }
+        }
+
+        Arrays.sort( components, new Comparator<Component>()
+                {
+
+                    public int compare(Component c1, Component c2)
+                    {
+                        return Long.signum(c1.getId() - c2.getId());
+                    }
+
+                });
+
+        out.println(" Id   State BundleId Name");
+        for ( Component component : components )
+        {
+            out.println( String.format( "[%1$4d] [%2$s] [%3$4d] %4$s", component.getId(), toStateString( component.getState() ), component.getBundle().getBundleId(), component.getName() ) );
+        }
+        out.flush();
+   }
+
+    /* (non-Javadoc)
+     * @see org.apache.felix.scr.impl.ScrInfo#info(java.lang.String, java.io.PrintStream, java.io.PrintStream)
+     */
+    public void info(final String componentId, PrintWriter out)
+    {
+        Component[] components = getComponentFromArg(componentId);
+        if (components == null)
+        {
+            return;
+        }
+
+        Arrays.sort( components, new Comparator<Component>()
+                {
+
+                    public int compare(Component c1, Component c2)
+                    {
+                        long bundleId1 = c1.getBundle().getBundleId();
+                        long bundleId2 = c2.getBundle().getBundleId();
+                        int result = Long.signum(bundleId1 - bundleId2);
+                        if (result == 0) {
+                            result = Long.signum(c1.getId() - c2.getId());
+                        }
+                        return result;
+                    }
+
+                });
+
+        long bundleId = -1;
+
+        for ( Component component : components )
+        {
+            if (components.length > 1)
+            {
+                if ( component.getBundle().getBundleId() != bundleId )
+                {
+                    if ( bundleId != -1 )
+                    {
+                        out.println();
+                        out.println();
+                    }
+                    bundleId = component.getBundle().getBundleId();
+                    out.println(String.format("*** Bundle: %1$s (%2$d)", component.getBundle().getSymbolicName(), bundleId));
+                }
+                out.println();
+            }
+            out.print( "ID: " );
+            out.println( component.getId() );
+            out.print( "Name: " );
+            out.println( component.getName() );
+            out.print( "Bundle: " );
+            out.println( component.getBundle().getSymbolicName() + " (" + component.getBundle().getBundleId() + ")" );
+            out.print( "State: " );
+            out.println( toStateString( component.getState() ) );
+            out.print( "Default State: " );
+            out.println( component.isDefaultEnabled() ? "enabled" : "disabled" );
+            out.print( "Activation: " );
+            out.println( component.isImmediate() ? "immediate" : "delayed" );
+
+            // DS 1.1 new features
+            out.print( "Configuration Policy: " );
+            out.println( component.getConfigurationPolicy() );
+            out.print( "Activate Method: " );
+            out.print( component.getActivate() );
+            if ( component.isActivateDeclared() )
+            {
+                out.print( " (declared in the descriptor)" );
+            }
+            out.println();
+            out.print( "Deactivate Method: " );
+            out.print( component.getDeactivate() );
+            if ( component.isDeactivateDeclared() )
+            {
+                out.print( " (declared in the descriptor)" );
+            }
+            out.println();
+            out.print( "Modified Method: " );
+            if ( component.getModified() != null )
+            {
+                out.print( component.getModified() );
+            }
+            else
+            {
+                out.print( "-" );
+            }
+            out.println();
+
+            out.print( "Configuration Pid: " );
+            out.print( component.getConfigurationPid() );
+            if ( component.isConfigurationPidDeclared() )
+            {
+                out.print( " (declared in the descriptor)" );
+            }
+            out.println();
+
+            if ( component.getFactory() != null )
+            {
+                out.print( "Factory: " );
+                out.println( component.getFactory() );
+            }
+
+            String[] services = component.getServices();
+            if ( services != null )
+            {
+                out.print( "Services: " );
+                out.println( services[0] );
+                for ( int i = 1; i < services.length; i++ )
+                {
+                    out.print( "          " );
+                    out.println( services[i] );
+                }
+                out.print( "Service Type: " );
+                out.println( component.isServiceFactory() ? "service factory" : "service" );
+            }
+
+            Reference[] refs = component.getReferences();
+            if ( refs != null )
+            {
+                for ( Reference ref : refs )
+                {
+                    out.print( "Reference: " );
+                    out.println( ref.getName() );
+                    out.print( "    Satisfied: " );
+                    out.println( ref.isSatisfied() ? "satisfied" : "unsatisfied" );
+                    out.print( "    Service Name: " );
+                    out.println( ref.getServiceName() );
+                    if ( ref.getTarget() != null )
+                    {
+                        out.print( "    Target Filter: " );
+                        out.println( ref.getTarget() );
+                    }
+                    out.print( "    Multiple: " );
+                    out.println( ref.isMultiple() ? "multiple" : "single" );
+                    out.print( "    Optional: " );
+                    out.println( ref.isOptional() ? "optional" : "mandatory" );
+                    out.print( "    Policy: " );
+                    out.println( ref.isStatic() ? "static" : "dynamic" );
+                    out.print( "    Policy option: " );
+                    out.println( ref.isReluctant() ? "reluctant" : "greedy" );
+                    ServiceReference[] serviceRefs = ref.getServiceReferences();
+                    if ( serviceRefs != null )
+                    {
+                        out.print( "    Bound to:" );
+                        for ( int k = 0; k < serviceRefs.length; k++ )
+                        {
+                            out.print( "        " );
+                            out.println( serviceRefs[k] );
+                        }
+                    }
+                    else
+                    {
+                        out.println( "    (unbound)" );
+                    }
+                }
+            }
+
+            Dictionary props = component.getProperties();
+            if ( props != null )
+            {
+                out.println( "Properties:" );
+                TreeSet keys = new TreeSet( Collections.list( props.keys() ) );
+                for ( Object key : keys )
+                {
+                    out.print( "    " );
+                    out.print( key );
+                    out.print( " = " );
+
+                    Object prop = props.get( key );
+                    if ( prop.getClass().isArray() )
+                    {
+                        prop = Arrays.asList( ( Object[] ) prop );
+                    }
+                    out.print( prop );
+
+                    out.println();
+                }
+            }
+        }
+        out.flush();
+    }
+
+    void change(final String componentIdentifier, PrintWriter out, boolean enable)
+    {
+        Component[] components = getComponentFromArg(componentIdentifier);
+        ArrayList<String> disposed = new ArrayList<String>();
+        if (components == null)
+        {
+            return;
+        }
+
+        for ( Component component : components )
+        {
+            if ( component.getState() == Component.STATE_DISPOSED )
+            {
+                disposed.add(component.getName());
+            }
+            else if ( enable )
+            {
+                if ( component.getState() == Component.STATE_DISABLED )
+                {
+                    component.enable();
+                    out.println( "Component " + component.getName() + " enabled" );
+                }
+                else
+                {
+                    out.println( "Component " + component.getName() + " already enabled" );
+                }
+            }
+            else
+            {
+                if ( component.getState() != Component.STATE_DISABLED )
+                {
+                    component.disable();
+                    out.println( "Component " + component.getName() + " disabled" );
+                }
+                else
+                {
+                    out.println( "Component " + component.getName() + " already disabled" );
+                }
+            }
+        }
+        out.flush();
+        if ( !disposed.isEmpty() )
+        {
+            throw new IllegalArgumentException( "Components " + disposed + " already disposed, cannot change state" );
+
+        }
+    }
+
+    private String toStateString(int state)
+    {
+        switch (state) {
+
+        case (Component.STATE_DISABLED):
+            return "disabled    ";
+        case (Component.STATE_ENABLING):
+            return "enabling    ";
+        case (Component.STATE_ENABLED):
+            return "enabled     ";
+        case (Component.STATE_UNSATISFIED):
+            return "unsatisfied ";
+        case (Component.STATE_ACTIVATING):
+            return "activating  ";
+        case (Component.STATE_ACTIVE):
+            return "active      ";
+        case (Component.STATE_REGISTERED):
+            return "registered  ";
+        case (Component.STATE_FACTORY):
+            return "factory     ";
+        case (Component.STATE_DEACTIVATING):
+            return "deactivating";
+        case (Component.STATE_DISABLING):
+            return "disabling   ";
+        case (Component.STATE_DISPOSING):
+            return "disposing   ";
+        case (Component.STATE_DISPOSED):
+            return "disposed    ";
+        default:
+            return "unkown: " + state;
+        }
+    }
+
+    private Component[] getComponentFromArg(final String componentIdentifier)
+    {
+        Component[] components = null;
+        if (componentIdentifier != null)
+        {
+            try
+            {
+                long componentId = Long.parseLong(componentIdentifier);
+                Component component = scrService.getComponent(componentId);
+                if (component == null)
+                {
+                    throw new IllegalArgumentException("Missing Component with ID " + componentId);
+                }
+                else
+                {
+                    return new Component[]
+                        { component };
+                }
+            }
+            catch (NumberFormatException nfe)
+            {
+
+                // check whether it is a component name
+                components = scrService.getComponents(componentIdentifier);
+            }
+        }
+        if ( components == null)
+        {
+            components = scrService.getComponents();
+            if (componentIdentifier != null)
+            {
+                ArrayList<Component> cs = new ArrayList<Component>(components.length);
+                Pattern p = Pattern.compile(componentIdentifier);
+                for (Component component: components)
+                {
+                    if ( p.matcher( component.getName()).matches() )
+                    {
+                        cs.add( component );
+                    }
+                }
+                if (cs.isEmpty())
+                {
+                    throw new IllegalArgumentException("No Component with ID or matching " + componentIdentifier);
+                }
+                components = cs.toArray( new Component[cs.size()] );
+            }
+        }
+
+        return components;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.felix.scr.impl.ScrInfo#config(java.io.PrintStream)
+     */
+    public void config(PrintWriter out)
+    {
+        out.println("Configuration not available.");
+    }
+}
diff --git a/scr-compat/src/main/java/org/apache/felix/scr/impl/compat/ScrServiceImpl.java b/scr-compat/src/main/java/org/apache/felix/scr/impl/compat/ScrServiceImpl.java
new file mode 100644
index 0000000..2ad5d64
--- /dev/null
+++ b/scr-compat/src/main/java/org/apache/felix/scr/impl/compat/ScrServiceImpl.java
@@ -0,0 +1,437 @@
+/*
+ * 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.impl.compat;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.apache.felix.scr.Component;
+import org.apache.felix.scr.Reference;
+import org.apache.felix.scr.ScrService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+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;
+import org.osgi.service.component.runtime.dto.ReferenceDTO;
+import org.osgi.service.component.runtime.dto.SatisfiedReferenceDTO;
+
+public class ScrServiceImpl implements ScrService
+{
+
+	private static final String[] EMPTY = {};
+
+	private final BundleContext context;
+	private final ServiceComponentRuntime runtime;
+
+
+	public ScrServiceImpl(BundleContext context, final ServiceComponentRuntime runtime)
+	{
+        // we always use the system bundle to avoid problems if subsystems etc.
+        // are used and the SCR implemented extends those "invisible" bundles
+		this.context = context.getBundle(0).getBundleContext();
+		this.runtime = runtime;
+	}
+
+
+	// ScrService
+
+    /**
+     * @see org.apache.felix.scr.ScrService#getComponents()
+     */
+    public Component[] getComponents()
+    {
+        return this.getComponents((Bundle)null);
+    }
+
+
+    /**
+     * @see org.apache.felix.scr.ScrService#getComponents(org.osgi.framework.Bundle)
+     */
+    public Component[] getComponents( final Bundle bundle )
+    {
+        List<Component> result = new ArrayList<Component>();
+
+        final Collection<ComponentDescriptionDTO> descriptions = this.runtime.getComponentDescriptionDTOs(bundle);
+        for(final ComponentDescriptionDTO descDTO : descriptions )
+        {
+            final Collection<ComponentConfigurationDTO> configs = this.runtime.getComponentConfigurationDTOs(descDTO);
+            ComponentConfigurationDTO configDTO = null;
+            if ( !configs.isEmpty() )
+            {
+                configDTO = configs.iterator().next();
+            }
+            result.add(new ComponentWrapper(this.context, this.runtime, descDTO, configDTO));
+        }
+
+        return result.isEmpty() ? null : result.toArray( new Component[result.size()] );
+    }
+
+
+    /**
+     * @see org.apache.felix.scr.ScrService#getComponent(long)
+     */
+    public Component getComponent( long componentId )
+    {
+        final Collection<ComponentDescriptionDTO> descriptions = this.runtime.getComponentDescriptionDTOs();
+        for(final ComponentDescriptionDTO descDTO : descriptions )
+        {
+            final Collection<ComponentConfigurationDTO> configs = this.runtime.getComponentConfigurationDTOs(descDTO);
+            for(final ComponentConfigurationDTO configDTO : configs)
+            {
+                if ( configDTO.id == componentId )
+                {
+                    return new ComponentWrapper(this.context, this.runtime, descDTO, configDTO);
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * @see org.apache.felix.scr.ScrService#getComponents(java.lang.String)
+     */
+    public Component[] getComponents( final String componentName )
+    {
+        List<Component> result = new ArrayList<Component>();
+
+        final Collection<ComponentDescriptionDTO> descriptions = this.runtime.getComponentDescriptionDTOs();
+        for(final ComponentDescriptionDTO descDTO : descriptions )
+        {
+            if ( descDTO.name.equals(componentName) ) {
+                final Collection<ComponentConfigurationDTO> configs = this.runtime.getComponentConfigurationDTOs(descDTO);
+                ComponentConfigurationDTO configDTO = null;
+                if ( !configs.isEmpty() )
+                {
+                    configDTO = configs.iterator().next();
+                }
+                result.add(new ComponentWrapper(this.context, this.runtime, descDTO, configDTO));
+            }
+        }
+
+        return result.isEmpty() ? null : result.toArray( new Component[result.size()] );
+    }
+
+
+    private static final class ComponentWrapper implements Component
+    {
+        private final ComponentDescriptionDTO description;
+
+        private final ComponentConfigurationDTO configuration;
+
+        private final BundleContext bundleContext;
+
+        private final ServiceComponentRuntime runtime;
+
+        public ComponentWrapper(final BundleContext bundleContext,
+                final ServiceComponentRuntime runtime,
+                final ComponentDescriptionDTO description,
+                final ComponentConfigurationDTO configuration)
+        {
+            this.bundleContext = bundleContext;
+            this.description = description;
+            this.configuration = configuration;
+            this.runtime = runtime;
+        }
+
+        public long getId()
+        {
+            return configuration != null ? configuration.id : -1;
+        }
+
+        public String getName()
+        {
+            return description.name;
+        }
+
+        public int getState()
+        {
+            if ( configuration == null )
+            {
+                return Component.STATE_UNSATISFIED; // TODO Check!
+            }
+            final int s = configuration.state;
+            switch ( s )
+            {
+                case ComponentConfigurationDTO.ACTIVE : return Component.STATE_ACTIVE;
+                case ComponentConfigurationDTO.SATISFIED : return Component.STATE_ENABLED;
+                case ComponentConfigurationDTO.UNSATISFIED_CONFIGURATION : return Component.STATE_UNSATISFIED;
+                case ComponentConfigurationDTO.UNSATISFIED_REFERENCE : return Component.STATE_UNSATISFIED;
+                default: // satisfied
+                    return Component.STATE_ENABLED;
+            }
+        }
+
+        public Bundle getBundle()
+        {
+            return this.bundleContext.getBundle(this.description.bundle.id);
+        }
+
+        public String getFactory()
+        {
+            return this.description.factory;
+        }
+
+        public boolean isServiceFactory()
+        {
+            return false; // TODO
+        }
+
+        public String getClassName()
+        {
+            return this.description.implementationClass;
+        }
+
+        public boolean isDefaultEnabled()
+        {
+            return this.description.defaultEnabled;
+        }
+
+        public boolean isImmediate()
+        {
+            return this.description.immediate;
+        }
+
+        public String[] getServices()
+        {
+            return this.description.serviceInterfaces;
+        }
+
+        public Dictionary getProperties()
+        {
+            return new Hashtable<String, Object>(this.description.properties);
+        }
+
+        public Reference[] getReferences()
+        {
+            if ( this.configuration == null )
+            {
+                return null;
+            }
+
+            final List<Reference> result = new ArrayList<Reference>();
+            for(final ReferenceDTO dto : this.description.references)
+            {
+                SatisfiedReferenceDTO sRef = null;
+                for(final SatisfiedReferenceDTO r : this.configuration.satisfiedReferences)
+                {
+                    if ( r.name.equals(dto.name) )
+                    {
+                        sRef = r;
+                        break;
+                    }
+                }
+                result.add(new ReferenceWrapper(this.bundleContext, dto, sRef));
+            }
+
+            if ( result.isEmpty() )
+            {
+                return null;
+            }
+
+            return result.toArray(new Reference[result.size()]);
+        }
+
+        public ComponentInstance getComponentInstance()
+        {
+            // TODO - how do we want to enable this?
+            return null;
+        }
+
+        public String getActivate()
+        {
+            return this.description.activate;
+        }
+
+        public boolean isActivateDeclared()
+        {
+            return this.description.activate != null;
+        }
+
+        public String getDeactivate()
+        {
+            return this.description.deactivate;
+        }
+
+        public boolean isDeactivateDeclared()
+        {
+            return this.description.deactivate != null;
+        }
+
+        public String getModified()
+        {
+            return this.description.modified;
+        }
+
+        public String getConfigurationPolicy()
+        {
+            return this.description.configurationPolicy;
+        }
+
+        public String getConfigurationPid()
+        {
+            final String[] pids = this.description.configurationPid;
+            return pids[0];
+        }
+
+        public boolean isConfigurationPidDeclared()
+        {
+            return true;
+        }
+
+        public void enable()
+        {
+            this.runtime.enableComponent(this.description);
+        }
+
+        public void disable()
+        {
+            this.runtime.disableComponent(this.description);
+        }
+    }
+
+    private static final class ReferenceWrapper implements Reference
+    {
+        // constant for option single reference - 0..1
+        private static final String CARDINALITY_0_1 = "0..1";
+
+        // constant for option multiple reference - 0..n
+        private static final String CARDINALITY_0_N = "0..n";
+
+        // constant for required multiple reference - 1..n
+        private static final String CARDINALITY_1_N = "1..n";
+
+        // constant for static policy
+        private static final String POLICY_STATIC = "static";
+
+        // constant for reluctant policy option
+        private static final String POLICY_OPTION_RELUCTANT = "reluctant";
+
+        private final ReferenceDTO dto;
+
+        private final SatisfiedReferenceDTO satisfiedDTO;
+
+        private final BundleContext bundleContext;
+
+        public ReferenceWrapper(
+                final BundleContext bundleContext,
+                final ReferenceDTO dto,
+                final SatisfiedReferenceDTO satisfied)
+        {
+            this.bundleContext = bundleContext;
+            this.dto = dto;
+            this.satisfiedDTO = satisfied;
+        }
+
+        public String getName()
+        {
+            return dto.name;
+        }
+
+        public String getServiceName()
+        {
+            return dto.interfaceName;
+        }
+
+        public ServiceReference[] getServiceReferences()
+        {
+            if ( this.satisfiedDTO == null )
+            {
+                return null;
+            }
+            final List<ServiceReference<?>> refs = new ArrayList<ServiceReference<?>>();
+            for(ServiceReferenceDTO dto : this.satisfiedDTO.boundServices)
+            {
+                try
+                {
+                    final ServiceReference<?>[] serviceRefs = this.bundleContext.getServiceReferences((String)null,
+                            "(" + Constants.SERVICE_ID + "=" + String.valueOf(dto.id) + ")");
+                    if ( serviceRefs != null && serviceRefs.length > 0 )
+                    {
+                        refs.add(serviceRefs[0]);
+                    }
+                }
+                catch ( final InvalidSyntaxException ise)
+                {
+                    // ignore
+                }
+            }
+            return refs.toArray(new ServiceReference<?>[refs.size()]);
+        }
+
+        public ServiceReference<?>[] getBoundServiceReferences()
+        {
+            return this.getServiceReferences();
+        }
+
+        public boolean isSatisfied()
+        {
+            return this.satisfiedDTO != null;
+        }
+
+        public boolean isOptional()
+        {
+            return CARDINALITY_0_1.equals(dto.cardinality) || CARDINALITY_0_N.equals(dto.cardinality);
+        }
+
+        public boolean isMultiple()
+        {
+            return CARDINALITY_1_N.equals(dto.cardinality) || CARDINALITY_0_N.equals(dto.cardinality);
+        }
+
+        public boolean isStatic()
+        {
+            return POLICY_STATIC.equals(dto.policy);
+        }
+
+        public boolean isReluctant()
+        {
+            return POLICY_OPTION_RELUCTANT.equals(dto.policyOption);
+        }
+
+        public String getTarget()
+        {
+            return this.dto.target;
+        }
+
+        public String getBindMethodName()
+        {
+            return this.dto.bind;
+        }
+
+        public String getUnbindMethodName()
+        {
+            return this.dto.unbind;
+        }
+
+        public String getUpdatedMethodName()
+        {
+            return this.dto.unbind;
+        }
+    }
+}