You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2017/10/30 14:50:45 UTC

svn commit: r1813772 - in /felix/trunk/osgi-r7/scr/src: main/java/org/apache/felix/scr/impl/inject/ main/java/org/apache/felix/scr/impl/manager/ main/java/org/apache/felix/scr/impl/metadata/ test/java/org/apache/felix/scr/integration/ test/java/org/apa...

Author: cziegeler
Date: Mon Oct 30 14:50:44 2017
New Revision: 1813772

URL: http://svn.apache.org/viewvc?rev=1813772&view=rev
Log:
FELIX-5455 : [R7] Constructor Injection. Supporting references

Added:
    felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorMultiReference.java   (with props)
    felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorSingleReference.java   (with props)
    felix/trunk/osgi-r7/scr/src/test/resources/integration_test_constructor.xml   (with props)
Removed:
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructorImpl.java
    felix/trunk/osgi-r7/scr/src/test/resources/integration_test_constructor_components.xml
Modified:
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ValueUtils.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurableComponentHolder.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java
    felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/ComponentConstructorTest.java
    felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/ComponentFieldActivationTest.java
    felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorComponent.java

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java Mon Oct 30 14:50:44 2017
@@ -18,33 +18,329 @@
  */
 package org.apache.felix.scr.impl.inject;
 
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
+import org.apache.felix.scr.impl.inject.ValueUtils.ValueType;
+import org.apache.felix.scr.impl.inject.field.FieldUtils;
+import org.apache.felix.scr.impl.logger.ComponentLogger;
 import org.apache.felix.scr.impl.manager.ComponentContextImpl;
 import org.apache.felix.scr.impl.manager.DependencyManager;
+import org.apache.felix.scr.impl.manager.RefPair;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
+import org.osgi.service.log.LogService;
 
 /**
- * This object describes a constructor for a component.
- * The name ComponentConstructor has been chosen to avoid a clash with the
- * existing Constructor class.
+ * This implementation is used to construct a component instance object,
+ * call the constructor and set the activation fields.
  */
-public interface ComponentConstructor<T> {
+public class ComponentConstructor<S>
+{
+    public static class ReferencePair<S>
+    {
+        public DependencyManager<S, ?> dependencyManager; // TODO check if we need this
+        public DependencyManager.OpenStatus<S, ?> openStatus;
+    }
+
+    private final Field[] activationFields;
+    private final ValueType[] activationFieldTypes;
+
+    private final Constructor<S> constructor;
+    private final ValueType[] constructorArgTypes;
+    private final ReferenceMetadata[] constructorRefs;
+
+    @SuppressWarnings("unchecked")
+    public ComponentConstructor(final ComponentMetadata componentMetadata,
+            final Class<S> componentClass,
+            final ComponentLogger logger)
+    {
+        // constructor injection
+        // get reference parameter map
+        final Map<Integer, List<ReferenceMetadata>> paramMap = ( componentMetadata.getNumberOfConstructorParameters() > 0 ? new HashMap<Integer, List<ReferenceMetadata>>() : null);
+        for ( final ReferenceMetadata refMetadata : componentMetadata.getDependencies())
+        {
+            if ( refMetadata.getParameterIndex() != null )
+            {
+                final int index = refMetadata.getParameterIndex();
+                if ( index > componentMetadata.getNumberOfConstructorParameters() )
+                {
+                    // if the index (starting at 0) is equal or higher than the number of constructor arguments
+                    // we log an error and ignore the reference
+                    logger.log(LogService.LOG_ERROR,
+                            "Ignoring reference {0} for constructor injection. Parameter index is too high.", null,
+                            refMetadata.getName() );
+                }
+                else if ( !refMetadata.isStatic() )
+                {
+                    // if the reference is dynamic, we log an error and ignore the reference
+                    logger.log(LogService.LOG_ERROR,
+                            "Ignoring reference {0} for constructor injection. Reference is dynamic.", null,
+                            refMetadata.getName() );
+                }
+                List<ReferenceMetadata> list = paramMap.get(index);
+                if ( list == null )
+                {
+                    list = new ArrayList<>();
+                    paramMap.put(index, list);
+                }
+                list.add(refMetadata);
+            }
+        }
+
+        // Search constructor
+        Constructor<S> found = null;
+        ValueType[] foundTypes = null;
+        ReferenceMetadata[] foundRefs = null;
+
+        final Constructor<?>[] constructors = componentClass.getConstructors();
+        for(final Constructor<?> c : constructors)
+        {
+            // we try each constructor with the right number of arguments
+            if ( c.getParameterTypes().length == componentMetadata.getNumberOfConstructorParameters() )
+            {
+                final Constructor<S> check = (Constructor<S>) c;
+                logger.log(LogService.LOG_DEBUG,
+                        "Checking constructor {0}", null,
+                        check );
+                // check argument types
+                if ( componentMetadata.getNumberOfConstructorParameters() > 0 )
+                {
+                    boolean hasFailure = false;
+                    final Class<?>[] argTypes = check.getParameterTypes();
+                    foundTypes = new ValueType[argTypes.length];
+                    foundRefs = new ReferenceMetadata[argTypes.length];
+                    for(int i=0; i<foundTypes.length;i++)
+                    {
+                        final List<ReferenceMetadata> refs = paramMap.get(i);
+                        if ( refs == null )
+                        {
+                            foundTypes[i] = ValueUtils.getValueType(argTypes[i]);
+                            if ( foundTypes[i] == ValueType.ignore )
+                            {
+                                logger.log(LogService.LOG_DEBUG,
+                                        "Constructor argument type {0} not supported by constructor injection: {1}", null,
+                                        i, argTypes[i] );
+                            }
+                        }
+                        else
+                        {
+                            for(final ReferenceMetadata ref : refs)
+                            {
+                                final ValueType t = ValueUtils.getReferenceValueType(componentClass, ref, argTypes[i], null, logger);
+                                if ( t != null )
+                                {
+                                    foundTypes[i] = t;
+                                    foundRefs[i] = ref;
+                                    break;
+                                }
+                            }
+                            if ( foundTypes[i] == null )
+                            {
+                                foundTypes[i] = ValueType.ignore;
+                            }
+                            else
+                            {
+                                if ( refs.size() > 1 )
+                                {
+                                    logger.log(LogService.LOG_ERROR,
+                                            "Several references for constructor injection of parameter {0}. Only {1} will be used out of: {2}.", null,
+                                            i, foundRefs[i].getName(), getNames(refs) );
+                                }
+                            }
+                        }
+
+                        if ( foundTypes[i] == ValueType.ignore )
+                        {
+                            hasFailure = true;
+                            break;
+                        }
+                    }
+                    if ( !hasFailure )
+                    {
+                        found = check;
+                        break;
+                    }
+                }
+                else
+                {
+                    found = (Constructor<S>) c;
+                    break;
+                }
+            }
+        }
+
+        this.constructor = found;
+        this.constructorArgTypes = foundTypes;
+        this.constructorRefs = foundRefs;
+
+        // activation fields
+        if ( componentMetadata.getActivationFields() != null )
+        {
+            activationFieldTypes = new ValueType[componentMetadata.getActivationFields().size()];
+            activationFields = new Field[activationFieldTypes.length];
 
-	public class ReferencePair<S> {
-		public DependencyManager<S, ?> dependencyManager; // TODO check if we need this
-		public DependencyManager.OpenStatus<S, ?> openStatus;
+            int index = 0;
+            for(final String fieldName : componentMetadata.getActivationFields() )
+            {
+                final FieldUtils.FieldSearchResult result = FieldUtils.searchField(componentClass, fieldName, logger);
+                if ( result == null || result.field == null )
+                {
+                    activationFieldTypes[index] = null;
+                    activationFields[index] = null;
+                }
+                else
+                {
+                    if ( result.usable )
+                    {
+                        activationFieldTypes[index] = ValueUtils.getValueType(result.field.getType());
+                        activationFields[index] = result.field;
+                    }
+                    else
+                    {
+                        activationFieldTypes[index] = ValueType.ignore;
+                        activationFields[index] = null;
+                    }
+                }
+
+                index++;
+            }
+        }
+        else
+        {
+            activationFieldTypes = ValueUtils.EMPTY_VALUE_TYPES;
+            activationFields = null;
+        }
+
+        if ( constructor == null )
+        {
+            logger.log(LogService.LOG_ERROR,
+                    "Constructor with {0} arguments not found. Component will fail.", null,
+                    componentMetadata.getNumberOfConstructorParameters() );
+        }
+        else
+        {
+            logger.log(LogService.LOG_DEBUG,
+                    "Found constructor with {0} arguments : {1}", null,
+                    componentMetadata.getNumberOfConstructorParameters(), found );
+        }
     }
 
-	/**
-	 * Create a new instance
-	 * @param componentContext The component context
-	 * @param parameterMap A map of reference parameters for handling references in the
-	 *                     constructor
-	 * @return The instance
-	 * @throws Exception If anything goes wrong, like constructor can't be found etc.
-	 */
-    <S> T newInstance(ComponentContextImpl<T> componentContext,
-    		           Map<ReferenceMetadata, ReferencePair<S>> parameterMap)
-    throws Exception;
+    /**
+     * Create a new instance
+     * @param componentContext The component context
+     * @param parameterMap A map of reference parameters for handling references in the
+     *                     constructor
+     * @return The instance
+     * @throws Exception If anything goes wrong, like constructor can't be found etc.
+     */
+    public <T> S newInstance(final ComponentContextImpl<S> componentContext,
+            final Map<ReferenceMetadata, ReferencePair<S>> parameterMap)
+    throws Exception
+    {
+        // no constructor -> throw
+        if ( constructor == null )
+        {
+            throw new InstantiationException("Constructor not found.");
+        }
+
+        final Object[] args;
+        if ( constructorArgTypes == null )
+        {
+            args = null;
+        }
+        else
+        {
+            args = new Object[constructorArgTypes.length];
+            for(int i=0; i<args.length; i++)
+            {
+                final ReferenceMetadata refMetadata = this.constructorRefs[i];
+                final ReferencePair<S> pair = refMetadata == null ? null : parameterMap.get(refMetadata);
+
+                if ( refMetadata == null )
+                {
+                    args[i] = ValueUtils.getValue(constructor.getDeclaringClass().getName(),
+                            constructorArgTypes[i],
+                            constructor.getParameterTypes()[i],
+                            componentContext,
+                            null);
+                }
+                else
+                {
+                    final List<Object> refs = refMetadata.isMultiple() ? new ArrayList<>() : null;
+                    Object ref = null;
+                    for(final RefPair<S, ?> refPair : pair.openStatus.refs)
+                    {
+                        if ( !refPair.isDeleted() && !refPair.isFailed() )
+                        {
+                            if ( refPair.getServiceObject(componentContext) == null
+                                    && (constructorArgTypes[i] == ValueType.ref_serviceType || constructorArgTypes[i] == ValueType.ref_tuple ) )
+                            {
+                                refPair.getServiceObject(componentContext, componentContext.getBundleContext());
+                            }
+                            ref = ValueUtils.getValue(constructor.getDeclaringClass().getName(),
+                                    constructorArgTypes[i],
+                                    constructor.getParameterTypes()[i],
+                                    componentContext,
+                                    refPair);
+                            if ( refMetadata.isMultiple() && ref != null )
+                            {
+                                refs.add(ref);
+                            }
+                        }
+                    }
+                    if ( !refMetadata.isMultiple())
+                    {
+                        if ( ref == null )
+                        {
+                            throw new InstantiationException("Unable to get service for reference " + refMetadata.getName());
+                        }
+                        args[i] = ref;
+                    }
+                    else
+                    {
+                        args[i] = refs;
+                    }
+                }
+            }
+        }
+        final S component = constructor.newInstance(args);
+
+        // activation fields
+        for(int i = 0; i<activationFieldTypes.length; i++)
+        {
+            if ( activationFieldTypes[i] != null && activationFieldTypes[i] != ValueType.ignore )
+            {
+                final Object value = ValueUtils.getValue(constructor.getDeclaringClass().getName(),
+                        activationFieldTypes[i],
+                        activationFields[i].getType(),
+                        componentContext,
+                        null); // null is ok as activation fields are not references
+                FieldUtils.setField(activationFields[i], component, value, componentContext.getLogger());
+            }
+        }
+
+        return component;
+    }
+
+    private String getNames(final List<ReferenceMetadata> refs)
+    {
+        final StringBuilder sb = new StringBuilder();
+        for(final ReferenceMetadata refMetadata : refs)
+        {
+            if ( sb.length() == 0 )
+            {
+                sb.append(refMetadata.getName());
+            }
+            else
+            {
+                sb.append(", ").append(refMetadata.getName());
+            }
+        }
+        return sb.toString();
+    }
 }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java Mon Oct 30 14:50:44 2017
@@ -103,7 +103,7 @@ public class ComponentMethodsImpl<T> imp
             }
         }
 
-    	    m_constructor = new ComponentConstructorImpl(componentMetadata, implementationObjectClass, logger);
+    	    m_constructor = new ComponentConstructor(componentMetadata, implementationObjectClass, logger);
     }
 
 	@Override

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ValueUtils.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ValueUtils.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ValueUtils.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ValueUtils.java Mon Oct 30 14:50:44 2017
@@ -80,10 +80,11 @@ public class ValueUtils {
         {
             return ValueType.config_map;
         }
-        else
+        else if ( typeClass.isAnnotation() )
         {
             return ValueType.config_annotation;
         }
+        return ValueType.ignore;
     }
 
     /**
@@ -178,23 +179,24 @@ public class ValueUtils {
         }
         else
         {
-            if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICE.equals(metadata.getFieldCollectionType()) )
+            String colType = field != null ? metadata.getFieldCollectionType() : metadata.getParameterCollectionType();
+            if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICE.equals(colType) )
             {
                 valueType = ValueType.ref_serviceType;
             }
-            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_REFERENCE.equals(metadata.getFieldCollectionType()) )
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_REFERENCE.equals(colType) )
             {
                 valueType = ValueType.ref_serviceReference;
             }
-            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICEOBJECTS.equals(metadata.getFieldCollectionType()) )
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICEOBJECTS.equals(colType) )
             {
                 valueType = ValueType.ref_serviceObjects;
             }
-            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_PROPERTIES.equals(metadata.getFieldCollectionType()) )
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_PROPERTIES.equals(colType) )
             {
                 valueType = ValueType.ref_map;
             }
-            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_TUPLE.equals(metadata.getFieldCollectionType()) )
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_TUPLE.equals(colType) )
             {
                 valueType = ValueType.ref_tuple;
             }
@@ -245,7 +247,7 @@ public class ValueUtils {
             }
         }
         // static references only allowed for replace strategy
-        if ( metadata.isStatic() && !metadata.isReplace() )
+        if ( field != null && metadata.isStatic() && !metadata.isReplace() )
         {
             logger.log( LogService.LOG_ERROR, "Update strategy for field {0} in class {1} only allowed for non static field references.", null,
                     metadata.getField(), componentClass );

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurableComponentHolder.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurableComponentHolder.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurableComponentHolder.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ConfigurableComponentHolder.java Mon Oct 30 14:50:44 2017
@@ -139,7 +139,7 @@ public abstract class ConfigurableCompon
     private volatile Promise<Void> m_enablePromise;
     private volatile Promise<Void> m_disablePromise = Promises.resolved(null);
 
-    private final ComponentMethods m_componentMethods;
+    private final ComponentMethods<S> m_componentMethods;
 
     private final ComponentLogger logger;
 
@@ -159,9 +159,9 @@ public abstract class ConfigurableCompon
         this.m_enabled = false;
     }
 
-    protected abstract ComponentMethods createComponentMethods();
+    protected abstract ComponentMethods<S> createComponentMethods();
 
-    protected ComponentMethods getComponentMethods() {
+    protected ComponentMethods<S> getComponentMethods() {
         return m_componentMethods;
     }
 

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java Mon Oct 30 14:50:44 2017
@@ -1290,7 +1290,7 @@ public class DependencyManager<S, T> imp
         return m_minCardinality == 0;
     }
 
-    private boolean cardinalitySatisfied(int serviceCount)
+    public boolean cardinalitySatisfied(int serviceCount)
     {
         return m_minCardinality <= serviceCount;
     }
@@ -1621,12 +1621,20 @@ public class DependencyManager<S, T> imp
                     null, getName());
             return false;
         }
+        final ReferenceMethod bindMethod = m_bindMethods.getBind();
+        return this.bindDependency(componentContext, bindMethod, status);
+    }
+
+    boolean bindDependency(final ComponentContextImpl<S> componentContext,
+            final ReferenceMethod bindMethod,
+            final OpenStatus<S, T> status)
+    {
         int serviceCount = 0;
-        for (RefPair<S, T> refPair : status.refs)
+        for (final RefPair<S, T> refPair : status.refs)
         {
             if (!refPair.isDeleted() && !refPair.isFailed())
             {
-                if (!doInvokeBindMethod(componentContext, refPair, status.trackingCount.get()))
+                if (!doInvokeBindMethod(componentContext, bindMethod, refPair, status.trackingCount.get()))
                 {
                     m_componentManager.getLogger().log(LogService.LOG_DEBUG,
                         "For dependency {0}, failed to invoke bind method on object {1}",
@@ -1773,7 +1781,7 @@ public class DependencyManager<S, T> imp
                 }
             }
             //edgeInfo open has been set, so binding has started.
-            return doInvokeBindMethod(componentContext, refPair, trackingCount);
+            return doInvokeBindMethod(componentContext, m_bindMethods.getBind(), refPair, trackingCount);
 
         }
         else
@@ -1785,10 +1793,11 @@ public class DependencyManager<S, T> imp
         }
     }
 
-    private boolean doInvokeBindMethod(ComponentContextImpl<S> componentContext, RefPair<S, T> refPair,
+    private boolean doInvokeBindMethod(ComponentContextImpl<S> componentContext,
+            final ReferenceMethod bindMethod,
+            RefPair<S, T> refPair,
         int trackingCount)
     {
-    	final ReferenceMethod bindMethod = m_bindMethods.getBind();
         if (!getServiceObject(componentContext, bindMethod, refPair))
         {
             m_componentManager.getLogger().log(LogService.LOG_WARNING,

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java Mon Oct 30 14:50:44 2017
@@ -62,7 +62,7 @@ public class ServiceFactoryComponentMana
      * @param container ComponentHolder for configuration management
      * @param componentMethods
      */
-    public ServiceFactoryComponentManager( ComponentContainer<S> container, ComponentMethods componentMethods )
+    public ServiceFactoryComponentManager( ComponentContainer<S> container, ComponentMethods<S> componentMethods )
     {
         super( container, componentMethods );
     }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java Mon Oct 30 14:50:44 2017
@@ -28,14 +28,17 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.felix.scr.impl.inject.BindParameters;
 import org.apache.felix.scr.impl.inject.ComponentConstructor;
 import org.apache.felix.scr.impl.inject.ComponentMethods;
 import org.apache.felix.scr.impl.inject.LifecycleMethod;
 import org.apache.felix.scr.impl.inject.MethodResult;
+import org.apache.felix.scr.impl.inject.ReferenceMethod;
 import org.apache.felix.scr.impl.manager.DependencyManager.OpenStatus;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.apache.felix.scr.impl.metadata.TargetedPID;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceFactory;
 import org.osgi.framework.ServiceReference;
@@ -76,12 +79,12 @@ public class SingleComponentManager<S> e
      * The constructor receives both the activator and the metadata
      * @param componentMethods
      */
-    public SingleComponentManager( final ComponentContainer<S> container, final ComponentMethods componentMethods )
+    public SingleComponentManager( final ComponentContainer<S> container, final ComponentMethods<S> componentMethods )
     {
         this(container, componentMethods, false);
     }
 
-    public SingleComponentManager( final ComponentContainer<S> container, final ComponentMethods componentMethods,
+    public SingleComponentManager( final ComponentContainer<S> container, final ComponentMethods<S> componentMethods,
             final boolean factoryInstance )
     {
         super( container, componentMethods, factoryInstance );
@@ -217,7 +220,6 @@ public class SingleComponentManager<S> e
     @SuppressWarnings("unchecked")
     protected S createImplementationObject( Bundle usingBundle, SetImplementationObject<S> setter, ComponentContextImpl<S> componentContext )
     {
-        final Class<S> implementationObjectClass;
         S implementationObject = null;
 
         // 1. Load the component implementation class
@@ -252,6 +254,33 @@ public class SingleComponentManager<S> e
             openStatusList.add(open);
             if ( dm.getReferenceMetadata().getParameterIndex() != null)
             {
+                if ( !dm.bindDependency(componentContext, new ReferenceMethod() {
+
+                        @Override
+                        public <S, T> MethodResult invoke(final Object componentInstance,
+                                final BindParameters rawParameter,
+                                final MethodResult methodCallFailureResult)
+                        {
+                            // nothing to do, binding will be done in constructor
+                            return MethodResult.VOID;
+                        }
+
+                        @Override
+                        public <S, T> boolean getServiceObject(
+                                final BindParameters rawParameter,
+                                final BundleContext context)
+                        {
+                            // nothing to do, binding will be done in constructor
+                            return true;
+                        }
+                    },(OpenStatus) open) )
+                {
+                    getLogger().log( LogService.LOG_DEBUG, "Cannot create component instance due to failure to bind reference {0}",
+                            null, dm.getName()  );
+                    failed = true;
+                    break;
+                }
+
                 final ComponentConstructor.ReferencePair<S> pair = new ComponentConstructor.ReferencePair<>();
                 pair.dependencyManager = dm;
                 pair.openStatus = open;
@@ -263,10 +292,6 @@ public class SingleComponentManager<S> e
         {
             try
             {
-                // 112.4.4 The class is retrieved with the loadClass method of the component's bundle
-                implementationObjectClass = (Class<S>) bundle.loadClass(
-                        getComponentMetadata().getImplementationClassName() )  ;
-
                 implementationObject = getComponentMethods().getConstructor().newInstance(
                         componentContext,
                         paramMap);
@@ -279,7 +304,7 @@ public class SingleComponentManager<S> e
                 this.setFailureReason(ie);
                 return null;
             }
-            catch ( Throwable t )
+            catch ( final Throwable t )
             {
                 // failed to instantiate, return null
                 getLogger().log( LogService.LOG_ERROR, "Error during instantiation of the implementation object", t );
@@ -466,11 +491,8 @@ public class SingleComponentManager<S> e
     @Override
     public Map<String, Object> getProperties()
     {
-
         if ( m_properties == null )
         {
-
-
             // 1. Merge all the config properties
             Map<String, Object> props = new HashMap<>();
             if ( m_configurationProperties != null )
@@ -595,26 +617,26 @@ public class SingleComponentManager<S> e
                 }
                 else
                 {
-                    getLogger().log( LogService.LOG_DEBUG, "Not updating service registration, no change in properties", null, null );
+                    getLogger().log( LogService.LOG_DEBUG, "Not updating service registration, no change in properties", null );
                 }
             }
-            catch ( IllegalStateException ise )
+            catch ( final IllegalStateException ise )
             {
                 // service has been unregistered asynchronously, ignore
             }
-            catch ( IllegalArgumentException iae )
+            catch ( final IllegalArgumentException iae )
             {
                 getLogger().log( LogService.LOG_ERROR,
                         "Unexpected configuration property problem when updating service registration", iae );
             }
-            catch ( Throwable t )
+            catch ( final Throwable t )
             {
                 getLogger().log( LogService.LOG_ERROR, "Unexpected problem when updating service registration", t );
             }
         }
         else
         {
-            getLogger().log( LogService.LOG_DEBUG, "No service registration to update", null, null );
+            getLogger().log( LogService.LOG_DEBUG, "No service registration to update", null );
         }
     }
 
@@ -958,7 +980,7 @@ public class SingleComponentManager<S> e
         {
             deleteComponent( ComponentConstants.DEACTIVATION_REASON_UNSPECIFIED );
         }
-        catch ( Throwable t )
+        catch ( final Throwable t )
         {
             getLogger().log( LogService.LOG_DEBUG, "Cannot delete incomplete component instance. Ignoring.", t );
         }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java Mon Oct 30 14:50:44 2017
@@ -134,6 +134,9 @@ public class ReferenceMetadata
     // Parameter index, set based on {@code m_parameter} after validation
     private Integer m_parameterIndex;
 
+    // Name of the value type for the parameter (optional, since DS 1.4)
+    private String m_parameter_collection_type;
+
     // Flags that store the values passed as strings
     private boolean m_isStatic = true;
     private boolean m_isOptional = false;
@@ -397,6 +400,21 @@ public class ReferenceMetadata
 		this.m_parameter = val;
 	}
 
+    /**
+     * Setter for the parameter value type attribute
+     * DS 1.4
+     * @param valuetype the parameter value type
+     */
+    public void setParameterCollectionType( final String valuetype )
+    {
+        if ( m_validated )
+        {
+            return;
+        }
+
+        m_parameter_collection_type = valuetype;
+    }
+
     /////////////////////////////////////////////// getters ///////////////////////////////////
 
 	/**
@@ -540,6 +558,7 @@ public class ReferenceMetadata
      * This method returns the correct value only after this metadata object has been validated
      * by a call to {@link #validate(ComponentMetadata, Logger)} and the validation has been
      * successful.
+     * DS 1.4
      * @return The parameter index , if no parameter is set this returns {@code -null}
      */
     public Integer getParameterIndex()
@@ -547,6 +566,17 @@ public class ReferenceMetadata
     	return m_parameterIndex;
     }
 
+    /**
+     * Get the value type of a parameter in the component implementation class that is used to hold
+     * the reference
+     * DS 1.4
+     * @return a String with the value type for the parameter
+     */
+    public String getParameterCollectionType()
+    {
+        return m_parameter_collection_type;
+    }
+
     // Getters for boolean values that determine both policy and cardinality
 
     /**
@@ -769,6 +799,26 @@ public class ReferenceMetadata
             {
                 throw componentMetadata.validationFailure( "Reference parameter value must be zero or higher: " + m_parameter );
             }
+            // parameter value type
+            if ( !m_isMultiple )
+            {
+                // value type must not be specified for unary references
+                if ( m_parameter_collection_type != null )
+                {
+                    throw componentMetadata.validationFailure( "Parameter value type must not be set for unary constructor references." );
+                }
+            }
+            else
+            {
+                if ( m_parameter_collection_type == null )
+                {
+                    setParameterCollectionType( FIELD_VALUE_TYPE_SERVICE );
+                }
+                else if ( !FIELD_VALUE_TYPE_VALID.contains( m_parameter_collection_type ) )
+                {
+                    throw componentMetadata.validationFailure( "Parameter value type must be one of " + FIELD_VALUE_TYPE_VALID );
+                }
+            }
         }
         m_validated = true;
     }

Modified: felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/ComponentConstructorTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/ComponentConstructorTest.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/ComponentConstructorTest.java (original)
+++ felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/ComponentConstructorTest.java Mon Oct 30 14:50:44 2017
@@ -43,7 +43,7 @@ public class ComponentConstructorTest ex
     static
     {
         // use different components
-        descriptorFile = "/integration_test_constructor_components.xml";
+        descriptorFile = "/integration_test_constructor.xml";
 
         // uncomment to enable debugging of this test class
         // paxRunnerVmOption = DEBUG_VM_OPTION;
@@ -61,7 +61,7 @@ public class ComponentConstructorTest ex
         ConstructorComponent cmp = this.getServiceFromConfiguration(cc, ConstructorComponent.class);
 
         final String msg = cmp.test();
-        assertNull(msg, msg);
+        assertNull(msg);
         disableAndCheck( cc );
     }
 
@@ -95,4 +95,34 @@ public class ComponentConstructorTest ex
 
         disableAndCheck( cc );
     }
+
+    @Test
+    public void test_constructor_singleRef() throws Exception
+    {
+        final String componentname = "ConstructorComponent.refsingle";
+
+        ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(componentname, ComponentConfigurationDTO.SATISFIED);
+        assertEquals(1, cc.description.init);
+
+        ConstructorComponent cmp = this.getServiceFromConfiguration(cc, ConstructorComponent.class);
+
+        final String msg = cmp.test();
+        assertNull(msg);
+        disableAndCheck( cc );
+    }
+
+    @Test
+    public void test_constructor_multiRef() throws Exception
+    {
+        final String componentname = "ConstructorComponent.refmulti";
+
+        ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(componentname, ComponentConfigurationDTO.SATISFIED);
+        assertEquals(1, cc.description.init);
+
+        ConstructorComponent cmp = this.getServiceFromConfiguration(cc, ConstructorComponent.class);
+
+        final String msg = cmp.test();
+        assertNull(msg);
+        disableAndCheck( cc );
+    }
 }

Modified: felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/ComponentFieldActivationTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/ComponentFieldActivationTest.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/ComponentFieldActivationTest.java (original)
+++ felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/ComponentFieldActivationTest.java Mon Oct 30 14:50:44 2017
@@ -67,25 +67,7 @@ public class ComponentFieldActivationTes
 
         disableAndCheck( cc );
     }
-/**
-    private <S> void failGetServiceFromConfiguration(ComponentConfigurationDTO dto, Class<S> clazz)
-    {
-        long id = dto.id;
-        String filter = "(component.id=" + id + ")";
-        Collection<ServiceReference<S>> srs;
-        try
-        {
-            srs = bundleContext.getServiceReferences( clazz, filter );
-            Assert.assertEquals( "Nothing for filter: " + filter, 1, srs.size() );
-            ServiceReference<S> sr = srs.iterator().next();
-            assertNull(bundleContext.getService( sr ));
-        }
-        catch ( InvalidSyntaxException e )
-        {
-            TestCase.fail( e.getMessage() );
-        }
-    }
-*/
+
     @Test
     public void test_field_activator_failure() throws Exception
     {

Modified: felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorComponent.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorComponent.java?rev=1813772&r1=1813771&r2=1813772&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorComponent.java (original)
+++ felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorComponent.java Mon Oct 30 14:50:44 2017
@@ -19,6 +19,9 @@
 package org.apache.felix.scr.integration.components;
 
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Map;
 
 import org.osgi.framework.BundleContext;
@@ -27,7 +30,14 @@ import org.osgi.service.component.Compon
 
 public class ConstructorComponent
 {
-    public @interface Config {
+    private enum Mode
+    {
+        FIELD,
+        SINGLE,
+        MULTI
+    }
+    public @interface Config
+    {
         String email() default "bar"; // property in component xml with value foo
         int port() default 443; // property in component xml with value 80
         long test() default 5; // no property in component xml, will be 0
@@ -41,10 +51,14 @@ public class ConstructorComponent
 
     private final Config annotation;
 
+    private final Mode mode;
+
     private boolean activated;
 
     private String activationTest;
 
+    private volatile Object ref;
+
     public ConstructorComponent(BundleContext b,
             ComponentContext c,
             Map<String, Object> configMap,
@@ -54,57 +68,143 @@ public class ConstructorComponent
         this.context = c;
         this.config = configMap;
         this.annotation = configAnnotation;
+        this.mode = Mode.FIELD;
+    }
+
+    public ConstructorComponent(final ConstructorSingleReference single)
+    {
+        this.bundle = null;
+        this.context = null;
+        this.config = null;
+        this.annotation = null;
+        this.mode = Mode.SINGLE;
+        this.ref = single;
+    }
+
+    public ConstructorComponent(final List<ConstructorMultiReference> list)
+    {
+        this.bundle = null;
+        this.context = null;
+        this.config = null;
+        this.annotation = null;
+        this.mode = Mode.MULTI;
+        this.ref = list;
     }
 
     @SuppressWarnings("unused")
-    private void activator() {
+    private void activator()
+    {
         // everything should be set here already
-        activationTest = check();
+        switch ( mode )
+        {
+            case FIELD :  activationTest = checkField();
+                          break;
+            case SINGLE : activationTest = checkSingle();
+                          break;
+            case MULTI : activationTest = checkMulti();
+                         break;
+        }
         activated = true;
     }
 
-    private String check()
+    @SuppressWarnings("rawtypes")
+    private String checkMulti()
+    {
+        if ( ref == null )
+        {
+            return "ref is null";
+        }
+        if ( !(ref instanceof List) )
+        {
+            return "ref is wrong type: " + ref.getClass();
+        }
+        if ( ((List)ref).size() != 3)
+        {
+            return "ref has wrong size: " + ((List)ref).size();
+        }
+        final List<String> names = new ArrayList<>(Arrays.asList("a", "b", "c"));
+        for(final Object obj : (List)ref)
+        {
+            if ( !(obj instanceof ConstructorMultiReference) )
+            {
+                return "ref has wrong type: " + obj.getClass();
+            }
+            names.remove(((ConstructorMultiReference)obj).getName());
+        }
+        if ( !names.isEmpty() )
+        {
+            return "Unexpected references found. Names not found: " + names;
+        }
+        return null;
+    }
+
+    private String checkSingle()
     {
-        if ( bundle == null ) {
+        if ( ref == null )
+        {
+            return "ref is null";
+        }
+        if ( !(ref instanceof ConstructorSingleReference) )
+        {
+            return "ref has wrong type: " + ref.getClass();
+        }
+        if ( !((ConstructorSingleReference)ref).getName().equals("single"))
+        {
+            return "ref has wrong name: " + ((ConstructorSingleReference)ref).getName().equals("single");
+        }
+        return null;
+    }
+
+    private String checkField()
+    {
+        if ( bundle == null )
+        {
             return "bundle is null";
         }
-        if ( context == null ) {
+        if ( context == null )
+        {
             return "context is null";
         }
-        if ( config == null ) {
+        if ( config == null )
+        {
             return "config is null";
         }
-        if ( annotation == null ) {
+        if ( annotation == null )
+        {
             return "annotation is null";
         }
-        if ( !annotation.email().equals("foo") ) {
+        if ( !annotation.email().equals("foo") )
+        {
             return "Wrong value for annotation.email: " + annotation.email();
         }
-        if ( annotation.port() != 80 ) {
+        if ( annotation.port() != 80 )
+        {
             return "Wrong value for annotation.port: " + annotation.port();
         }
-        if ( annotation.test() != 0 ) {
+        if ( annotation.test() != 0 )
+        {
             return "Wrong value for annotation.test: " + annotation.test();
         }
-        if ( !config.get("email").equals("foo") ) {
+        if ( !config.get("email").equals("foo") )
+        {
             return "Wrong value for map.email: " + config.get("email");
         }
-        if ( !config.get("port").equals("80") ) {
+        if ( !config.get("port").equals("80") )
+        {
             return "Wrong value for map.email: " + config.get("port");
         }
-        if ( config.get("test") != null ) {
+        if ( config.get("test") != null )
+        {
             return "Wrong value for map.test: " + config.get("test");
         }
         return null;
     }
 
     public String test() {
-        if ( !activated ) {
+        if ( !activated )
+        {
             return "activate not called";
         }
-        if ( activationTest != null ) {
-            return "not set before activate: " + activationTest;
-        }
-        return check();
+        return activationTest;
     }
 }

Added: felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorMultiReference.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorMultiReference.java?rev=1813772&view=auto
==============================================================================
--- felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorMultiReference.java (added)
+++ felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorMultiReference.java Mon Oct 30 14:50:44 2017
@@ -0,0 +1,40 @@
+/*
+ * 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.integration.components;
+
+public class ConstructorMultiReference
+{
+    public @interface Config
+    {
+        String name();
+    }
+
+    private String name;
+
+    @SuppressWarnings("unused")
+    private void activator(final Config config)
+    {
+        this.name = config.name();
+    }
+
+    public String getName()
+    {
+        return this.name;
+    }
+}

Propchange: felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorMultiReference.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorMultiReference.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorSingleReference.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorSingleReference.java?rev=1813772&view=auto
==============================================================================
--- felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorSingleReference.java (added)
+++ felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorSingleReference.java Mon Oct 30 14:50:44 2017
@@ -0,0 +1,40 @@
+/*
+ * 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.integration.components;
+
+public class ConstructorSingleReference
+{
+    public @interface Config
+    {
+        String name();
+    }
+
+    private String name;
+
+    @SuppressWarnings("unused")
+    private void activator(final Config config)
+    {
+        this.name = config.name();
+    }
+
+    public String getName()
+    {
+        return this.name;
+    }
+}

Propchange: felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorSingleReference.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/osgi-r7/scr/src/test/java/org/apache/felix/scr/integration/components/ConstructorSingleReference.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/trunk/osgi-r7/scr/src/test/resources/integration_test_constructor.xml
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/test/resources/integration_test_constructor.xml?rev=1813772&view=auto
==============================================================================
--- felix/trunk/osgi-r7/scr/src/test/resources/integration_test_constructor.xml (added)
+++ felix/trunk/osgi-r7/scr/src/test/resources/integration_test_constructor.xml Mon Oct 30 14:50:44 2017
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.4.0">
+
+    <!-- Use constructor -->
+    <scr:component name="ConstructorComponent.satisfied" enabled="false" activate="activator"
+                   init="4">
+        <implementation class="org.apache.felix.scr.integration.components.ConstructorComponent" />
+        <service factory="false">
+            <provide interface="org.apache.felix.scr.integration.components.ConstructorComponent"/>
+        </service>
+        <property name="email" value="foo"/>
+        <property name="port" value="80"/>
+    </scr:component>
+
+    <!-- Constructor does not exist -->
+    <scr:component name="ConstructorComponent.unsatisfied" enabled="false" activate="activator">
+        <implementation class="org.apache.felix.scr.integration.components.ConstructorComponent" />
+        <service factory="false">
+            <provide interface="org.apache.felix.scr.integration.components.ConstructorComponent"/>
+        </service>
+    </scr:component>
+
+    <!-- Use constructor - single reference -->
+    <scr:component name="ConstructorComponent.refsingle" enabled="false" activate="activator"
+                   init="1">
+        <implementation class="org.apache.felix.scr.integration.components.ConstructorComponent" />
+        <service factory="false">
+            <provide interface="org.apache.felix.scr.integration.components.ConstructorComponent"/>
+        </service>
+        <reference interface="org.apache.felix.scr.integration.components.ConstructorSingleReference"
+                   cardinality="1..1"
+                   parameter="0"/>
+    </scr:component>
+
+    <!-- Use constructor - multi reference -->
+    <scr:component name="ConstructorComponent.refmulti" enabled="false" activate="activator"
+                   init="1">
+        <implementation class="org.apache.felix.scr.integration.components.ConstructorComponent" />
+        <service factory="false">
+            <provide interface="org.apache.felix.scr.integration.components.ConstructorComponent"/>
+        </service>
+        <reference interface="org.apache.felix.scr.integration.components.ConstructorMultiReference"
+                   cardinality="1..n"
+                   parameter="0"/>
+    </scr:component>
+
+    <!-- References -->
+    <scr:component name="SingleReference" activate="activator">
+        <implementation class="org.apache.felix.scr.integration.components.ConstructorSingleReference" />
+        <service factory="false">
+            <provide interface="org.apache.felix.scr.integration.components.ConstructorSingleReference"/>
+        </service>
+        <property name="name" value="single"/>
+    </scr:component>
+    <scr:component name="MultiReferenceA" activate="activator">
+        <implementation class="org.apache.felix.scr.integration.components.ConstructorMultiReference" />
+        <service factory="false">
+            <provide interface="org.apache.felix.scr.integration.components.ConstructorMultiReference"/>
+        </service>
+        <property name="name" value="a"/>
+    </scr:component>
+    <scr:component name="MultiReferenceB" activate="activator">
+        <implementation class="org.apache.felix.scr.integration.components.ConstructorMultiReference" />
+        <service factory="false">
+            <provide interface="org.apache.felix.scr.integration.components.ConstructorMultiReference"/>
+        </service>
+        <property name="name" value="b"/>
+    </scr:component>
+    <scr:component name="MultiReferenceC" activate="activator">
+        <implementation class="org.apache.felix.scr.integration.components.ConstructorMultiReference" />
+        <service factory="false">
+            <provide interface="org.apache.felix.scr.integration.components.ConstructorMultiReference"/>
+        </service>
+        <property name="name" value="c"/>
+    </scr:component>
+</components>

Propchange: felix/trunk/osgi-r7/scr/src/test/resources/integration_test_constructor.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/osgi-r7/scr/src/test/resources/integration_test_constructor.xml
------------------------------------------------------------------------------
    svn:keywords = Id