felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1777960 - in /felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl: helper/ inject/ manager/ metadata/ runtime/
Date Mon, 09 Jan 2017 13:28:57 GMT
Author: cziegeler
Date: Mon Jan  9 13:28:57 2017
New Revision: 1777960

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

Modified:
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/helper/ConstructorMethod.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/ConstructorMethodImpl.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldUtils.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.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/SingleComponentManager.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ReferenceMetadata.java
    felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/helper/ConstructorMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/helper/ConstructorMethod.java?rev=1777960&r1=1777959&r2=1777960&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/helper/ConstructorMethod.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/helper/ConstructorMethod.java Mon Jan  9 13:28:57 2017
@@ -18,7 +18,10 @@
  */
 package org.apache.felix.scr.impl.helper;
 
-import org.osgi.service.component.ComponentContext;
+import java.util.TreeMap;
+
+import org.apache.felix.scr.impl.manager.ComponentContextImpl;
+import org.apache.felix.scr.impl.manager.DependencyManager;
 
 /**
  * This object describes a constructor for a component.
@@ -34,15 +37,19 @@ public interface ConstructorMethod<T> {
 	 * @param logger A logger 
 	 * @return The instance
 	 */
-    T newInstance(Class<T> componentClass,
-    		           ComponentContext componentContext,
+    <S> T newInstance(Class<T> componentClass,
+    		           ComponentContextImpl<T> componentContext,
+    		           TreeMap<Integer, DependencyManager<S, ?>> parameterMap,
                        SimpleLogger logger )
     throws Exception;
     
     public ConstructorMethod<Object> DEFAULT = new ConstructorMethod<Object>() {
 		
 		@Override
-		public Object newInstance(Class<Object> componentClass, ComponentContext componentContext, SimpleLogger logger) 
+		public <S> Object newInstance(Class<Object> componentClass, 
+				ComponentContextImpl<Object> componentContext, 
+				TreeMap<Integer, DependencyManager<S, ?>> parameterMap,
+				SimpleLogger logger) 
 				throws Exception
 		{
             // 112.4.4 The class must be public and have a public constructor without arguments so component instances

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=1777960&r1=1777959&r2=1777960&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 Jan  9 13:28:57 2017
@@ -56,7 +56,7 @@ public class ComponentMethodsImpl<T> imp
         boolean supportsInterfaces = componentMetadata.isConfigureWithInterfaces();
         
         m_activateMethod = new ActivateMethod( 
-        		ConstructorMethodImpl.CONSTRUCTOR_MARKER.equals(componentMetadata.getActivate()) ? null : componentMetadata.getActivate(), 
+        		ComponentMetadata.CONSTRUCTOR_MARKER.equals(componentMetadata.getActivate()) ? null : componentMetadata.getActivate(), 
         		componentMetadata.isActivateDeclared(), 
         		implementationObjectClass, 
         		dsVersion, 
@@ -88,9 +88,11 @@ public class ComponentMethodsImpl<T> imp
             bindMethodMap.put( refName, methods );
         }
         
-        if ( componentMetadata.getActivationFields() != null )
+        // special constructor handling with activation fields and/or constructor injection
+        if ( componentMetadata.getActivationFields() != null 
+             || ComponentMetadata.CONSTRUCTOR_MARKER.equals(componentMetadata.getActivate()))
         {
-        	m_constructor = new ConstructorMethodImpl(componentMetadata);
+        	m_constructor = new ConstructorMethodImpl();
         }
         else
         {
@@ -99,7 +101,7 @@ public class ComponentMethodsImpl<T> imp
     }
 
 	@Override
-   public ComponentMethod getActivateMethod()
+    public ComponentMethod getActivateMethod()
     {
         return m_activateMethod;
     }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java?rev=1777960&r1=1777959&r2=1777960&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java Mon Jan  9 13:28:57 2017
@@ -18,13 +18,16 @@
  */
 package org.apache.felix.scr.impl.inject;
 
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
-import java.util.Map;
+import java.util.TreeMap;
 
 import org.apache.felix.scr.impl.helper.ConstructorMethod;
 import org.apache.felix.scr.impl.helper.SimpleLogger;
+import org.apache.felix.scr.impl.manager.ComponentContextImpl;
+import org.apache.felix.scr.impl.manager.DependencyManager;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
-import org.osgi.service.component.ComponentContext;
+import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
 import org.osgi.service.log.LogService;
 
 /**
@@ -33,61 +36,48 @@ import org.osgi.service.log.LogService;
  */
 public class ConstructorMethodImpl<T> implements ConstructorMethod<T> 
 {
-	/** If the activate method has this value, a constructor is used instead. */
-	public static final String CONSTRUCTOR_MARKER = "-init-";
-	
-    private enum ParamType {
-        failure,
-        ignore,
-        componentContext,
-        bundleContext,
-        map,
-        annotation
-    }
-
-    private final ComponentMetadata m_metadata;
+    private volatile boolean m_initialized = false;
     
-    private final ParamType[] EMPTY_PARAMS = new ParamType[0];
-    
-    private volatile ParamType[] m_paramTypes;
+    private volatile FieldUtils.ValueType[] m_paramTypes;
     private volatile Field[] m_fields;
     
-	public ConstructorMethodImpl( final ComponentMetadata metadata)
-	{
-		this.m_metadata = metadata;
-
-	}
-	
+    private volatile Constructor<T> m_constructor;
+    private volatile FieldUtils.ValueType[] m_constructorArgTypes;
+    
 	@SuppressWarnings("unchecked")
 	@Override
-	public T newInstance(Class<T> componentClass, ComponentContext componentContext, SimpleLogger logger)
-			throws Exception
+	public <S> T newInstance(Class<T> componentClass, 
+             			 ComponentContextImpl<T> componentContext, 
+                         TreeMap<Integer, DependencyManager<S, ?>> parameterMap,
+			             SimpleLogger logger)
+    throws Exception
 	{
-		if ( m_paramTypes == null ) {
-			if ( m_metadata.getActivationFields() != null )
+		if ( !m_initialized ) {
+			// activation fields
+			if ( componentContext.getComponentMetadata().getActivationFields() != null )
 			{
-				m_paramTypes = new ParamType[m_metadata.getActivationFields().size()];
+				m_paramTypes = new FieldUtils.ValueType[componentContext.getComponentMetadata().getActivationFields().size()];
 				m_fields = new Field[m_paramTypes.length];
 			
 				int index = 0;
-				for(final String fieldName : m_metadata.getActivationFields() ) 
+				for(final String fieldName : componentContext.getComponentMetadata().getActivationFields() ) 
 				{
 					final FieldUtils.FieldSearchResult result = FieldUtils.findField(componentClass, fieldName, logger);
 					if ( result == null )
 					{
-						m_paramTypes[index] = ParamType.failure;
+						m_paramTypes[index] = null;
 						m_fields[index] = null;
 					}
 					else
 					{
 						if ( result.usable )
 						{
-							m_paramTypes[index] = getFieldType(result.field);
+							m_paramTypes[index] = FieldUtils.getValueType(result.field.getType());
 							m_fields[index] = result.field;
 						}
 						else
 						{
-							m_paramTypes[index] = ParamType.ignore;
+							m_paramTypes[index] = FieldUtils.ValueType.ignore;
 							m_fields[index] = null;
 						}
 					}
@@ -96,101 +86,115 @@ public class ConstructorMethodImpl<T> im
 			}
 			else
 			{
-				m_paramTypes = EMPTY_PARAMS;
+				m_paramTypes = FieldUtils.EMPTY_TYPES;
 				m_fields = null;
 			}
+			// constructor injection
+			if ( ComponentMetadata.CONSTRUCTOR_MARKER.equals(componentContext.getComponentMetadata().getActivate() ) ) 
+			{
+				// TODO search constructor
+				m_constructor = null;
+				
+				boolean hasFailure = false;
+				final Class<?>[] argTypes = m_constructor.getParameterTypes();
+				m_constructorArgTypes = new FieldUtils.ValueType[argTypes.length];
+				for(int i=0;i<m_constructorArgTypes.length;i++)
+				{
+					// TODO get reference metadata
+					ReferenceMetadata reference = null;
+					for(final ReferenceMetadata ref : componentContext.getComponentMetadata().getDependencies())
+					{
+						if ( ref.getParamterIndex() == i )
+						{
+							reference = ref;
+							break;
+						}
+					}
+					if ( reference == null )
+					{
+						m_constructorArgTypes[i] = FieldUtils.getValueType(argTypes[i]);
+					}
+					else 
+					{
+						m_constructorArgTypes[i] = FieldUtils.getReferenceValueType(componentClass, null, argTypes[i], null, logger);
+					}
+					if ( m_constructorArgTypes[i] == FieldUtils.ValueType.ignore )
+					{
+						hasFailure = true;
+						break;
+					}
+				}
+				if ( hasFailure )
+				{
+					m_constructor = null;
+				}
+			}
+			
+			// done
+			m_initialized = true;
 		}
 		
-		// if we have fields and one is in state failure we can directly throw
-		for(final ParamType t : m_paramTypes)
+		// if we have fields and one is in state failure (type == null) we can directly throw
+		for(final FieldUtils.ValueType t : m_paramTypes)
 		{
-			if ( t == ParamType.failure )
+			if ( t == null )
 			{
 				throw new InstantiationException("Field not found; Component will fail");
 			}
 		}
 
+		// constructor
 		final T component;
-		if ( CONSTRUCTOR_MARKER.equals(m_metadata.getActivate() ) ) 
+		if ( ComponentMetadata.CONSTRUCTOR_MARKER.equals(componentContext.getComponentMetadata().getActivate() ) ) 
 		{
-		    component = null;
-		    throw new IllegalStateException("Constructor init not implemented yet");
+			if ( m_constructor == null )
+			{
+				throw new InstantiationException("Constructor not found; Component will fail");				
+			}
+			final Object[] args = new Object[m_constructorArgTypes.length];
+			for(int i=0; i<args.length; i++) 
+			{
+				// TODO key pair for reference
+				args[i] = FieldUtils.getValue(m_constructorArgTypes[i], 
+						m_constructor.getParameterTypes()[i], 
+						componentContext, 
+						null);
+			}
+		    component = m_constructor.newInstance(args);
 		}
 		else
 		{
-		    component = (T)ConstructorMethod.DEFAULT.newInstance((Class<Object>)componentClass, componentContext, logger);
+		    component = (T)ConstructorMethod.DEFAULT.newInstance((Class<Object>)componentClass, 
+		    		(ComponentContextImpl<Object>)componentContext, null, logger);
 		}
+		
+		// activation fields
 		for(int i = 0; i<m_paramTypes.length; i++)
 		{
-			setField(componentClass, m_fields[i], m_paramTypes[i], component, componentContext, logger);
+	    	if ( m_paramTypes[i] != FieldUtils.ValueType.ignore )
+	    	{
+		        final Object value = FieldUtils.getValue(m_paramTypes[i], 
+		        		m_fields[i].getType(), 
+		        		(ComponentContextImpl<T>) componentContext, 
+		        		null);
+				this.setField(m_fields[i], component, value, logger);
+	    	}
 		}
 		
 		return component;
 	}
 
-	/**
-     * Get the field parameter type.
-     * @param f The field
-     * @return The parameter type of the field
-     */
-    private ParamType getFieldType( final Field f)
-    {
-        final Class<?> fieldType = f.getType();
-        if ( fieldType == ClassUtils.COMPONENT_CONTEXT_CLASS )
-        {
-        	return ParamType.componentContext;
-        }
-        else if ( fieldType == ClassUtils.BUNDLE_CONTEXT_CLASS )
-        {
-        	return ParamType.bundleContext;
-        }
-        else if ( fieldType == ClassUtils.MAP_CLASS )
-        {
-        	return ParamType.map;
-        }
-        else
-        {
-        	return ParamType.annotation;
-        }
-    }
-    
+   
     /**
      * Set the field, type etc.
      * @param f The field
      * @param logger The logger
      */
-    @SuppressWarnings("unchecked")
-	private void setField( final Class<T> componentClass, 
-    		final Field f, 
-    		final ParamType type,
+	private void setField( final Field f, 
     		final T component,
-    		final ComponentContext componentContext,
+    		final Object value,
     		final SimpleLogger logger )
     {
-    	if ( type == ParamType.ignore )
-    	{
-    		return;
-    	}
-        final Object value;
-        if ( type == ParamType.componentContext )
-        {
-    	    value = componentContext;
-        }
-        else if ( type == ParamType.bundleContext )
-        {
-            value = componentContext.getBundleContext();
-        }
-        else if ( type == ParamType.map )
-        {
-            // note: getProperties() returns a ReadOnlyDictionary which is a Map
-        	value = componentContext.getProperties();
-        }
-        else
-        {
-        	value = Annotations.toObject(f.getType(),
-                (Map<String, Object>) componentContext.getProperties(),
-                componentContext.getBundleContext().getBundle(), m_metadata.isConfigureWithInterfaces());
-        }
         try
         {
             f.set(component, value);
@@ -198,12 +202,13 @@ public class ConstructorMethodImpl<T> im
         catch ( final IllegalArgumentException iae )
         {
             logger.log( LogService.LOG_ERROR, "Field {0} in component {1} can't be set", new Object[]
-                    {f.getName(), componentClass}, iae );
+                    {f.getName(), component.getClass().getName()}, iae );
         }
         catch ( final IllegalAccessException iae )
         {
             logger.log( LogService.LOG_ERROR, "Field {0} in component {1} can't be set", new Object[]
-                    {f.getName(), componentClass}, iae );
+                    {f.getName(), component.getClass().getName()}, iae );
         }
     }
+    
 }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java?rev=1777960&r1=1777959&r2=1777960&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java Mon Jan  9 13:28:57 2017
@@ -33,14 +33,12 @@ import java.util.concurrent.CopyOnWriteA
 
 import org.apache.felix.scr.impl.helper.InitReferenceMethod;
 import org.apache.felix.scr.impl.helper.MethodResult;
-import org.apache.felix.scr.impl.helper.ReadOnlyDictionary;
 import org.apache.felix.scr.impl.helper.ReferenceMethod;
 import org.apache.felix.scr.impl.helper.SimpleLogger;
 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.framework.ServiceReference;
 import org.osgi.service.log.LogService;
 
 /**
@@ -48,15 +46,6 @@ import org.osgi.service.log.LogService;
  */
 public class FieldHandler
 {
-    private enum ParamType {
-        serviceReference,
-        serviceObjects,
-        serviceType,
-        map,
-        tuple,
-        ignore
-    }
-
     /** The reference metadata. */
     private final ReferenceMetadata metadata;
 
@@ -67,7 +56,7 @@ public class FieldHandler
     private volatile Field field;
 
     /** Value type. */
-    private volatile ParamType valueType;
+    private volatile FieldUtils.ValueType valueType;
 
     /** State handling. */
     private volatile State state;
@@ -122,135 +111,6 @@ public class FieldHandler
         }
     }
 
-
-
-    /**
-     * Validate the field, type etc.
-     * @param f The field
-     * @param logger The logger
-     * @return The field if it's valid, {@code null} otherwise.
-     */
-    private Field validateField( final Field f, final SimpleLogger logger )
-    {
-        final Class<?> fieldType = f.getType();
-        final Class<?> referenceType = ClassUtils.getClassFromComponentClassLoader(
-                this.componentClass, metadata.getInterface(), logger);
-
-        // unary reference
-        if ( !metadata.isMultiple() )
-        {
-            if ( fieldType.isAssignableFrom(referenceType) )
-            {
-                valueType = ParamType.serviceType;
-            }
-            else if ( fieldType == ClassUtils.SERVICE_REFERENCE_CLASS )
-            {
-                valueType = ParamType.serviceReference;
-            }
-            else if ( fieldType == ClassUtils.COMPONENTS_SERVICE_OBJECTS_CLASS )
-            {
-                valueType = ParamType.serviceObjects;
-            }
-            else if ( fieldType == ClassUtils.MAP_CLASS )
-            {
-                valueType = ParamType.map;
-            }
-            else if ( fieldType == ClassUtils.MAP_ENTRY_CLASS )
-            {
-                valueType = ParamType.tuple;
-            }
-            else
-            {
-                logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}", new Object[]
-                        {metadata.getField(), this.componentClass, fieldType.getName()}, null );
-                valueType = ParamType.ignore;
-            }
-
-            // if the field is dynamic, it has to be volatile (field is ignored, case logged) (112.3.8.1)
-            if ( !metadata.isStatic() && !Modifier.isVolatile(f.getModifiers()) ) {
-                logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must be declared volatile to handle a dynamic reference", new Object[]
-                        {metadata.getField(), this.componentClass}, null );
-                valueType = ParamType.ignore;
-            }
-
-            // the field must not be final (field is ignored, case logged) (112.3.8.1)
-            if ( Modifier.isFinal(f.getModifiers()) )
-            {
-                logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be declared as final", new Object[]
-                        {metadata.getField(), this.componentClass}, null );
-                valueType = ParamType.ignore;
-            }
-        }
-        else
-        {
-            if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICE.equals(metadata.getFieldCollectionType()) )
-            {
-                valueType = ParamType.serviceType;
-            }
-            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_REFERENCE.equals(metadata.getFieldCollectionType()) )
-            {
-                valueType = ParamType.serviceReference;
-            }
-            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICEOBJECTS.equals(metadata.getFieldCollectionType()) )
-            {
-                valueType = ParamType.serviceObjects;
-            }
-            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_PROPERTIES.equals(metadata.getFieldCollectionType()) )
-            {
-                valueType = ParamType.map;
-            }
-            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_TUPLE.equals(metadata.getFieldCollectionType()) )
-            {
-                valueType = ParamType.tuple;
-            }
-
-            // multiple cardinality, field type must be collection or subtype
-            if ( !ClassUtils.COLLECTION_CLASS.isAssignableFrom(fieldType) )
-            {
-                logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}", new Object[]
-                        {metadata.getField(), this.componentClass, fieldType.getName()}, null );
-                valueType = ParamType.ignore;
-            }
-
-            // additional checks for replace strategy:
-            if ( metadata.isReplace()  )
-            {
-                // if the field is dynamic wit has to be volatile (field is ignored, case logged) (112.3.8.1)
-                if ( !metadata.isStatic() && !Modifier.isVolatile(f.getModifiers()) )
-                {
-                    logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must be declared volatile to handle a dynamic reference", new Object[]
-                            {metadata.getField(), this.componentClass}, null );
-                    valueType = ParamType.ignore;
-                }
-
-                // replace strategy: field must not be final (field is ignored, case logged) (112.3.8.1)
-                //                   only collection and list allowed
-                if ( fieldType != ClassUtils.LIST_CLASS && fieldType != ClassUtils.COLLECTION_CLASS )
-                {
-                    logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}."+
-                        " It must be one of java.util.Collection or java.util.List.",
-                        new Object[] {metadata.getField(), this.componentClass, fieldType.getName()}, null );
-                    valueType = ParamType.ignore;
-
-                }
-                if ( Modifier.isFinal(f.getModifiers()) )
-                {
-                    logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be declared as final", new Object[]
-                            {metadata.getField(), this.componentClass}, null );
-                    valueType = ParamType.ignore;
-                }
-            }
-        }
-        // static references only allowed for replace strategy
-        if ( metadata.isStatic() && !metadata.isReplace() )
-        {
-            logger.log( LogService.LOG_ERROR, "Update strategy for field {0} in component {1} only allowed for non static field references.", new Object[]
-                    {metadata.getField(), this.componentClass}, null );
-            valueType = ParamType.ignore;
-        }
-        return f;
-    }
-
     private enum METHOD_TYPE
     {
         BIND,
@@ -258,78 +118,11 @@ public class FieldHandler
         UPDATED
     };
 
-    @SuppressWarnings("rawtypes")
-    private final class MapEntryImpl implements Map.Entry, Comparable<Map.Entry<?, ?>>
-    {
-
-        private final Object key;
-        private final Object value;
-        private final ServiceReference<?> ref;
-
-        public MapEntryImpl(final Object key,
-                final Object value,
-                final ServiceReference<?> ref)
-        {
-            this.key = key;
-            this.value = value;
-            this.ref = ref;
-        }
-
-        public Object getKey()
-        {
-            return this.key;
-        }
-
-        public Object getValue()
-        {
-            return this.value;
-        }
-
-        public Object setValue(final Object value)
-        {
-            throw new UnsupportedOperationException();
-        }
-
-        public int compareTo(final Map.Entry<?, ?> o)
-        {
-            if ( o == null )
-            {
-                return 1;
-            }
-            if ( o instanceof MapEntryImpl )
-            {
-                final MapEntryImpl other = (MapEntryImpl)o;
-                return ref.compareTo(other.ref);
-
-            }
-            return new Integer(this.hashCode()).compareTo(o.hashCode());
-        }
-
-    }
-
-    private Object getValue(final ComponentContextImpl key,
-            final RefPair<?, ?> refPair)
-    {
-        final Object obj;
-        switch ( this.valueType )
-        {
-            case serviceType : obj = refPair.getServiceObject(key); break;
-            case serviceReference : obj = refPair.getRef(); break;
-            case serviceObjects : obj = key.getComponentServiceObjectsHelper().getServiceObjects(refPair.getRef()); break;
-            case map : obj = new ReadOnlyDictionary( refPair.getRef() ); break;
-            case tuple : final Object tupleKey = new ReadOnlyDictionary( refPair.getRef() );
-                         final Object tupleValue = refPair.getServiceObject(key);
-                         obj = new MapEntryImpl(tupleKey, tupleValue, refPair.getRef());
-                         break;
-            default: obj = null;
-        }
-        return obj;
-    }
 
     private boolean initField(final Object componentInstance,
             final SimpleLogger logger )
     {
-    	if ( valueType == ParamType.ignore )
+    	if ( valueType == FieldUtils.ValueType.ignore )
     	{
     		return true;
     	}
@@ -354,7 +147,7 @@ public class FieldHandler
                         {
                             logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be declared as final", new Object[]
                                     {metadata.getField(), this.componentClass}, null );
-                            valueType = ParamType.ignore;
+                            valueType = FieldUtils.ValueType.ignore;
                             return true;
                         }
                         if ( fieldType != ClassUtils.LIST_CLASS && fieldType != ClassUtils.COLLECTION_CLASS )
@@ -362,7 +155,7 @@ public class FieldHandler
                             logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}."+
                                 " It must be one of java.util.Collection or java.util.List.",
                                 new Object[] {metadata.getField(), this.componentClass, fieldType.getName()}, null );
-                            valueType = ParamType.ignore;
+                            valueType = FieldUtils.ValueType.ignore;
                             return true;
                         }
                         if ( fieldType == ClassUtils.LIST_CLASS )
@@ -388,7 +181,7 @@ public class FieldHandler
         }
         catch ( final InvocationTargetException ite)
         {
-            valueType = ParamType.ignore;
+            valueType = FieldUtils.ValueType.ignore;
 
             logger.log( LogService.LOG_ERROR, "Field {0} in component {1} can't be initialized.",
                     new Object[] {metadata.getField(), this.componentClass}, ite );
@@ -414,7 +207,8 @@ public class FieldHandler
                                      final SimpleLogger logger )
         throws InvocationTargetException
     {
-        final ComponentContextImpl key = bp.getComponentContext();
+        @SuppressWarnings("rawtypes")
+		final ComponentContextImpl key = bp.getComponentContext();
         final RefPair<?, ?> refPair = bp.getRefPair();
 
         if ( !this.metadata.isMultiple() )
@@ -439,13 +233,13 @@ public class FieldHandler
             // for a static reference we need a reactivation
             else if ( mType == METHOD_TYPE.UPDATED )
             {
-            	if ( this.valueType == ParamType.map || this.valueType == ParamType.tuple )
+            	if ( this.valueType == FieldUtils.ValueType.ref_map || this.valueType == FieldUtils.ValueType.ref_tuple )
             	{
             		if ( this.metadata.isStatic() )
             		{
             			return MethodResult.REACTIVATE;
             		}
-                    final Object obj = getValue(key, refPair);
+                    final Object obj = FieldUtils.getValue(valueType, field.getType(), key, refPair);
                     this.setFieldValue(componentInstance, obj);
                     this.boundValues.put(refPair, obj);
             	}
@@ -453,7 +247,7 @@ public class FieldHandler
             // bind needs always be done
             else
             {
-                final Object obj = getValue(key, refPair);
+                final Object obj = FieldUtils.getValue(valueType, field.getType(), key, refPair);
                 this.setFieldValue(componentInstance, obj);
                 this.boundValues.put(refPair, obj);
             }
@@ -465,7 +259,7 @@ public class FieldHandler
             // bind: replace or update the field
             if ( mType == METHOD_TYPE.BIND )
             {
-                final Object obj = getValue(key, refPair);
+                final Object obj = FieldUtils.getValue(valueType, field.getType(), key, refPair);
                 this.boundValues.put(refPair, obj);
                 if ( metadata.isReplace() )
                 {
@@ -499,11 +293,11 @@ public class FieldHandler
             // updated needs only be done, if the value type is map or tuple
             else if ( mType == METHOD_TYPE.UPDATED)
             {
-            	if ( this.valueType == ParamType.map || this.valueType == ParamType.tuple )
+            	if ( this.valueType == FieldUtils.ValueType.ref_map || this.valueType == FieldUtils.ValueType.ref_tuple )
             	{
                     if ( !this.metadata.isStatic() )
                     {
-	                    final Object obj = getValue(key, refPair);
+	                    final Object obj = FieldUtils.getValue(valueType, field.getType(), key, refPair);
 	                    final Object oldObj = this.boundValues.put(refPair, obj);
 
 	                    if ( metadata.isReplace() )
@@ -604,14 +398,19 @@ public class FieldHandler
         	}
         	else 
         	{
+        		field = result.field;
             	if ( !result.usable ) 
             	{
-            		handler.valueType = ParamType.ignore;
-            		field = result.field;
+            		handler.valueType = FieldUtils.ValueType.ignore;
             	}
             	else
             	{
-            		field = handler.validateField( result.field, logger );
+            		handler.valueType = FieldUtils.getReferenceValueType( 
+            				handler.componentClass,
+            				handler.metadata,
+            				field.getType(),
+            				field, 
+            				logger );
             	}
         	}
 
@@ -718,7 +517,7 @@ public class FieldHandler
                 final MethodResult methodCallFailureResult,
                 final SimpleLogger logger)
         {
-            if ( handler.valueType == ParamType.ignore )
+            if ( handler.valueType == FieldUtils.ValueType.ignore )
             {
                 return MethodResult.VOID;
             }
@@ -750,7 +549,7 @@ public class FieldHandler
                 //??? this resolves which we need.... better way?
                 if ( refPair.getServiceObject(key) == null
                   && handler.fieldExists( logger )
-                  && (handler.valueType == ParamType.serviceType || handler.valueType == ParamType.tuple ) )
+                  && (handler.valueType == FieldUtils.ValueType.ref_serviceType || handler.valueType == FieldUtils.ValueType.ref_tuple ) )
                 {
                     return refPair.getServiceObject(key, context, logger);
                 }
@@ -776,7 +575,7 @@ public class FieldHandler
 
     public InitReferenceMethod getInit()
     {
-        if ( valueType == ParamType.ignore )
+        if ( valueType == FieldUtils.ValueType.ignore )
         {
             return null;
         }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldUtils.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldUtils.java?rev=1777960&r1=1777959&r2=1777960&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldUtils.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldUtils.java Mon Jan  9 13:28:57 2017
@@ -23,13 +23,35 @@ import java.lang.reflect.InvocationTarge
 import java.lang.reflect.Modifier;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.Map;
 
+import org.apache.felix.scr.impl.helper.ReadOnlyDictionary;
 import org.apache.felix.scr.impl.helper.SimpleLogger;
+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.ServiceReference;
 import org.osgi.service.log.LogService;
 
 public class FieldUtils {
 
-	public static final class FieldSearchResult 
+	public enum ValueType
+    {
+        ignore,
+        componentContext,
+        bundleContext,
+        config_map,
+        config_annotation,
+        ref_serviceReference,
+        ref_serviceObjects,
+        ref_serviceType,
+        ref_map,
+        ref_tuple
+    }
+    
+	public static final ValueType[] EMPTY_TYPES = new ValueType[0];
+
+    public static final class FieldSearchResult 
 	{
 		public final Field field;
 		public final boolean usable;
@@ -271,4 +293,265 @@ public class FieldUtils {
             }
         } );
     }
+
+	/**
+     * Get the value type for the parameter class.
+     * @param typeClass The class of the parameter
+     * @return The value type
+     */
+    public static ValueType getValueType( final Class<?> typeClass )
+    {
+        if ( typeClass == ClassUtils.COMPONENT_CONTEXT_CLASS )
+        {
+        	return ValueType.componentContext;
+        }
+        else if ( typeClass == ClassUtils.BUNDLE_CONTEXT_CLASS )
+        {
+        	return ValueType.bundleContext;
+        }
+        else if ( typeClass == ClassUtils.MAP_CLASS )
+        {
+        	return ValueType.config_map;
+        }
+        else
+        {
+        	return ValueType.config_annotation;
+        }
+    }
+
+    /**
+     * Get the value type of the reference
+     * @param componentClass The component class declaring the reference
+     * @param metadata The reference metadata
+     * @param typeClass The type of the field/parameter
+     * @param f The optional field. If null, this is a constructor reference
+     * @param logger The logger
+     * @return The value type for the field. If invalid, {@code ValueType#ignore}
+     */
+    public static ValueType getReferenceValueType( 
+    		final Class<?> componentClass,
+    		final ReferenceMetadata metadata,
+    		final Class<?> typeClass, 
+    		final Field field,
+    		final SimpleLogger logger )
+    {
+        final Class<?> referenceType = ClassUtils.getClassFromComponentClassLoader(
+                componentClass, metadata.getInterface(), logger);
+
+        ValueType valueType = ValueType.ignore;
+        
+        // unary reference
+        if ( !metadata.isMultiple() )
+        {
+            if ( typeClass.isAssignableFrom(referenceType) )
+            {
+                valueType = ValueType.ref_serviceType;
+            }
+            else if ( typeClass == ClassUtils.SERVICE_REFERENCE_CLASS )
+            {
+                valueType = ValueType.ref_serviceReference;
+            }
+            else if ( typeClass == ClassUtils.COMPONENTS_SERVICE_OBJECTS_CLASS )
+            {
+                valueType = ValueType.ref_serviceObjects;
+            }
+            else if ( typeClass == ClassUtils.MAP_CLASS )
+            {
+                valueType = ValueType.ref_map;
+            }
+            else if ( typeClass == ClassUtils.MAP_ENTRY_CLASS )
+            {
+                valueType = ValueType.ref_tuple;
+            }
+            else
+            {
+            	if ( field != null )
+            	{
+	                logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}", new Object[]
+	                        {metadata.getField(), componentClass, typeClass.getName()}, null );
+            	}
+            	else
+            	{
+	                logger.log( LogService.LOG_ERROR, "Constructor argument {0} in component {1} has unsupported type {2}", new Object[]
+	                        {metadata.getParamterIndex(), componentClass, typeClass.getName()}, null );            		
+            	}
+                valueType = ValueType.ignore;
+            }
+
+            // if the field is dynamic, it has to be volatile (field is ignored, case logged) (112.3.8.1)
+            if ( field != null && !metadata.isStatic() && !Modifier.isVolatile(field.getModifiers()) ) {
+                logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must be declared volatile to handle a dynamic reference", new Object[]
+                        {metadata.getField(), componentClass}, null );
+                valueType = ValueType.ignore;
+            }
+
+            // the field must not be final (field is ignored, case logged) (112.3.8.1)
+            if ( field != null && Modifier.isFinal(field.getModifiers()) )
+            {
+                logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be declared as final", new Object[]
+                        {metadata.getField(), componentClass}, null );
+                valueType = ValueType.ignore;
+            }
+        }
+        else
+        {
+            if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICE.equals(metadata.getFieldCollectionType()) )
+            {
+                valueType = ValueType.ref_serviceType;
+            }
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_REFERENCE.equals(metadata.getFieldCollectionType()) )
+            {
+                valueType = ValueType.ref_serviceReference;
+            }
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICEOBJECTS.equals(metadata.getFieldCollectionType()) )
+            {
+                valueType = ValueType.ref_serviceObjects;
+            }
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_PROPERTIES.equals(metadata.getFieldCollectionType()) )
+            {
+                valueType = ValueType.ref_map;
+            }
+            else if ( ReferenceMetadata.FIELD_VALUE_TYPE_TUPLE.equals(metadata.getFieldCollectionType()) )
+            {
+                valueType = ValueType.ref_tuple;
+            }
+
+            // multiple cardinality, field type must be collection or subtype
+            if ( !ClassUtils.COLLECTION_CLASS.isAssignableFrom(typeClass) )
+            {
+            	if ( field != null )
+            	{
+	                logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}", new Object[]
+	                        {metadata.getField(), componentClass, typeClass.getName()}, null );
+            	}
+            	else
+            	{
+                    logger.log( LogService.LOG_ERROR, "Constructor argument {0} in component {1} has unsupported type {2}", new Object[]
+                            {metadata.getParamterIndex(), componentClass, typeClass.getName()}, null );            		
+            	}
+                valueType = ValueType.ignore;
+            }
+
+            // additional checks for replace strategy:
+            if ( metadata.isReplace() && field != null )
+            {
+                // if the field is dynamic wit has to be volatile (field is ignored, case logged) (112.3.8.1)
+                if ( !metadata.isStatic() && !Modifier.isVolatile(field.getModifiers()) )
+                {
+                    logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must be declared volatile to handle a dynamic reference", new Object[]
+                            {metadata.getField(), componentClass}, null );
+                    valueType = ValueType.ignore;
+                }
+
+                // replace strategy: field must not be final (field is ignored, case logged) (112.3.8.1)
+                //                   only collection and list allowed
+                if ( typeClass != ClassUtils.LIST_CLASS && typeClass != ClassUtils.COLLECTION_CLASS )
+                {
+                    logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}."+
+                        " It must be one of java.util.Collection or java.util.List.",
+                        new Object[] {metadata.getField(), componentClass, typeClass.getName()}, null );
+                    valueType = ValueType.ignore;
+
+                }
+                if ( Modifier.isFinal(field.getModifiers()) )
+                {
+                    logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be declared as final", new Object[]
+                            {metadata.getField(), componentClass}, null );
+                    valueType = ValueType.ignore;
+                }
+            }
+        }
+        // static references only allowed for replace strategy
+        if ( metadata.isStatic() && !metadata.isReplace() )
+        {
+            logger.log( LogService.LOG_ERROR, "Update strategy for field {0} in component {1} only allowed for non static field references.", new Object[]
+                    {metadata.getField(), componentClass}, null );
+            valueType = ValueType.ignore;
+        }
+        return valueType;
+    }
+
+    /**
+     * Get the value for the parameter type
+     * @param type The parameter type
+     * @param componentContext The component context
+     */
+    @SuppressWarnings("unchecked")
+	public static Object getValue( final ValueType type,
+			final Class<?> targetType,
+    		@SuppressWarnings("rawtypes") final ComponentContextImpl componentContext,
+    		final RefPair<?, ?> refPair)
+    {
+    	final Object value;
+    	switch ( type ) {
+    		case ignore : value = null; break;
+    		case componentContext : value = componentContext; break;
+    		case bundleContext : value = componentContext.getBundleContext(); break;
+    		case config_map : // note: getProperties() returns a ReadOnlyDictionary which is a Map
+    			              value = componentContext.getProperties(); break;
+    		case config_annotation : value = Annotations.toObject(targetType,
+                    (Map<String, Object>) componentContext.getProperties(),
+                    componentContext.getBundleContext().getBundle(), componentContext.getComponentMetadata().isConfigureWithInterfaces());
+    		        break;
+    		case ref_serviceType : value = refPair.getServiceObject(componentContext); break;
+    		case ref_serviceReference : value = refPair.getRef(); break;
+    		case ref_serviceObjects : value = componentContext.getComponentServiceObjectsHelper().getServiceObjects(refPair.getRef()); break;
+    		case ref_map : value = new ReadOnlyDictionary( refPair.getRef() ); break;
+    		case ref_tuple : final Object tupleKey = new ReadOnlyDictionary( refPair.getRef() );
+                 final Object tupleValue = refPair.getServiceObject(componentContext);
+                 value = new MapEntryImpl(tupleKey, tupleValue, refPair.getRef());
+                 break;
+            default: value = null;
+    	}
+    	return value;
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static final class MapEntryImpl implements Map.Entry, Comparable<Map.Entry<?, ?>>
+    {
+
+        private final Object key;
+        private final Object value;
+        private final ServiceReference<?> ref;
+
+        public MapEntryImpl(final Object key,
+                final Object value,
+                final ServiceReference<?> ref)
+        {
+            this.key = key;
+            this.value = value;
+            this.ref = ref;
+        }
+
+        public Object getKey()
+        {
+            return this.key;
+        }
+
+        public Object getValue()
+        {
+            return this.value;
+        }
+
+        public Object setValue(final Object value)
+        {
+            throw new UnsupportedOperationException();
+        }
+
+        public int compareTo(final Map.Entry<?, ?> o)
+        {
+            if ( o == null )
+            {
+                return 1;
+            }
+            if ( o instanceof MapEntryImpl )
+            {
+                final MapEntryImpl other = (MapEntryImpl)o;
+                return ref.compareTo(other.ref);
+
+            }
+            return new Integer(this.hashCode()).compareTo(o.hashCode());
+        }
+
+    }
 }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java?rev=1777960&r1=1777959&r2=1777960&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/manager/ComponentContextImpl.java Mon Jan  9 13:28:57 2017
@@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit;
 import org.apache.felix.scr.component.ExtComponentContext;
 import org.apache.felix.scr.impl.helper.ComponentServiceObjectsHelper;
 import org.apache.felix.scr.impl.helper.ReadOnlyDictionary;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
@@ -116,6 +117,11 @@ public class ComponentContextImpl<S> imp
         return m_componentManager;
     }
 
+    public ComponentMetadata getComponentMetadata() 
+    {
+    	return m_componentManager.getComponentMetadata();
+    }
+    
     public final Dictionary<String, Object> getProperties()
     {
         // 112.12.3.5 The Dictionary is read-only and cannot be modified

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=1777960&r1=1777959&r2=1777960&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 Jan  9 13:28:57 2017
@@ -1488,6 +1488,11 @@ public class DependencyManager<S, T> imp
         return m_dependencyMetadata.getName();
     }
 
+    public int getParameterIndex() 
+    {
+    	return m_dependencyMetadata.getParamterIndex();
+    }
+    
     /**
      * Returns <code>true</code> if this dependency manager is satisfied, that
      * is if either the dependency is optional or the number of services

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=1777960&r1=1777959&r2=1777960&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 Jan  9 13:28:57 2017
@@ -25,11 +25,13 @@ import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.felix.scr.impl.helper.ComponentMethod;
 import org.apache.felix.scr.impl.helper.ComponentMethods;
 import org.apache.felix.scr.impl.helper.MethodResult;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.TargetedPID;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
@@ -212,7 +214,8 @@ public class SingleComponentManager<S> e
     }
 
 
-    protected S createImplementationObject( Bundle usingBundle, SetImplementationObject<S> setter, ComponentContextImpl<S> componentContext )
+    @SuppressWarnings("unchecked")
+	protected S createImplementationObject( Bundle usingBundle, SetImplementationObject<S> setter, ComponentContextImpl<S> componentContext )
     {
         final Class<S> implementationObjectClass;
         final S implementationObject;
@@ -226,6 +229,65 @@ public class SingleComponentManager<S> e
             log( LogService.LOG_WARNING, "Bundle shut down during instantiation of the implementation object", null);
             return null;
         }
+        
+        ReferenceManager<S, ?> failedDm = null;
+        
+        // bind target services for constructor injection
+        final TreeMap<Integer, DependencyManager<S, ?>> paramMap;
+        if ( ComponentMetadata.CONSTRUCTOR_MARKER.equals(getComponentMetadata().getActivate()))
+        {
+        	paramMap = new TreeMap<Integer, DependencyManager<S,?>>();
+	        for ( DependencyManager<S, ?> dm : getDependencyManagers())
+	        {
+	            if ( failedDm == null )
+	            {
+	            	if ( dm.getParameterIndex() != - 1)
+	            	{
+		                // if a dependency turned unresolved since the validation check,
+		                // creating the instance fails here, so we deactivate and return
+		                // null.
+		                boolean open = dm.open( componentContext, componentContext.getEdgeInfo( dm ) );
+		                if ( !open )
+		                {
+		                    log( LogService.LOG_DEBUG, "Cannot create component instance due to failure to bind reference {0}",
+		                            new Object[] { dm.getName() }, null );
+		
+		                    failedDm = dm;
+		                }
+		                paramMap.put(dm.getParameterIndex(), dm);
+	                }
+	            }
+	        }
+	        if (failedDm != null)
+	        {
+	            // make sure, we keep no bindings. Only close the dm's we opened.
+	            boolean skip = true;
+	            for ( DependencyManager<S, ?> md: getReversedDependencyManagers() )
+	            {
+	                if ( skip )
+	                {
+	                	if ( failedDm == md ) 
+	                	{
+	                		skip = false;
+	                	}
+	                }
+	                else
+	                {
+	                	if ( md.getParameterIndex() != -1 )
+	                	{
+	                		md.close( componentContext, componentContext.getEdgeInfo( md ) );
+	                	}
+	                }
+	                md.deactivate();
+	            }
+	            return null;
+	        }
+        }
+        else
+        {
+        	paramMap = null;
+        }
+        
         try
         {
             // 112.4.4 The class is retrieved with the loadClass method of the component's bundle
@@ -234,6 +296,7 @@ public class SingleComponentManager<S> e
 
             implementationObject = getComponentMethods().getConstructor().newInstance(implementationObjectClass,
             		componentContext,
+            		paramMap,
             		this);
             
         }
@@ -251,29 +314,35 @@ public class SingleComponentManager<S> e
 
         // 4. Bind the target services
 
-        ReferenceManager<S, ?> failedDm = null;
         for ( DependencyManager<S, ?> dm: getDependencyManagers())
         {
             if ( failedDm == null )
             {
-                // if a dependency turned unresolved since the validation check,
-                // creating the instance fails here, so we deactivate and return
-                // null.
-                boolean open = dm.open( componentContext, componentContext.getEdgeInfo( dm ) );
-                if ( !open )
-                {
-                    log( LogService.LOG_DEBUG, "Cannot create component instance due to failure to bind reference {0}",
-                            new Object[] { dm.getName() }, null );
-
-                    failedDm = dm;
-
-                }
+            	if ( dm.getParameterIndex() == - 1)
+            	{
+	                // if a dependency turned unresolved since the validation check,
+	                // creating the instance fails here, so we deactivate and return
+	                // null.
+	                boolean open = dm.open( componentContext, componentContext.getEdgeInfo( dm ) );
+	                if ( !open )
+	                {
+	                    log( LogService.LOG_DEBUG, "Cannot create component instance due to failure to bind reference {0}",
+	                            new Object[] { dm.getName() }, null );
+	
+	                    failedDm = dm;
+	
+	                }
+            	}
             }
             else
             {
-                componentContext.getEdgeInfo( dm ).ignore();
+            	if ( dm.getParameterIndex() == - 1)
+            	{
+            		componentContext.getEdgeInfo( dm ).ignore();
+            	}
             }
         }
+
         if (failedDm != null)
         {
             // make sure, we keep no bindings. Only close the dm's we opened.
@@ -284,7 +353,7 @@ public class SingleComponentManager<S> e
                 {
                     skip = false;
                 }
-                if ( !skip )
+                if ( !skip || md.getParameterIndex() != -1 )
                 {
                     md.close( componentContext, componentContext.getEdgeInfo( md ) );
                 }

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java?rev=1777960&r1=1777959&r2=1777960&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java Mon Jan  9 13:28:57 2017
@@ -55,6 +55,9 @@ public class ComponentMetadata
     // marker value indicating duplicate service setting
     private static final ServiceMetadata SERVICE_DUPLICATE = new ServiceMetadata();
 
+	/** If the activate method has this value, a constructor is used instead. */
+	public static final String CONSTRUCTOR_MARKER = "-init-";
+	       
     // the namespace code of the namespace declaring this component
     private final DSVersion m_dsVersion;
 
@@ -1005,6 +1008,34 @@ public class ComponentMetadata
             throw validationFailure( "Activation fields require version 1.4 or later");
         }
         
+        // constructor injection requires DS 1.4
+        if ( CONSTRUCTOR_MARKER.equals(this.getActivate()) )
+        {
+        	if ( !m_dsVersion.isDS14() )
+        	{
+                throw validationFailure( "Constructor injection requires version 1.4 or later");        		
+        	}
+        	final Set<Integer> parIndexSet = new HashSet<Integer>();
+        	for(final ReferenceMetadata ref : this.m_references) 
+        	{
+        		if ( ref.getParamterIndex() != -1 && !parIndexSet.add(ref.getParamterIndex()) ) 
+        		{
+                    throw validationFailure( "Duplicate reference for argument " + ref.getParamterIndex() + " in constructor" );        	                        
+        		}
+        	}
+        }
+        else
+        {
+        	// no constructor injection, check references for having a parameter index
+        	for(final ReferenceMetadata ref : this.m_references) 
+        	{
+        		if ( ref.getParamterIndex() != -1 )
+        		{
+                    throw validationFailure( "Reference must not use parameter attribute if no constructor injection is used" );        			
+        		}
+        	}
+        }
+        
         if (m_dsVersion == DSVersion.DS12Felix)
         {
         	m_configurableServiceProperties = true;

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=1777960&r1=1777959&r2=1777960&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 Jan  9 13:28:57 2017
@@ -134,7 +134,7 @@ public class ReferenceMetadata
     private String m_parameter;
     
     // Parameter index, set based on {@code m_parameter} after validation
-    private int m_parameterIndex;
+    private int m_parameterIndex = -1;
     
     // Flags that store the values passed as strings
     private boolean m_isStatic = true;
@@ -542,7 +542,7 @@ public class ReferenceMetadata
      * This method returns the correct value only of this metadata object has been validated
      * by a call to {@link #validate(ComponentMetadata, Logger)} and the validation has been
      * successful.
-     * @return The parameter index , if no parameter is set this returns {@code 0}
+     * @return The parameter index , if no parameter is set this returns {@code -1}
      */
     public int getParamterIndex() 
     {

Modified: felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java?rev=1777960&r1=1777959&r2=1777960&view=diff
==============================================================================
--- felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java (original)
+++ felix/trunk/osgi-r7/scr/src/main/java/org/apache/felix/scr/impl/runtime/ServiceComponentRuntimeImpl.java Mon Jan  9 13:28:57 2017
@@ -400,7 +400,7 @@ public class ServiceComponentRuntimeImpl
 			dto.unbind = r.getUnbind();
 			dto.updated = r.getUpdated();
 			// DS 1.4
-			dto.parameter = r.getParamterIndex();
+			dto.parameter = (r.getParamterIndex() == -1 ? 0 : r.getParamterIndex());
 			dto.collectionType = r.getFieldCollectionType();
 			dtos[i++] = dto;
 		}



Mime
View raw message