You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2017/01/06 15:24:42 UTC

svn commit: r1777628 - in /felix/trunk/scr/src/main/java/org/apache/felix/scr/impl: helper/ inject/ manager/ metadata/ xml/

Author: cziegeler
Date: Fri Jan  6 15:24:42 2017
New Revision: 1777628

URL: http://svn.apache.org/viewvc?rev=1777628&view=rev
Log:
FELIX-5456 : [R7] Field injection of component activation objects

Added:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ConstructorMethod.java   (with props)
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java   (with props)
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldUtils.java   (with props)
Modified:
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentMethods.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ActivateMethod.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/FieldHandler.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/metadata/ComponentMetadata.java
    felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentMethods.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentMethods.java?rev=1777628&r1=1777627&r2=1777628&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentMethods.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ComponentMethods.java Fri Jan  6 15:24:42 2017
@@ -35,4 +35,6 @@ public interface ComponentMethods
 
     ReferenceMethods getBindMethods(String refName );
 
+	ConstructorMethod getConstructor();
+
 }

Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ConstructorMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ConstructorMethod.java?rev=1777628&view=auto
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ConstructorMethod.java (added)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/helper/ConstructorMethod.java Fri Jan  6 15:24:42 2017
@@ -0,0 +1,54 @@
+/*
+ * 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.helper;
+
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * This object describes a constructor for a component.
+ * The name ConstructorMethod has been chosen to avoid a clash with the 
+ * existing Constructor class.
+ */
+public interface ConstructorMethod {
+
+	/**
+	 * Create a new instance
+	 * @param componentClass The implementation class of the component
+	 * @param componentContext The component context
+	 * @param logger A logger 
+	 * @return The instance
+	 */
+	<T> T newInstance(Class<T> componentClass,
+    		           ComponentContext componentContext,
+                       SimpleLogger logger )
+    throws Exception;
+    
+    public ConstructorMethod DEFAULT = new ConstructorMethod() {
+		
+		@Override
+		public <T> T newInstance(Class<T> componentClass, ComponentContext componentContext, SimpleLogger logger) 
+				throws Exception
+		{
+            // 112.4.4 The class must be public and have a public constructor without arguments so component instances
+            // may be created by the SCR with the newInstance method on Class
+            return componentClass.newInstance();
+		}
+	};
+
+}

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

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

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ActivateMethod.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ActivateMethod.java?rev=1777628&r1=1777627&r2=1777628&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ActivateMethod.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ActivateMethod.java Fri Jan  6 15:24:42 2017
@@ -31,7 +31,6 @@ import org.apache.felix.scr.impl.helper.
 import org.apache.felix.scr.impl.helper.MethodResult;
 import org.apache.felix.scr.impl.helper.SimpleLogger;
 import org.apache.felix.scr.impl.metadata.DSVersion;
-import org.osgi.framework.BundleContext;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.log.LogService;
 
@@ -39,19 +38,14 @@ import org.osgi.service.log.LogService;
 public class ActivateMethod extends BaseMethod<ActivatorParameter> implements ComponentMethod
 {
 
-    protected static final Class<?> COMPONENT_CONTEXT_CLASS = ComponentContext.class;
-    protected static final Class<?> BUNDLE_CONTEXT_CLASS = BundleContext.class;
-    protected static final Class<?> INTEGER_CLASS = Integer.class;
-
     protected final boolean m_supportsInterfaces;
-
-
+    
     public ActivateMethod( final String methodName,
             final boolean methodRequired,
             final Class<?> componentClass,
             final DSVersion dsVersion,
             final boolean configurableServiceProperties,
-            boolean supportsInterfaces )
+            final boolean supportsInterfaces)
     {
         super( methodName, methodRequired, componentClass, dsVersion, configurableServiceProperties );
         m_supportsInterfaces = supportsInterfaces;
@@ -69,7 +63,7 @@ public class ActivateMethod extends Base
         {
             // find the declared method in this class
             final Method method = getMethod( targetClass, getMethodName(), new Class[]
-                { COMPONENT_CONTEXT_CLASS }, acceptPrivate, acceptPackage, logger );
+                { ClassUtils.COMPONENT_CONTEXT_CLASS }, acceptPrivate, acceptPackage, logger );
             if ( method != null )
             {
                 return method;
@@ -90,7 +84,7 @@ public class ActivateMethod extends Base
                 {
                     Class<?> type = parameterTypes[0];
                     //single parameter method with parameter ComponentContext will already have been found.
-                    if (type == BUNDLE_CONTEXT_CLASS)
+                    if (type == ClassUtils.BUNDLE_CONTEXT_CLASS)
                     {
                         if ( accept( m, acceptPrivate, acceptPackage, returnValue() ) )
                         {
@@ -137,8 +131,8 @@ public class ActivateMethod extends Base
                     boolean accept = true;
                     for (Class<?> type: parameterTypes)
                     {
-                        accept = type == COMPONENT_CONTEXT_CLASS
-                            || type == BUNDLE_CONTEXT_CLASS
+                        accept = type == ClassUtils.COMPONENT_CONTEXT_CLASS
+                            || type == ClassUtils.BUNDLE_CONTEXT_CLASS
                             || type == ClassUtils.MAP_CLASS
                             || ( isDeactivate() && ( type == int.class || type == Integer.class))
                             || ( getDSVersion().isDS13() && isAnnotation(type));
@@ -220,10 +214,10 @@ public class ActivateMethod extends Base
                     final Class<?> t1 = m1.getParameterTypes()[0];
                     final Class<?> t2 = m2.getParameterTypes()[0];
                     //t1, t2 can't be equal
-                    if (t1 == COMPONENT_CONTEXT_CLASS) return -1;
-                    if (t2 == COMPONENT_CONTEXT_CLASS) return 1;
-                    if (t1 == BUNDLE_CONTEXT_CLASS) return -1;
-                    if (t2 == BUNDLE_CONTEXT_CLASS) return 1;
+                    if (t1 == ClassUtils.COMPONENT_CONTEXT_CLASS) return -1;
+                    if (t2 == ClassUtils.COMPONENT_CONTEXT_CLASS) return 1;
+                    if (t1 == ClassUtils.BUNDLE_CONTEXT_CLASS) return -1;
+                    if (t2 == ClassUtils.BUNDLE_CONTEXT_CLASS) return 1;
                     if (isAnnotation(t1)) return isAnnotation(t2)? 0: -1;
                     if (isAnnotation(t2)) return 1;
                     if (t1 == ClassUtils.MAP_CLASS) return -1;
@@ -255,11 +249,11 @@ public class ActivateMethod extends Base
         final Object[] param = new Object[parameterTypes.length];
         for ( int i = 0; i < param.length; i++ )
         {
-            if ( parameterTypes[i] == COMPONENT_CONTEXT_CLASS )
+            if ( parameterTypes[i] == ClassUtils.COMPONENT_CONTEXT_CLASS )
             {
                 param[i] = ap.getComponentContext();
             }
-            else if ( parameterTypes[i] == BUNDLE_CONTEXT_CLASS )
+            else if ( parameterTypes[i] == ClassUtils.BUNDLE_CONTEXT_CLASS )
             {
                 param[i] = ap.getComponentContext().getBundleContext();
             }
@@ -268,7 +262,7 @@ public class ActivateMethod extends Base
                 // note: getProperties() returns a ReadOnlyDictionary which is a Map
                 param[i] = ap.getComponentContext().getProperties();
             }
-            else if ( parameterTypes[i] == INTEGER_CLASS || parameterTypes[i] == Integer.TYPE )
+            else if ( parameterTypes[i] == ClassUtils.INTEGER_CLASS || parameterTypes[i] == Integer.TYPE )
             {
                 param[i] = ap.getReason();
             }
@@ -290,12 +284,22 @@ public class ActivateMethod extends Base
         return "activate";
     }
 
-    public MethodResult invoke(Object componentInstance, ComponentContext componentContext, int reason, MethodResult methodCallFailureResult, SimpleLogger logger) {
+    /**
+     * @see org.apache.felix.scr.impl.helper.ComponentMethod#invoke(java.lang.Object, org.osgi.service.component.ComponentContext, int, org.apache.felix.scr.impl.helper.MethodResult, org.apache.felix.scr.impl.helper.SimpleLogger)
+     */
+    public MethodResult invoke(final Object componentInstance, 
+    		final ComponentContext componentContext, 
+    		final int reason, 
+    		final MethodResult methodCallFailureResult, 
+    		final SimpleLogger logger) {
         return invoke(componentInstance, new ActivatorParameter(componentContext, reason), methodCallFailureResult, logger);
     }
 
     @Override
-    public MethodResult invoke( Object componentInstance, ActivatorParameter rawParameter, final MethodResult methodCallFailureResult, SimpleLogger logger )
+    public MethodResult invoke(final  Object componentInstance, 
+    		final ActivatorParameter rawParameter,
+    		final MethodResult methodCallFailureResult, 
+    		final SimpleLogger logger )
     {
         if (methodExists( logger ))
         {

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ClassUtils.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ClassUtils.java?rev=1777628&r1=1777627&r2=1777628&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ClassUtils.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ClassUtils.java Fri Jan  6 15:24:42 2017
@@ -26,6 +26,7 @@ import java.util.Map;
 import org.apache.felix.scr.impl.helper.SimpleLogger;
 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;
@@ -54,6 +55,11 @@ public class ClassUtils
     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;
+
+
     // this bundle's context
     private static BundleContext m_context;
     // the package admin service (see BindMethod.getParameterClass)
@@ -206,4 +212,16 @@ public class ClassUtils
         // 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( Class<?> clazz )
+    {
+        String name = clazz.getName();
+        int dot = name.lastIndexOf( '.' );
+        return ( dot > 0 ) ? name.substring( 0, dot ) : "";
+    }
+
 }

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java?rev=1777628&r1=1777627&r2=1777628&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ComponentMethodsImpl.java Fri Jan  6 15:24:42 2017
@@ -25,13 +25,8 @@ import java.util.Map;
 
 import org.apache.felix.scr.impl.helper.ComponentMethod;
 import org.apache.felix.scr.impl.helper.ComponentMethods;
+import org.apache.felix.scr.impl.helper.ConstructorMethod;
 import org.apache.felix.scr.impl.helper.ReferenceMethods;
-import org.apache.felix.scr.impl.inject.ActivateMethod;
-import org.apache.felix.scr.impl.inject.BindMethods;
-import org.apache.felix.scr.impl.inject.DeactivateMethod;
-import org.apache.felix.scr.impl.inject.DuplexReferenceMethods;
-import org.apache.felix.scr.impl.inject.FieldMethods;
-import org.apache.felix.scr.impl.inject.ModifiedMethod;
 import org.apache.felix.scr.impl.metadata.ComponentMetadata;
 import org.apache.felix.scr.impl.metadata.DSVersion;
 import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
@@ -41,9 +36,10 @@ import org.apache.felix.scr.impl.metadat
  */
 public class ComponentMethodsImpl implements ComponentMethods
 {
-    private ActivateMethod m_activateMethod;
-    private ModifiedMethod m_modifiedMethod;
-    private DeactivateMethod m_deactivateMethod;
+    private ComponentMethod m_activateMethod;
+    private ComponentMethod m_modifiedMethod;
+    private ComponentMethod m_deactivateMethod;
+    private ConstructorMethod m_constructor;
 
     private final Map<String, ReferenceMethods> bindMethodMap = new HashMap<String, ReferenceMethods>();
 
@@ -56,8 +52,12 @@ public class ComponentMethodsImpl implem
         DSVersion dsVersion = componentMetadata.getDSVersion();
         boolean configurableServiceProperties = componentMetadata.isConfigurableServiceProperties();
         boolean supportsInterfaces = componentMetadata.isConfigureWithInterfaces();
-        m_activateMethod = new ActivateMethod( componentMetadata.getActivate(), componentMetadata
-                .isActivateDeclared(), implementationObjectClass, dsVersion, configurableServiceProperties, supportsInterfaces );
+        m_activateMethod = new ActivateMethod( componentMetadata.getActivate(), 
+        		componentMetadata.isActivateDeclared(), 
+        		implementationObjectClass, 
+        		dsVersion, 
+        		configurableServiceProperties, 
+        		supportsInterfaces);
         m_deactivateMethod = new DeactivateMethod( componentMetadata.getDeactivate(),
                 componentMetadata.isDeactivateDeclared(), implementationObjectClass, dsVersion, configurableServiceProperties, supportsInterfaces );
 
@@ -83,26 +83,44 @@ public class ComponentMethodsImpl implem
             }
             bindMethodMap.put( refName, methods );
         }
+        
+        if ( componentMetadata.getActivationFields() != null )
+        {
+        	
+        }
+        else
+        {
+        	m_constructor = ConstructorMethod.DEFAULT;
+        }
     }
 
-    public ComponentMethod getActivateMethod()
+	@Override
+   public ComponentMethod getActivateMethod()
     {
         return m_activateMethod;
     }
 
+	@Override
     public ComponentMethod getDeactivateMethod()
     {
         return m_deactivateMethod;
     }
 
+	@Override
     public ComponentMethod getModifiedMethod()
     {
         return m_modifiedMethod;
     }
 
+	@Override
     public ReferenceMethods getBindMethods(String refName )
     {
         return bindMethodMap.get( refName );
     }
 
+	@Override
+	public ConstructorMethod getConstructor() 
+	{
+		return m_constructor;
+	}
 }

Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java?rev=1777628&view=auto
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java (added)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/ConstructorMethodImpl.java Fri Jan  6 15:24:42 2017
@@ -0,0 +1,119 @@
+/*
+ * 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.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
+import org.apache.felix.scr.impl.helper.ConstructorMethod;
+import org.apache.felix.scr.impl.helper.SimpleLogger;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.log.LogService;
+
+public class ConstructorMethodImpl implements ConstructorMethod 
+{
+
+	private final ComponentMetadata m_metadata;
+	
+	public ConstructorMethodImpl( final ComponentMetadata metadata)
+	{
+		m_metadata = metadata;
+	}
+	
+	@Override
+	public <T> T newInstance(Class<T> componentClass, ComponentContext componentContext, SimpleLogger logger)
+			throws Exception
+	{
+		final T component = ConstructorMethod.DEFAULT.newInstance(componentClass, componentContext, logger);
+		
+		if ( m_metadata.getActivationFields() != null )
+		{
+			for(final String fieldName : m_metadata.getActivationFields() ) 
+			{
+				Field field = FieldUtils.findField(componentClass, fieldName, logger);
+				if ( field != null )
+				{
+					setField(componentClass, field, component, componentContext, logger);
+				}
+			}
+		}
+		
+		return component;
+	}
+	
+    /**
+     * Validate and set the field, type etc.
+     * @param f The field
+     * @param logger The logger
+     */
+    private <T> void setField( final Class<T> componentClass, 
+    		final Field f, 
+    		final T component,
+    		final ComponentContext componentContext,
+    		final SimpleLogger logger )
+    {
+
+        // ignore static fields
+        if ( Modifier.isStatic(f.getModifiers()))
+        {
+            logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be static", new Object[]
+                    {f.getName(), componentClass}, null );
+        }
+        else
+        {
+            final Class<?> fieldType = f.getType();
+            final Object value;
+            if ( fieldType == ClassUtils.COMPONENT_CONTEXT_CLASS )
+            {
+        	    value = componentContext;
+            }
+            else if ( fieldType == ClassUtils.BUNDLE_CONTEXT_CLASS )
+            {
+                value = componentContext.getBundleContext();
+            }
+            else if ( fieldType == ClassUtils.MAP_CLASS )
+            {
+                // note: getProperties() returns a ReadOnlyDictionary which is a Map
+            	value = componentContext.getProperties();
+            }
+            else
+            {
+            	value = Annotations.toObject(fieldType,
+                    (Map<String, Object>) componentContext.getProperties(),
+                    componentContext.getBundleContext().getBundle(), m_metadata.isConfigureWithInterfaces());
+            }
+            try
+            {
+                f.set(component, value);
+            }
+            catch ( final IllegalArgumentException iae )
+            {
+                logger.log( LogService.LOG_ERROR, "Field {0} in component {1} can't be set", new Object[]
+                        {f.getName(), componentClass}, 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 );
+            }
+        }
+    }
+}

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

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

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java?rev=1777628&r1=1777627&r2=1777628&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java Fri Jan  6 15:24:42 2017
@@ -22,8 +22,6 @@ package org.apache.felix.scr.impl.inject
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Modifier;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
@@ -124,149 +122,7 @@ public class FieldHandler
         }
     }
 
-    /**
-     * Finds the field named in the {@link #fieldName} field in the given
-     * <code>targetClass</code>. If the target class has no acceptable method
-     * the class hierarchy is traversed until a field is found or the root
-     * of the class hierarchy is reached without finding a field.
-     *
-     * @return The requested field or <code>null</code> if no acceptable field
-     *      can be found in the target class or any super class.
-     * @throws InvocationTargetException If an unexpected Throwable is caught
-     *      trying to find the requested field.
-     * @param logger
-     */
-    private Field findField( final SimpleLogger logger )
-    throws InvocationTargetException
-    {
-        final Class<?> targetClass = this.componentClass;
-        final ClassLoader targetClasslLoader = targetClass.getClassLoader();
-        final String targetPackage = getPackageName( targetClass );
-        Class<?> theClass = targetClass;
-        boolean acceptPrivate = true;
-        boolean acceptPackage = true;
-        while (true)
-        {
-
-            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
-            {
-                logger.log( LogService.LOG_DEBUG,
-                    "Locating field " + this.metadata.getField() + " in class " + theClass.getName(), null );
-            }
-
-            try
-            {
-                final Field field = getField( theClass, acceptPrivate, acceptPackage, logger );
-                if ( field != null )
-                {
-                    return field;
-                }
-            }
-            catch ( SuitableMethodNotAccessibleException ex )
-            {
-                // log and return null
-                logger.log( LogService.LOG_ERROR,
-                    "findField: Suitable but non-accessible field {0} found in class {1}, subclass of {2}", new Object[]
-                        { this.metadata.getField(), theClass.getName(), targetClass.getName() }, null );
-                break;
-            }
-
-            // if we get here, we have no field, so check the super class
-            theClass = theClass.getSuperclass();
-            if ( theClass == null )
-            {
-                break;
-            }
-
-            // super class field check ignores private fields and accepts
-            // package fields only if in the same package and package
-            // fields are (still) allowed
-            acceptPackage &= targetClasslLoader == theClass.getClassLoader()
-                && targetPackage.equals( getPackageName( theClass ) );
-
-            // private fields will not be accepted any more in super classes
-            acceptPrivate = false;
-        }
-
-        // nothing found after all these years ...
-        return null;
-    }
-
-    /**
-     * Finds the field named in the {@link #fieldName} field in the given
-     * <code>targetClass</code>. If the target class has no acceptable field
-     * the class hierarchy is traversed until a field is found or the root
-     * of the class hierarchy is reached without finding a field.
-     *
-     *
-     * @param targetClass The class in which to look for the method
-     * @param acceptPrivate <code>true</code> if private fields should be
-     *      considered.
-     * @param acceptPackage <code>true</code> if package private fields should
-     *      be considered.
-     * @param logger
-     * @return The requested field or <code>null</code> if no acceptable field
-     *      can be found in the target class or any super class.
-     * @throws InvocationTargetException If an unexpected Throwable is caught
-     *      trying to find the requested field.
-     */
-    private Field getField( final Class<?> clazz,
-            final boolean acceptPrivate,
-            final boolean acceptPackage,
-            final SimpleLogger logger )
-    throws SuitableMethodNotAccessibleException, InvocationTargetException
-    {
-        try
-        {
-            // find the declared field in this class
-            final Field field = clazz.getDeclaredField( this.metadata.getField() );
-
-            // accept public and protected fields only and ensure accessibility
-            if ( accept( field, acceptPrivate, acceptPackage ) )
-            {
-                return field;
-            }
-
-            // the method would fit the requirements but is not acceptable
-            throw new SuitableMethodNotAccessibleException();
-        }
-        catch ( NoSuchFieldException nsfe )
-        {
-            // thrown if no field is declared with the given name and
-            // parameters
-            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
-            {
-                logger.log( LogService.LOG_DEBUG, "Declared Field {0}.{1} not found", new Object[]
-                    { clazz.getName(), this.metadata.getField() }, null );
-            }
-        }
-        catch ( NoClassDefFoundError cdfe )
-        {
-            // may be thrown if a method would be found but the signature
-            // contains throws declaration for an exception which cannot
-            // be loaded
-            if ( logger.isLogEnabled( LogService.LOG_WARNING ) )
-            {
-                StringBuffer buf = new StringBuffer();
-                buf.append( "Failure loooking up field " ).append( this.metadata.getField() );
-                buf.append( " in class class " ).append( clazz.getName() ).append( ". Assuming no such field." );
-                logger.log( LogService.LOG_WARNING, buf.toString(), cdfe );
-            }
-        }
-        catch ( SuitableMethodNotAccessibleException e)
-        {
-            throw e;
-        }
-        catch ( Throwable throwable )
-        {
-            // unexpected problem accessing the field, don't let everything
-            // blow up in this situation, just throw a declared exception
-            throw new InvocationTargetException( throwable, "Unexpected problem trying to get field " + this.metadata.getField() );
-        }
 
-        // caught and ignored exception, assume no field and continue search
-        return null;
-    }
 
     /**
      * Validate the field, type etc.
@@ -717,91 +573,8 @@ public class FieldHandler
         }
     }
 
-    /**
-     * Returns <code>true</code> if the field is acceptable to be returned from the
-     * {@link #getField(Class, String, boolean, boolean, SimpleLogger)} and also
-     * makes the field accessible.
-     * <p>
-     * This method returns <code>true</code> if the field:
-     * <ul>
-     * <li>Is not static</li>
-     * <li>Is public or protected</li>
-     * <li>Is private and <code>acceptPrivate</code> is <code>true</code></li>
-     * <li>Is package private and <code>acceptPackage</code> is <code>true</code></li>
-     * </ul>
-     * <p>
-     *
-     * @param field The field to check
-     * @param acceptPrivate Whether a private field is acceptable
-     * @param acceptPackage Whether a package private field is acceptable
-     * @return whether the field is acceptable
-     */
-    private static boolean accept( final Field field,
-            final boolean acceptPrivate,
-            final boolean acceptPackage )
-    {
-        // check modifiers now
-        final int mod = field.getModifiers();
-
-        // no static fields
-        if ( Modifier.isStatic( mod ) )
-        {
-            return true;
-        }
-
-        // accept public and protected fields
-        if ( Modifier.isPublic( mod ) || Modifier.isProtected( mod ) )
-        {
-            setAccessible( field );
-            return true;
-        }
-
-        // accept private if accepted
-        if ( Modifier.isPrivate( mod ) )
-        {
-            if ( acceptPrivate )
-            {
-                setAccessible( field );
-                return true;
-            }
-
-            return false;
-        }
-
-        // accept default (package)
-        if ( acceptPackage )
-        {
-            setAccessible( field );
-            return true;
-        }
-
-        // else don't accept
-        return false;
-    }
-
-    private static void setAccessible(final Field field)
-    {
-        AccessController.doPrivileged( new PrivilegedAction<Object>()
-        {
-            public Object run()
-            {
-                field.setAccessible( true );
-                return 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( Class<?> clazz )
-    {
-        String name = clazz.getName();
-        int dot = name.lastIndexOf( '.' );
-        return ( dot > 0 ) ? name.substring( 0, dot ) : "";
-    }
 
     /**
      * Internal state interface.
@@ -835,7 +608,7 @@ public class FieldHandler
             Field field = null;
             try
             {
-                field = handler.findField( logger );
+                field = FieldUtils.findField( handler.componentClass, handler.metadata.getField(), logger );
                 field = handler.validateField( field, logger );
             }
             catch ( final InvocationTargetException ex )

Added: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldUtils.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldUtils.java?rev=1777628&view=auto
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldUtils.java (added)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldUtils.java Fri Jan  6 15:24:42 2017
@@ -0,0 +1,251 @@
+/*
+ * 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.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.apache.felix.scr.impl.helper.SimpleLogger;
+import org.osgi.service.log.LogService;
+
+public class FieldUtils {
+
+    /**
+     * Finds the field named in the {@link #fieldName} field in the given
+     * <code>targetClass</code>. If the target class has no acceptable method
+     * the class hierarchy is traversed until a field is found or the root
+     * of the class hierarchy is reached without finding a field.
+     *
+     * @return The requested field or <code>null</code> if no acceptable field
+     *      can be found in the target class or any super class.
+     * @throws InvocationTargetException If an unexpected Throwable is caught
+     *      trying to find the requested field.
+     * @param logger
+     */
+    public static Field findField( final Class<?> targetClass,
+    		final String fieldName,
+    		final SimpleLogger logger )
+    throws InvocationTargetException
+    {
+        final ClassLoader targetClasslLoader = targetClass.getClassLoader();
+        final String targetPackage = ClassUtils.getPackageName( targetClass );
+        Class<?> theClass = targetClass;
+        boolean acceptPrivate = true;
+        boolean acceptPackage = true;
+        while (true)
+        {
+
+            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log( LogService.LOG_DEBUG,
+                    "Locating field " + fieldName + " in class " + theClass.getName(), null );
+            }
+
+            try
+            {
+                final Field field = getField( theClass, fieldName, acceptPrivate, acceptPackage, logger );
+                if ( field != null )
+                {
+                    return field;
+                }
+            }
+            catch ( SuitableMethodNotAccessibleException ex )
+            {
+                // log and return null
+                logger.log( LogService.LOG_ERROR,
+                    "findField: Suitable but non-accessible field {0} found in class {1}, subclass of {2}", new Object[]
+                        { fieldName, theClass.getName(), targetClass.getName() }, null );
+                break;
+            }
+
+            // if we get here, we have no field, so check the super class
+            theClass = theClass.getSuperclass();
+            if ( theClass == null )
+            {
+                break;
+            }
+
+            // super class field check ignores private fields and accepts
+            // package fields only if in the same package and package
+            // fields are (still) allowed
+            acceptPackage &= targetClasslLoader == theClass.getClassLoader()
+                && targetPackage.equals( ClassUtils.getPackageName( theClass ) );
+
+            // private fields will not be accepted any more in super classes
+            acceptPrivate = false;
+        }
+
+        // nothing found after all these years ...
+        return null;
+    }
+
+    /**
+     * Finds the field named in the {@link #fieldName} field in the given
+     * <code>targetClass</code>. If the target class has no acceptable field
+     * the class hierarchy is traversed until a field is found or the root
+     * of the class hierarchy is reached without finding a field.
+     *
+     *
+     * @param targetClass The class in which to look for the method
+     * @param acceptPrivate <code>true</code> if private fields should be
+     *      considered.
+     * @param acceptPackage <code>true</code> if package private fields should
+     *      be considered.
+     * @param logger
+     * @return The requested field or <code>null</code> if no acceptable field
+     *      can be found in the target class or any super class.
+     * @throws InvocationTargetException If an unexpected Throwable is caught
+     *      trying to find the requested field.
+     */
+    private static Field getField( final Class<?> clazz,
+    		final String fieldName,
+            final boolean acceptPrivate,
+            final boolean acceptPackage,
+            final SimpleLogger logger )
+    throws SuitableMethodNotAccessibleException, InvocationTargetException
+    {
+        try
+        {
+            // find the declared field in this class
+            final Field field = clazz.getDeclaredField( fieldName );
+
+            // accept public and protected fields only and ensure accessibility
+            if ( accept( field, acceptPrivate, acceptPackage ) )
+            {
+                return field;
+            }
+
+            // the method would fit the requirements but is not acceptable
+            throw new SuitableMethodNotAccessibleException();
+        }
+        catch ( NoSuchFieldException nsfe )
+        {
+            // thrown if no field is declared with the given name and
+            // parameters
+            if ( logger.isLogEnabled( LogService.LOG_DEBUG ) )
+            {
+                logger.log( LogService.LOG_DEBUG, "Declared Field {0}.{1} not found", new Object[]
+                    { clazz.getName(), fieldName }, null );
+            }
+        }
+        catch ( NoClassDefFoundError cdfe )
+        {
+            // may be thrown if a method would be found but the signature
+            // contains throws declaration for an exception which cannot
+            // be loaded
+            if ( logger.isLogEnabled( LogService.LOG_WARNING ) )
+            {
+                StringBuffer buf = new StringBuffer();
+                buf.append( "Failure loooking up field " ).append( fieldName );
+                buf.append( " in class class " ).append( clazz.getName() ).append( ". Assuming no such field." );
+                logger.log( LogService.LOG_WARNING, buf.toString(), cdfe );
+            }
+        }
+        catch ( SuitableMethodNotAccessibleException e)
+        {
+            throw e;
+        }
+        catch ( Throwable throwable )
+        {
+            // unexpected problem accessing the field, don't let everything
+            // blow up in this situation, just throw a declared exception
+            throw new InvocationTargetException( throwable, "Unexpected problem trying to get field " + fieldName );
+        }
+
+        // caught and ignored exception, assume no field and continue search
+        return null;
+    }
+
+    /**
+     * Returns <code>true</code> if the field is acceptable to be returned from the
+     * {@link #getField(Class, String, boolean, boolean, SimpleLogger)} and also
+     * makes the field accessible.
+     * <p>
+     * This method returns <code>true</code> if the field:
+     * <ul>
+     * <li>Is not static</li>
+     * <li>Is public or protected</li>
+     * <li>Is private and <code>acceptPrivate</code> is <code>true</code></li>
+     * <li>Is package private and <code>acceptPackage</code> is <code>true</code></li>
+     * </ul>
+     * <p>
+     *
+     * @param field The field to check
+     * @param acceptPrivate Whether a private field is acceptable
+     * @param acceptPackage Whether a package private field is acceptable
+     * @return whether the field is acceptable
+     */
+    private static boolean accept( final Field field,
+            final boolean acceptPrivate,
+            final boolean acceptPackage )
+    {
+        // check modifiers now
+        final int mod = field.getModifiers();
+
+        // no static fields
+        if ( Modifier.isStatic( mod ) )
+        {
+            return true;
+        }
+
+        // accept public and protected fields
+        if ( Modifier.isPublic( mod ) || Modifier.isProtected( mod ) )
+        {
+            setAccessible( field );
+            return true;
+        }
+
+        // accept private if accepted
+        if ( Modifier.isPrivate( mod ) )
+        {
+            if ( acceptPrivate )
+            {
+                setAccessible( field );
+                return true;
+            }
+
+            return false;
+        }
+
+        // accept default (package)
+        if ( acceptPackage )
+        {
+            setAccessible( field );
+            return true;
+        }
+
+        // else don't accept
+        return false;
+    }
+
+    private static void setAccessible(final Field field)
+    {
+        AccessController.doPrivileged( new PrivilegedAction<Object>()
+        {
+            public Object run()
+            {
+                field.setAccessible( true );
+                return null;
+            }
+        } );
+    }
+}

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

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

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java?rev=1777628&r1=1777627&r2=1777628&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/manager/SingleComponentManager.java Fri Jan  6 15:24:42 2017
@@ -232,9 +232,10 @@ public class SingleComponentManager<S> e
             implementationObjectClass = (Class<S>) bundle.loadClass(
                     getComponentMetadata().getImplementationClassName() )  ;
 
-            // 112.4.4 The class must be public and have a public constructor without arguments so component instances
-            // may be created by the SCR with the newInstance method on Class
-            implementationObject = implementationObjectClass.newInstance();
+            implementationObject = getComponentMethods().getConstructor().newInstance(implementationObjectClass,
+            		componentContext,
+            		this);
+            
         }
         catch ( Throwable t )
         {

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java?rev=1777628&r1=1777627&r2=1777628&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/metadata/ComponentMetadata.java Fri Jan  6 15:24:42 2017
@@ -96,6 +96,9 @@ public class ComponentMetadata
     // 112.4.4 configuration-pid (since DS 1.2)
     private List<String> m_configurationPid;
 
+    // activation fields (since DS 1.4)
+    private List<String> m_activationFields;
+    
     // Associated properties (0..*)
     private final Map<String, Object> m_properties = new HashMap<String, Object>();
 
@@ -433,6 +436,15 @@ public class ComponentMetadata
 
 
 
+	public void setActivationFields( final String[] fields ) 
+	{
+		if ( m_validated )
+		{
+			return;
+		}
+		this.m_activationFields = new ArrayList<String>( Arrays.asList( fields ) );
+	}
+
     /////////////////////////////////////////// GETTERS //////////////////////////////////////
 
 	/**
@@ -605,6 +617,18 @@ public class ComponentMetadata
 
 
     /**
+     * Returns the names of the activation fields
+     *
+     * @return the list of activation fields or {@code null}
+     * @since 2.1.0 (DS 1.4)
+     */
+    public List<String> getActivationFields()
+    {
+        return m_activationFields;
+    }
+
+    
+    /**
      * Returns the name of the deactivate method
      *
      * @return the name of the deactivate method
@@ -975,6 +999,12 @@ public class ComponentMetadata
             }
         }
 
+        // activation fields require DS 1.4
+        if ( m_activationFields != null && !m_dsVersion.isDS14() )
+        {
+            throw validationFailure( "Activation fields require version 1.4 or later");
+        }
+        
         if (m_dsVersion == DSVersion.DS12Felix)
         {
         	m_configurableServiceProperties = true;

Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java?rev=1777628&r1=1777627&r2=1777628&view=diff
==============================================================================
--- felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java (original)
+++ felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/xml/XmlHandler.java Fri Jan  6 15:24:42 2017
@@ -282,6 +282,14 @@ public class XmlHandler implements KXml2
                     m_currentComponent.setConfigureWithInterfaces("true".equals(attributes.getAttribute(NAMESPACE_URI_1_0_FELIX_EXTENSIONS, CONFIGURE_WITH_INTERFACES)));
                     m_currentComponent.setDelayedKeepInstances(m_globalDelayedKeepInstances || "true".equals(attributes.getAttribute(NAMESPACE_URI_1_0_FELIX_EXTENSIONS, DELAYED_KEEP_INSTANCES)));
 
+                    // activation-fields is optional (since DS 1.4)
+                    String activationFields = attributes.getAttribute( "activation-fields" );
+                    if ( activationFields != null ) 
+                    {
+                    	final String[] fields = activationFields.split(" ");
+                    	m_currentComponent.setActivationFields( fields );
+                    }
+                    
                     // Add this component to the list
                     m_components.add( m_currentComponent );
                 }