Author: cziegeler
Date: Thu Feb 13 07:36:01 2020
New Revision: 1873971

URL: http://svn.apache.org/viewvc?rev=1873971&view=rev
Log:
FELIX-6220 : Refactor injection implementation

Added:
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/OpenStatus.java  
 (with props)
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/RefPair.java 
  (with props)
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ScrComponentContext.java
   (with props)
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/Annotations.java
   (with props)
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ClassUtils.java
   (with props)
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ComponentConstructorImpl.java
   (with props)
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ComponentMethodsImpl.java
   (with props)
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/DuplexReferenceMethods.java
   (with props)
    felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/inject/internal/
    
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/inject/internal/AnnotationTest.java
   (with props)
    
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/inject/methods/BindMethodTest.java
   (with props)
Removed:
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/Annotations.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ClassUtils.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/DuplexReferenceMethods.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/RefPair.java
    
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/inject/AnnotationTest.java
    
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/inject/BindMethodTest.java
Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ActivatorParameter.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/BaseParameter.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/BindParameters.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethods.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/LifecycleMethod.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ValueUtils.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/field/FieldHandler.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/field/FieldUtils.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/methods/ActivateMethod.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/methods/BaseMethod.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/methods/BindMethod.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractComponentManager.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/AbstractPrototypeRefPair.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentFactoryImpl.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/DependencyManager.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/MultiplePrototypeRefPair.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/ServiceFactoryComponentManager.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SinglePrototypeRefPair.java
    
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleRefPair.java
    
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/PackageIsolationTest.java
    
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/inject/methods/ActivateMethodTest.java
    
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/ConfiguredComponentHolderTest.java
    
felix/trunk/scr/src/test/java/org/apache/felix/scr/impl/manager/SingleComponentManagerTest.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java 
(original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/Activator.java Thu 
Feb 13 07:36:01 2020
@@ -41,7 +41,7 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.felix.scr.impl.config.ScrConfigurationImpl;
-import org.apache.felix.scr.impl.inject.ClassUtils;
+import org.apache.felix.scr.impl.inject.internal.ClassUtils;
 import org.apache.felix.scr.impl.logger.ScrLogger;
 import org.apache.felix.scr.impl.manager.ComponentHolder;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java 
(original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/ComponentRegistry.java 
Thu Feb 13 07:36:01 2020
@@ -34,7 +34,7 @@ import java.util.concurrent.ConcurrentHa
 import java.util.concurrent.ConcurrentMap;
 
 import org.apache.felix.scr.impl.inject.ComponentMethods;
-import org.apache.felix.scr.impl.inject.ComponentMethodsImpl;
+import org.apache.felix.scr.impl.inject.internal.ComponentMethodsImpl;
 import org.apache.felix.scr.impl.logger.ComponentLogger;
 import org.apache.felix.scr.impl.logger.ScrLogger;
 import org.apache.felix.scr.impl.manager.AbstractComponentManager;

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ActivatorParameter.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ActivatorParameter.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ActivatorParameter.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ActivatorParameter.java
 Thu Feb 13 07:36:01 2020
@@ -18,13 +18,11 @@
  */
 package org.apache.felix.scr.impl.inject;
 
-import org.apache.felix.scr.impl.manager.ComponentContextImpl;
-
 public final class ActivatorParameter extends BaseParameter
 {
     private final int m_reason;
 
-    public ActivatorParameter( ComponentContextImpl<?> componentContext, int 
reason )
+    public ActivatorParameter(ScrComponentContext componentContext, int reason)
     {
         super(componentContext);
         this.m_reason = reason;

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/BaseParameter.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/BaseParameter.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/BaseParameter.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/BaseParameter.java
 Thu Feb 13 07:36:01 2020
@@ -18,19 +18,17 @@
  */
 package org.apache.felix.scr.impl.inject;
 
-import org.apache.felix.scr.impl.manager.ComponentContextImpl;
-
 public abstract class BaseParameter
 {
-    private final ComponentContextImpl<?> m_componentContext;
+    private final ScrComponentContext m_componentContext;
 
-    public BaseParameter( ComponentContextImpl<?> componentContext )
+    public BaseParameter(ScrComponentContext componentContext)
     {
         this.m_componentContext = componentContext;
     }
 
 
-    public ComponentContextImpl<?> getComponentContext()
+    public ScrComponentContext getComponentContext()
     {
         return m_componentContext;
     }

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/BindParameters.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/BindParameters.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/BindParameters.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/BindParameters.java
 Thu Feb 13 07:36:01 2020
@@ -18,32 +18,19 @@
  */
 package org.apache.felix.scr.impl.inject;
 
-import org.apache.felix.scr.impl.manager.ComponentContextImpl;
-import org.apache.felix.scr.impl.manager.RefPair;
-import org.osgi.framework.BundleContext;
-
 public class BindParameters extends BaseParameter
 {
 
     private final RefPair<?, ?> refPair;
-    public BindParameters(ComponentContextImpl<?> componentContext, RefPair<?, 
?> refPair)
+
+    public BindParameters(ScrComponentContext componentContext, RefPair<?, ?> 
refPair)
     {
         super(componentContext);
         this.refPair = refPair;
     }
 
-    public RefPair getRefPair()
+    public RefPair<?, ?> getRefPair()
     {
         return refPair;
     }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public Object getServiceObject() {
-       return 
refPair.getServiceObject((ComponentContextImpl)this.getComponentContext());
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public boolean getServiceObject(BundleContext context) {
-       return 
refPair.getServiceObject((ComponentContextImpl)this.getComponentContext(), 
context);
-    }
 }

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentConstructor.java
 Thu Feb 13 07:36:01 2020
@@ -18,212 +18,15 @@
  */
 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 java.util.concurrent.atomic.AtomicInteger;
 
-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 implementation is used to construct a component instance object,
- * call the constructor and set the activation fields.
+ * This is used to construct a component instance object, call the constructor
+ * and set the activation fields.
  */
-public class ComponentConstructor<S>
-{
-    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];
-
-            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 );
-        }
-    }
+public interface ComponentConstructor<S> {
 
     /**
      * Create a new instance
@@ -233,112 +36,8 @@ public class ComponentConstructor<S>
      * @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, DependencyManager.OpenStatus<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 DependencyManager.OpenStatus<S, ?> status = 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 : status.getRefs(new 
AtomicInteger()))
-                    {
-                        if ( !refPair.isDeleted() && !refPair.isFailed() )
-                        {
-                            if ( refPair.getServiceObject(componentContext) == 
null
-                                    && (constructorArgTypes[i] == 
ValueType.ref_serviceType
-                                    || constructorArgTypes[i] == 
ValueType.ref_tuple
-                                    || constructorArgTypes[i] == 
ValueType.ref_logger
-                                    || constructorArgTypes[i] == 
ValueType.ref_formatterLogger) )
-                            {
-                                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;
-    }
+    <T> S newInstance(final ScrComponentContext componentContext,
+            final Map<ReferenceMetadata, OpenStatus<S, ?>> parameterMap)
+            throws Exception;
 
-    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/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethods.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethods.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethods.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethods.java
 Thu Feb 13 07:36:01 2020
@@ -30,6 +30,8 @@ public interface ComponentMethods<T>
             Class<T> implementationObjectClass,
             ComponentLogger logger);
 
+    ComponentConstructor<T> getConstructor();
+
     LifecycleMethod getActivateMethod();
 
     LifecycleMethod getDeactivateMethod();
@@ -37,7 +39,4 @@ public interface ComponentMethods<T>
     LifecycleMethod getModifiedMethod();
 
     ReferenceMethods getBindMethods(String refName );
-
-       ComponentConstructor<T> getConstructor();
-
 }

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/LifecycleMethod.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/LifecycleMethod.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/LifecycleMethod.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/LifecycleMethod.java
 Thu Feb 13 07:36:01 2020
@@ -18,8 +18,6 @@
  */
 package org.apache.felix.scr.impl.inject;
 
-import org.apache.felix.scr.impl.manager.ComponentContextImpl;
-
 /**
  * Interface for invocation one of the lifecycle methods:
  * <ul>
@@ -31,7 +29,7 @@ import org.apache.felix.scr.impl.manager
 public interface LifecycleMethod {
 
     MethodResult invoke(Object componentInstance,
-                        ComponentContextImpl<?> componentContext,
+            ScrComponentContext componentContext,
                         int reason,
                         MethodResult methodCallFailureResult);
 

Added: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/OpenStatus.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/OpenStatus.java?rev=1873971&view=auto
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/OpenStatus.java 
(added)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/OpenStatus.java 
Thu Feb 13 07:36:01 2020
@@ -0,0 +1,30 @@
+/*
+ * 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.inject;
+
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public interface OpenStatus<S, T>
+{
+    Collection<RefPair<S, T>> getRefs(AtomicInteger trackingCount);
+}

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/OpenStatus.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/OpenStatus.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/OpenStatus.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/RefPair.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/RefPair.java?rev=1873971&view=auto
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/RefPair.java 
(added)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/RefPair.java 
Thu Feb 13 07:36:01 2020
@@ -0,0 +1,77 @@
+/*
+ * 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.inject;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class RefPair<S, T>
+{
+    private final ServiceReference<T> ref;
+
+    volatile boolean failed;
+    volatile boolean deleted;
+
+    public RefPair( ServiceReference<T> ref )
+    {
+        this.ref = ref;
+    }
+
+    public ServiceReference<T> getRef()
+    {
+        return ref;
+    }
+
+    public abstract boolean getServiceObject(ScrComponentContext key, 
BundleContext context);
+
+    public abstract T getServiceObject(ScrComponentContext key);
+
+    public abstract boolean setServiceObject(ScrComponentContext key, T 
serviceObject);
+
+    public abstract void ungetServiceObjects(BundleContext context);
+
+    public abstract T ungetServiceObject(ScrComponentContext key);
+
+    public void markFailed( )
+    {
+        this.failed = true;
+    }
+
+    public void clearFailed() {
+        this.failed = false;
+    }
+
+    public boolean isFailed()
+    {
+        return failed;
+    }
+
+    public boolean isDeleted()
+    {
+        return deleted;
+    }
+
+    public void markDeleted()
+    {
+        this.deleted = true;
+    }
+}

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/RefPair.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/RefPair.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/RefPair.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ScrComponentContext.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ScrComponentContext.java?rev=1873971&view=auto
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ScrComponentContext.java
 (added)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ScrComponentContext.java
 Thu Feb 13 07:36:01 2020
@@ -0,0 +1,39 @@
+/*
+ * 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.inject;
+
+
+import java.util.Map;
+
+import org.apache.felix.scr.component.ExtComponentContext;
+import org.apache.felix.scr.impl.helper.ComponentServiceObjectsHelper;
+import org.apache.felix.scr.impl.logger.ComponentLogger;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
+
+
+public interface ScrComponentContext extends ExtComponentContext {
+
+    ComponentLogger getLogger();
+
+    ComponentMetadata getComponentMetadata();
+
+    ComponentServiceObjectsHelper getComponentServiceObjectsHelper();
+
+    Map<RefPair<?, ?>, Object> getBoundValues(final String key);
+}

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ScrComponentContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ScrComponentContext.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ScrComponentContext.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ValueUtils.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ValueUtils.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ValueUtils.java 
(original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ValueUtils.java 
Thu Feb 13 07:36:01 2020
@@ -25,9 +25,9 @@ import java.lang.reflect.Modifier;
 import java.util.Map;
 
 import org.apache.felix.scr.impl.helper.ReadOnlyDictionary;
+import org.apache.felix.scr.impl.inject.internal.Annotations;
+import org.apache.felix.scr.impl.inject.internal.ClassUtils;
 import org.apache.felix.scr.impl.logger.ComponentLogger;
-import org.apache.felix.scr.impl.manager.ComponentContextImpl;
-import org.apache.felix.scr.impl.manager.RefPair;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceReference;
@@ -271,7 +271,7 @@ public class ValueUtils {
             final String componentType,
             final ValueType type,
             final Class<?> targetType,
-            @SuppressWarnings("rawtypes") final ComponentContextImpl 
componentContext,
+            final ScrComponentContext componentContext,
             final RefPair<?, ?> refPair)
     {
         final Object value;
@@ -312,10 +312,9 @@ public class ValueUtils {
 
     private static Object getLogger(String componentType,
             final Class<?> targetType,
-            @SuppressWarnings("rawtypes") final ComponentContextImpl 
componentContext,
+            final ScrComponentContext componentContext,
             final RefPair<?, ?> refPair )
     {
-        @SuppressWarnings("unchecked")
         final Object factory = refPair.getServiceObject(componentContext);
         if ( factory != null )
         {

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/field/FieldHandler.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/field/FieldHandler.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/field/FieldHandler.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/field/FieldHandler.java
 Thu Feb 13 07:36:01 2020
@@ -29,16 +29,16 @@ import java.util.concurrent.CopyOnWriteA
 import java.util.concurrent.CopyOnWriteArraySet;
 
 import org.apache.felix.scr.impl.inject.BindParameters;
-import org.apache.felix.scr.impl.inject.ClassUtils;
 import org.apache.felix.scr.impl.inject.InitReferenceMethod;
 import org.apache.felix.scr.impl.inject.MethodResult;
+import org.apache.felix.scr.impl.inject.RefPair;
 import org.apache.felix.scr.impl.inject.ReferenceMethod;
+import org.apache.felix.scr.impl.inject.ScrComponentContext;
 import org.apache.felix.scr.impl.inject.ValueUtils;
 import org.apache.felix.scr.impl.inject.ValueUtils.ValueType;
 import org.apache.felix.scr.impl.inject.field.FieldUtils.FieldSearchResult;
+import org.apache.felix.scr.impl.inject.internal.ClassUtils;
 import org.apache.felix.scr.impl.logger.ComponentLogger;
-import org.apache.felix.scr.impl.manager.ComponentContextImpl;
-import org.apache.felix.scr.impl.manager.RefPair;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.log.LogService;
@@ -82,7 +82,7 @@ public class FieldHandler
         BIND,
         UNBIND,
         UPDATED
-    };
+    }
 
 
     private boolean initField(final Object componentInstance,
@@ -172,8 +172,7 @@ public class FieldHandler
                                      final BindParameters bp)
         throws InvocationTargetException
     {
-        @SuppressWarnings("rawtypes")
-               final ComponentContextImpl key = bp.getComponentContext();
+        final ScrComponentContext key = bp.getComponentContext();
         final RefPair<?, ?> refPair = bp.getRefPair();
 
         if ( !this.metadata.isMultiple() )
@@ -511,12 +510,12 @@ public class FieldHandler
             if ( methodType != METHOD_TYPE.UNBIND )
             {
                 //??? this resolves which we need.... better way?
-                if ( rawParameter.getServiceObject() == null
+                if 
(rawParameter.getRefPair().getServiceObject(rawParameter.getComponentContext()) 
== null
                   && handler.fieldExists( 
rawParameter.getComponentContext().getLogger() )
-                  && (handler.valueType == ValueType.ref_serviceType || 
handler.valueType == ValueType.ref_tuple 
+                  && (handler.valueType == ValueType.ref_serviceType || 
handler.valueType == ValueType.ref_tuple
                       || handler.valueType == ValueType.ref_logger || 
handler.valueType == ValueType.ref_formatterLogger) )
                 {
-                    return rawParameter.getServiceObject(context);
+                    return 
rawParameter.getRefPair().getServiceObject(rawParameter.getComponentContext(), 
context);
                 }
             }
             return true;

Modified: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/field/FieldUtils.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/field/FieldUtils.java?rev=1873971&r1=1873970&r2=1873971&view=diff
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/field/FieldUtils.java
 (original)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/field/FieldUtils.java
 Thu Feb 13 07:36:01 2020
@@ -24,7 +24,7 @@ import java.lang.reflect.Modifier;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
-import org.apache.felix.scr.impl.inject.ClassUtils;
+import org.apache.felix.scr.impl.inject.internal.ClassUtils;
 import org.apache.felix.scr.impl.logger.ComponentLogger;
 import org.osgi.service.log.LogService;
 

Added: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/Annotations.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/Annotations.java?rev=1873971&view=auto
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/Annotations.java
 (added)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/Annotations.java
 Thu Feb 13 07:36:01 2020
@@ -0,0 +1,451 @@
+/*
+ * 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.inject.internal;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.felix.scr.impl.helper.Coercions;
+import org.osgi.framework.Bundle;
+import org.osgi.service.component.ComponentException;
+
+public class Annotations
+{
+    /** Capture all methods defined by the annotation interface */
+    private static final Set<Method> ANNOTATION_METHODS = new HashSet<>();
+    static
+    {
+        for(final Method m : Annotation.class.getMethods())
+        {
+            ANNOTATION_METHODS.add(m);
+        }
+    }
+
+    /** Constant for the single element method */
+    private static final String VALUE_METHOD = "value";
+
+    /** Constant for the prefix constant. */
+    private static final String PREFIX_CONSTANT = "PREFIX_";
+
+    /**
+     * Check whether the provided type is a single element annotation.
+     * A single element annotation has a method named "value" and all
+     * other annotation methods must have a default value.
+     * @param clazz The provided type
+     * @return {@code true} if the type is a single element annotation.
+     */
+    static public boolean isSingleElementAnnotation(final Class<?> clazz)
+    {
+        boolean result = false;
+        if ( clazz.isAnnotation() )
+        {
+            result = true;
+            boolean hasValue = false;
+            for ( final Method method: clazz.getMethods() )
+            {
+                // filter out methods from Annotation
+                boolean isFromAnnotation = false;
+                for(final Method objMethod : ANNOTATION_METHODS)
+                {
+                    if ( objMethod.getName().equals(method.getName())
+                      && Arrays.equals(objMethod.getParameterTypes(), 
method.getParameterTypes()) )
+                    {
+                        isFromAnnotation = true;
+                        break;
+                    }
+                }
+                if ( isFromAnnotation )
+                {
+                    continue;
+                }
+                if ( VALUE_METHOD.equals(method.getName()) )
+                {
+                    hasValue = true;
+                    continue;
+                }
+                if ( method.getDefaultValue() == null )
+                {
+                    result = false;
+                    break;
+                }
+
+            }
+            if ( result )
+            {
+                result = hasValue;
+            }
+
+        }
+        return result;
+    }
+
+    static public String getPrefix(Class<?> clazz)
+    {
+        try
+        {
+            final Field f = clazz.getField(PREFIX_CONSTANT);
+            if ( Modifier.isStatic(f.getModifiers())
+                 && Modifier.isPublic(f.getModifiers())
+                 && Modifier.isFinal(f.getModifiers())
+                 && String.class.isAssignableFrom(f.getType()))
+            {
+                final Object value = f.get(null);
+                if ( value != null )
+                {
+                    return value.toString();
+                }
+            }
+        }
+        catch ( final Exception ignore)
+        {
+            // ignore
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+       static public <T> T toObject(Class<T> clazz, Map<String, Object> props, 
Bundle b, boolean supportsInterfaces )
+    {
+        final boolean isSingleElementAnn = isSingleElementAnnotation(clazz);
+        final String prefix = getPrefix(clazz);
+        final Map<String, Object> m = new HashMap<>();
+
+        final Map<String, Method> complexFields = new HashMap<>();
+        for ( final Method method: clazz.getMethods() )
+        {
+            final String name = method.getName();
+            final String mapped;
+            if ( isSingleElementAnn && name.equals(VALUE_METHOD) )
+            {
+                mapped = mapTypeNameToKey(clazz.getSimpleName());
+            }
+            else
+            {
+                mapped = mapIdentifierToKey(name);
+            }
+            final String key = (prefix == null ? mapped : 
prefix.concat(mapped));
+
+            Object raw = props.get(key);
+            Class<?> returnType = method.getReturnType();
+            Object cooked;
+            if ( returnType.isInterface() || returnType.isAnnotation())
+            {
+                complexFields.put(key, method);
+                continue;
+            }
+
+            try
+            {
+                if (returnType.isArray())
+                {
+                    Class<?> componentType = returnType.getComponentType();
+                    if (componentType.isInterface() || 
componentType.isAnnotation())
+                    {
+                        complexFields.put(key, method);
+                        continue;
+                    }
+                    cooked = coerceToArray(componentType, raw, b);
+                }
+                else
+                {
+                    cooked = Coercions.coerce(returnType, raw, b);
+                }
+            }
+            catch (ComponentException e)
+            {
+                cooked = new Invalid(e);
+            }
+            m.put( name, cooked );
+        }
+        if (!complexFields.isEmpty())
+        {
+            if (supportsInterfaces )
+            {
+                Map<String, List<Map<String, Object>>> nested = 
extractSubMaps(complexFields.keySet(), props);
+                for (Map.Entry<String, Method> entry: complexFields.entrySet())
+                {
+                    List<Map<String, Object>> proplist = 
nested.get(entry.getKey());
+                    if (proplist == null)
+                    {
+                       proplist = Collections.emptyList();
+                    }
+                    Method method = entry.getValue();
+                    Class<?> returnType  = method.getReturnType();
+                    if (returnType.isArray())
+                    {
+                        Class<?> componentType = returnType.getComponentType();
+                        Object result = Array.newInstance(componentType, 
proplist.size());
+                        for (int i = 0; i < proplist.size(); i++)
+                        {
+                            Map<String, Object> rawElement = proplist.get(i);
+                            Object cooked = toObject(componentType, 
rawElement, b, supportsInterfaces);
+                            Array.set(result, i, cooked);
+                        }
+                        m.put(method.getName(), result);
+                    }
+                    else
+                    {
+                        if (!proplist.isEmpty())
+                        {
+                            Object cooked = toObject(returnType, 
proplist.get(0), b, supportsInterfaces);
+                            m.put(method.getName(), cooked);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for (Method method: complexFields.values())
+                {
+                    m.put(method.getName(), new Invalid("Invalid annotation 
member type" + method.getReturnType().getName() + " for member: " + 
method.getName()));
+                }
+            }
+        }
+
+        final InvocationHandler h = new Handler(m, clazz);
+        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new 
Class<?>[] { clazz }, h);
+    }
+
+    private static Map<String, List<Map<String, Object>>> 
extractSubMaps(Collection<String> keys, Map<String, Object> map)
+    {
+        Map<String, List<Map<String, Object>>> result = new HashMap<>();
+        //Form a regexp to recognize all the keys as prefixes in the map keys.
+        StringBuilder b = new StringBuilder("(");
+        for (String key: keys)
+        {
+            b.append(key).append("|");
+        }
+        b.deleteCharAt(b.length() -1);
+        b.append(")\\.([0-9]*)\\.(.*)");
+        Pattern p = Pattern.compile(b.toString());
+        for (Map.Entry<String, Object> entry: map.entrySet())
+        {
+            String longKey = entry.getKey();
+            Matcher m = p.matcher(longKey);
+            if (m.matches())
+            {
+                String key = m.group(1);
+                int index = Integer.parseInt(m.group(2));
+                String subkey = m.group(3);
+                List<Map<String, Object>> subMapsForKey = result.get(key);
+                if (subMapsForKey == null)
+                {
+                    subMapsForKey = new ArrayList<>();
+                    result.put(key, subMapsForKey);
+                }
+                //make sure there is room for the possible new submap
+                for (int i = subMapsForKey.size(); i <= index; i++)
+                {
+                    subMapsForKey.add(new HashMap<String, Object>());
+                }
+                Map<String, Object> subMap = subMapsForKey.get(index);
+                subMap.put(subkey, entry.getValue());
+            }
+        }
+        return result;
+    }
+
+    private static Object coerceToArray(Class<?> componentType, Object raw, 
Bundle bundle)
+    {
+        if (raw == null)
+        {
+            return Array.newInstance(componentType, 0);
+        }
+        if (raw.getClass().isArray())
+        {
+            int size = Array.getLength(raw);
+            Object result = Array.newInstance(componentType, size);
+            for (int i = 0; i < size; i++)
+            {
+                Object rawElement = Array.get(raw, i);
+                Object cooked = Coercions.coerce(componentType, rawElement, 
bundle);
+                Array.set(result, i, cooked);
+            }
+            return result;
+        }
+        if (raw instanceof Collection)
+        {
+            @SuppressWarnings("rawtypes")
+                       Collection raws = (Collection) raw;
+            int size = raws.size();
+            Object result = Array.newInstance(componentType, size);
+            int i = 0;
+            for (Object rawElement: raws)
+            {
+                Object cooked = Coercions.coerce(componentType, rawElement, 
bundle);
+                Array.set(result, i++, cooked);
+            }
+            return result;
+
+        }
+        Object cooked = Coercions.coerce(componentType, raw, bundle);
+        Object result = Array.newInstance(componentType, 1);
+        Array.set(result, 0, cooked);
+        return result;
+
+    }
+
+    private static final Pattern p = 
Pattern.compile("(\\$_\\$)|(\\$\\$)|(\\$)|(__)|(_)");
+
+    static String mapIdentifierToKey(String name)
+    {
+        Matcher m = p.matcher(name);
+        StringBuffer b = new StringBuffer();
+        while (m.find())
+        {
+            String replacement = "";
+            if (m.group(1) != null) replacement = "-";
+            if (m.group(2) != null) replacement = "\\$";
+            if (m.group(3) != null) replacement = "";
+            if (m.group(4) != null) replacement = "_";
+            if (m.group(5) != null) replacement = ".";
+
+            m.appendReplacement(b, replacement);
+        }
+        m.appendTail(b);
+        return b.toString();
+    }
+
+    static String mapTypeNameToKey(String name)
+    {
+        final StringBuilder sb = new StringBuilder();
+        boolean lastLow = false;
+        for(final char c : name.toCharArray())
+        {
+            if ( lastLow && (Character.isLetter(c) || Character.isDigit(c)) && 
Character.isUpperCase(c) )
+            {
+                sb.append('.');
+            }
+            lastLow = false;
+            if ( (Character.isLetter(c) || Character.isDigit(c)) && 
Character.isLowerCase(c))
+            {
+                lastLow = true;
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+        return sb.toString();
+    }
+
+    private final static class Handler implements InvocationHandler
+    {
+        private final Map<String, Object> values;
+
+        private final Class<?> type;
+
+        public Handler(final Map<String, Object> values, final Class<?> type)
+        {
+            this.values = values;
+            this.type = type;
+        }
+
+        @Override
+        public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable
+        {
+            Object value = values.get(method.getName());
+            if (value instanceof Invalid)
+            {
+                throw new ComponentException(((Invalid)value).getMessage());
+            }
+            if ( value == null )
+            {
+                // check for methods of the Annotations class like hashCode, 
toString, equals etc.
+                if (method.getName().equals("hashCode") &&
+                    method.getParameterTypes().length == 0 )
+                {
+                    int hashCode = 0;
+                    for (final Map.Entry<String, Object> entry : 
values.entrySet()) {
+                        if (value instanceof Invalid) {
+                            continue;
+                        }
+                        hashCode += (127 * entry.getKey().hashCode()) ^ 
entry.getValue().hashCode();
+                    }
+                    value = hashCode;
+                }
+                else if (method.getName().equals("equals")
+                         && method.getParameterTypes().length == 1)
+                {
+                    final Object other = args[0];
+                    if (proxy == other)
+                    {
+                        value = true;
+                    }
+                    else
+                    {
+                        value = false;
+                        if (type.isInstance(other) && 
Proxy.isProxyClass(other.getClass()))
+                        {
+                            final InvocationHandler ih = 
Proxy.getInvocationHandler(other);
+                            if (ih instanceof Handler) {
+                                value = ((Handler)ih).values.equals(values);
+                            }
+                        }
+                    }
+                }
+                else if (method.getName().equals("toString")
+                        && method.getParameterTypes().length == 0 )
+                {
+                    value = type.getName() + " : " + values;
+                }
+                else if (method.getName().equals("annotationType")
+                         && method.getParameterTypes().length == 0 )
+                {
+                    value = type;
+                }
+            }
+            return value;
+        }
+    }
+
+    private final static class Invalid
+    {
+        private final String message;
+
+        public Invalid(ComponentException e)
+        {
+            this.message = e.getMessage();
+        }
+
+        public Invalid(String message)
+        {
+            this.message = message;
+        }
+
+        public String getMessage()
+        {
+            return message;
+        }
+    }
+
+}

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/Annotations.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/Annotations.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/Annotations.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ClassUtils.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ClassUtils.java?rev=1873971&view=auto
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ClassUtils.java
 (added)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ClassUtils.java
 Thu Feb 13 07:36:01 2020
@@ -0,0 +1,230 @@
+/*
+ * 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.inject.internal;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.scr.impl.logger.ComponentLogger;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.ComponentServiceObjects;
+import org.osgi.service.log.LogService;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+
+/**
+ * Utility methods for class handling used by method and field references.
+ */
+public class ClassUtils
+{
+
+    // name of the PackageAdmin class (this is a string to not create a 
reference to the class)
+    private static final String PACKAGEADMIN_CLASS = 
"org.osgi.service.packageadmin.PackageAdmin";
+
+    private static final Class<?> OBJECT_CLASS = Object.class;
+
+    public static final Class<?> SERVICE_REFERENCE_CLASS = 
ServiceReference.class;
+
+    public static final Class<?> COMPONENTS_SERVICE_OBJECTS_CLASS = 
ComponentServiceObjects.class;
+
+    public static final Class<?> MAP_CLASS = Map.class;
+    public static final Class<?> MAP_ENTRY_CLASS = Map.Entry.class;
+
+    public static final Class<?> COLLECTION_CLASS = Collection.class;
+    public static final Class<?> LIST_CLASS = List.class;
+
+    public static final Class<?> COMPONENT_CONTEXT_CLASS = 
ComponentContext.class;
+    public static final Class<?> BUNDLE_CONTEXT_CLASS = BundleContext.class;
+    public static final Class<?> INTEGER_CLASS = Integer.class;
+
+    public static final String LOGGER_CLASS = "org.osgi.service.log.Logger";
+    public static final String FORMATTER_LOGGER_CLASS = 
"org.osgi.service.log.FormatterLogger";
+    public static final String LOGGER_FACTORY_CLASS = 
"org.osgi.service.log.LoggerFactory";
+
+
+    // this bundle's context
+    private static BundleContext m_context;
+    // the package admin service (see BindMethod.getParameterClass)
+    public static volatile ServiceTracker<?, ?> m_packageAdmin;
+
+    /**
+     * Returns the class object representing the class of the field reference
+     * The class loader of the component class is used to load the service 
class.
+     * <p>
+     * It may well be possible, that the class loader of the target class 
cannot
+     * see the service object class, for example if the service reference is
+     * inherited from a component class of another bundle.
+     *
+     * @return The class object for the referred to service or 
<code>null</code>
+     *      if the class loader of the <code>targetClass</code> cannot see that
+     *      class.
+     */
+    public static Class<?> getClassFromComponentClassLoader(
+            final Class<?> componentClass,
+            final String className,
+            final ComponentLogger logger )
+    {
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log(
+                LogService.LOG_DEBUG,
+                "getReferenceClass: Looking for interface class {0} through 
loader of {1}", null,
+                    className, componentClass.getName() );
+        }
+
+        try
+        {
+            // need the class loader of the target class, which may be the
+            // system classloader, which case getClassLoader may retur null
+            ClassLoader loader = componentClass.getClassLoader();
+            if ( loader == null )
+            {
+                loader = ClassLoader.getSystemClassLoader();
+            }
+
+            final Class<?> referenceClass = loader.loadClass( className );
+            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log( LogService.LOG_DEBUG,
+                    "getParameterClass: Found class {0}", null, 
referenceClass.getName() );
+            }
+            return referenceClass;
+        }
+        catch ( final ClassNotFoundException cnfe )
+        {
+            // if we can't load the class, perhaps the method is declared in a
+            // super class so we try this class next
+        }
+
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log( LogService.LOG_DEBUG,
+                "getParameterClass: Not found through component class, using 
PackageAdmin service", null );
+        }
+
+        // try to load the class with the help of the PackageAdmin service
+        PackageAdmin pa = ( PackageAdmin ) getPackageAdmin();
+        if ( pa != null )
+        {
+            final String referenceClassPackage = className.substring( 0, 
className
+                .lastIndexOf( '.' ) );
+            ExportedPackage[] pkg = pa.getExportedPackages( 
referenceClassPackage );
+            if ( pkg != null )
+            {
+                for ( int i = 0; i < pkg.length; i++ )
+                {
+                    try
+                    {
+                        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+                        {
+                            logger.log(
+                                LogService.LOG_DEBUG,
+                                "getParameterClass: Checking Bundle {0}/{1}",
+                                null, 
pkg[i].getExportingBundle().getSymbolicName(), 
pkg[i].getExportingBundle().getBundleId() );
+                        }
+
+                        Class<?> referenceClass = 
pkg[i].getExportingBundle().loadClass( className );
+                        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+                        {
+                            logger.log( LogService.LOG_DEBUG,
+                                    "getParameterClass: Found class {0}", 
null,referenceClass.getName() );
+                        }
+                        return referenceClass;
+                    }
+                    catch ( ClassNotFoundException cnfe )
+                    {
+                        // exported package does not provide the interface !!!!
+                    }
+                }
+            }
+            else if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log( LogService.LOG_DEBUG,
+                    "getParameterClass: No bundles exporting package {0} 
found", null, referenceClassPackage );
+            }
+        }
+        else if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log( LogService.LOG_DEBUG,
+                "getParameterClass: PackageAdmin service not available, cannot 
find class", null );
+        }
+
+        // class cannot be found, neither through the component nor from an
+        // export, so we fall back to assuming Object
+        if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+        {
+            logger.log( LogService.LOG_DEBUG,
+                "getParameterClass: No class found, falling back to class 
Object", null );
+        }
+        return OBJECT_CLASS;
+    }
+
+    public static void setBundleContext( BundleContext bundleContext )
+    {
+        ClassUtils.m_context = bundleContext;
+    }
+
+    public static Object getPackageAdmin()
+    {
+        if (m_packageAdmin == null)
+        {
+            synchronized (ClassUtils.class)
+            {
+                if (m_packageAdmin == null)
+                {
+                    m_packageAdmin = new ServiceTracker(m_context, 
PACKAGEADMIN_CLASS,
+                        null);
+                    m_packageAdmin.open();
+                }
+            }
+        }
+
+        return m_packageAdmin.getService();
+    }
+
+    public static void close()
+    {
+        // close the PackageAdmin tracker now
+        if (m_packageAdmin != null)
+        {
+            m_packageAdmin.close();
+            m_packageAdmin = null;
+        }
+
+        // remove the reference to the component context
+        m_context = null;
+    }
+
+    /**
+     * Returns the name of the package to which the class belongs or an
+     * empty string if the class is in the default package.
+     */
+    public static String getPackageName( final Class<?> clazz )
+    {
+        String name = clazz.getName();
+        int dot = name.lastIndexOf( '.' );
+        return ( dot > 0 ) ? name.substring( 0, dot ) : "";
+    }
+
+}

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ClassUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ClassUtils.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ClassUtils.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ComponentConstructorImpl.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ComponentConstructorImpl.java?rev=1873971&view=auto
==============================================================================
--- 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ComponentConstructorImpl.java
 (added)
+++ 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ComponentConstructorImpl.java
 Thu Feb 13 07:36:01 2020
@@ -0,0 +1,347 @@
+/*
+ * 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.inject.internal;
+
+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 java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.felix.scr.impl.inject.ComponentConstructor;
+import org.apache.felix.scr.impl.inject.OpenStatus;
+import org.apache.felix.scr.impl.inject.RefPair;
+import org.apache.felix.scr.impl.inject.ScrComponentContext;
+import org.apache.felix.scr.impl.inject.ValueUtils;
+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.metadata.ComponentMetadata;
+import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
+import org.osgi.service.log.LogService;
+
+/**
+ * This implementation is used to construct a component instance object,
+ * call the constructor and set the activation fields.
+ */
+public class ComponentConstructorImpl<S> implements ComponentConstructor<S>
+{
+    private final Field[] activationFields;
+    private final ValueType[] activationFieldTypes;
+
+    private final Constructor<S> constructor;
+    private final ValueType[] constructorArgTypes;
+    private final ReferenceMetadata[] constructorRefs;
+
+    @SuppressWarnings("unchecked")
+    public ComponentConstructorImpl(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];
+
+            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.
+     */
+    @Override
+    public <T> S newInstance(final ScrComponentContext componentContext,
+            final Map<ReferenceMetadata, OpenStatus<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 OpenStatus<S, ?> status = 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 : status.getRefs(new 
AtomicInteger()))
+                    {
+                        if ( !refPair.isDeleted() && !refPair.isFailed() )
+                        {
+                            if ( refPair.getServiceObject(componentContext) == 
null
+                                    && (constructorArgTypes[i] == 
ValueType.ref_serviceType
+                                    || constructorArgTypes[i] == 
ValueType.ref_tuple
+                                    || constructorArgTypes[i] == 
ValueType.ref_logger
+                                    || constructorArgTypes[i] == 
ValueType.ref_formatterLogger) )
+                            {
+                                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();
+    }
+}

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ComponentConstructorImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ComponentConstructorImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Propchange: 
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ComponentConstructorImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url


Reply via email to