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 );
}