FELIX-4631 : [DS][R6/RFC212] Implement field injection. WiP
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1637766 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java b/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java
index ee040ee..0cda876 100644
--- a/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java
+++ b/scr/src/main/java/org/apache/felix/scr/impl/helper/FieldHandler.java
@@ -61,6 +61,9 @@
/** State handling. */
private volatile State state;
+ /** Last ref pair used to set. */
+ private volatile RefPair<?, ?> lastRefPair;
+
/**
* Create a new field handler
* @param fieldName name of the field
@@ -317,15 +320,8 @@
UPDATED
};
- private MethodResult updateField( final METHOD_TYPE mType,
- final Object componentInstance,
- final BindParameters bp,
- final SimpleLogger logger )
- throws InvocationTargetException
- {
- final ComponentContextImpl key = bp.getComponentContext();
- final RefPair<?, ?> refPair = bp.getRefPair();
-
+ private Object getValue(final ComponentContextImpl key,
+ final RefPair<?, ?> refPair) {
final Object obj;
switch ( this.valueType ) {
case serviceType : obj = refPair.getServiceObject(key); break;
@@ -339,20 +335,86 @@
break;
default: obj = null;
}
+ return obj;
+ }
- try {
- if ( mType == METHOD_TYPE.BIND ) {
- field.set(componentInstance, obj);
- } else if ( mType == METHOD_TYPE.UNBIND ) {
- field.set(componentInstance, null);
+ private MethodResult updateField( final METHOD_TYPE mType,
+ final Object componentInstance,
+ final BindParameters bp,
+ final SimpleLogger logger )
+ throws InvocationTargetException
+ {
+ final ComponentContextImpl key = bp.getComponentContext();
+ final RefPair<?, ?> refPair = bp.getRefPair();
+
+ if ( !this.metadata.isMultiple() )
+ {
+ // unary references
+ // unbind needs only be done, if reference is dynamic and optional
+ if ( mType == METHOD_TYPE.UNBIND )
+ {
+ if ( this.metadata.isOptional() && !this.metadata.isStatic() )
+ {
+ // we only reset if it was previously set with this value
+ if ( refPair == lastRefPair )
+ {
+ this.setFieldValue(componentInstance, null);
+ this.lastRefPair = null;
+ }
+ }
+ else
+ {
+ this.lastRefPair = null;
+ }
}
+ // updated needs only be done, if reference is dynamic and optional
+ else if ( mType == METHOD_TYPE.UPDATED )
+ {
+ if ( this.metadata.isOptional() && !this.metadata.isStatic() )
+ {
+ final Object obj = getValue(key, refPair);
+ this.setFieldValue(componentInstance, obj);
+ this.lastRefPair = refPair;
+ }
+ else
+ {
+ this.lastRefPair = null;
+ }
+ }
+ // bind needs always be done
+ else
+ {
+ final Object obj = getValue(key, refPair);
+ this.setFieldValue(componentInstance, obj);
+ this.lastRefPair = refPair;
+ }
+ }
+
+ return MethodResult.VOID;
+ }
+
+ private void setFieldValue(final Object componentInstance, final Object value)
+ throws InvocationTargetException
+ {
+ try {
+ field.set(componentInstance, value);
} catch ( final IllegalArgumentException iae ) {
throw new InvocationTargetException(iae);
} catch ( final IllegalAccessException iae ) {
throw new InvocationTargetException(iae);
}
+ }
- return MethodResult.VOID;
+ private Object getFieldValue(final Object componentInstance)
+ throws InvocationTargetException
+ {
+ try {
+ return field.get(componentInstance);
+ } catch ( final IllegalArgumentException iae ) {
+ throw new InvocationTargetException(iae);
+ } catch ( final IllegalAccessException iae ) {
+ throw new InvocationTargetException(iae);
+ }
}
/**
@@ -374,10 +436,12 @@
* @param acceptPackage Whether a package private field is acceptable
* @return whether the field is acceptable
*/
- private static boolean accept( final Field field, boolean acceptPrivate, boolean acceptPackage )
+ private static boolean accept( final Field field,
+ final boolean acceptPrivate,
+ final boolean acceptPackage )
{
// check modifiers now
- int mod = field.getModifiers();
+ final int mod = field.getModifiers();
// no static fields
if ( Modifier.isStatic( mod ) )
@@ -445,12 +509,14 @@
private static interface State
{
- MethodResult invoke( final FieldHandler baseMethod,
+ MethodResult invoke( final FieldHandler handler,
final METHOD_TYPE mType,
final Object componentInstance,
final BindParameters rawParameter,
final SimpleLogger logger )
throws InvocationTargetException;
+
+ boolean fieldExists( final FieldHandler handler, final SimpleLogger logger);
}
/**
@@ -460,36 +526,42 @@
{
private static final State INSTANCE = new NotResolved();
- private synchronized void resolve( final FieldHandler baseMethod, final SimpleLogger logger )
+ private synchronized void resolve( final FieldHandler handler, final SimpleLogger logger )
{
logger.log( LogService.LOG_DEBUG, "getting field: {0}", new Object[]
- {baseMethod.metadata.getField()}, null );
+ {handler.metadata.getField()}, null );
// resolve the field
Field field = null;
try
{
- field = baseMethod.findField( logger );
- field = baseMethod.validateField( field, logger );
+ field = handler.findField( logger );
+ field = handler.validateField( field, logger );
}
catch ( final InvocationTargetException ex )
{
logger.log( LogService.LOG_WARNING, "{0} cannot be found", new Object[]
- {baseMethod.metadata.getField()}, ex.getTargetException() );
+ {handler.metadata.getField()}, ex.getTargetException() );
}
- baseMethod.setField( field, logger );
+ handler.setField( field, logger );
}
- public MethodResult invoke( final FieldHandler baseMethod,
+ public MethodResult invoke( final FieldHandler handler,
final METHOD_TYPE mType,
final Object componentInstance,
final BindParameters rawParameter,
SimpleLogger logger )
throws InvocationTargetException
{
- resolve( baseMethod, logger );
- return baseMethod.state.invoke( baseMethod, mType, componentInstance, rawParameter, logger );
+ resolve( handler, logger );
+ return handler.state.invoke( handler, mType, componentInstance, rawParameter, logger );
+ }
+
+ public boolean fieldExists( final FieldHandler handler, final SimpleLogger logger)
+ {
+ resolve( handler, logger );
+ return handler.state.fieldExists( handler, logger );
}
}
@@ -500,17 +572,21 @@
{
private static final State INSTANCE = new NotFound();
-
- public MethodResult invoke( final FieldHandler baseMethod,
+ public MethodResult invoke( final FieldHandler handler,
final METHOD_TYPE mType,
final Object componentInstance,
final BindParameters rawParameter,
final SimpleLogger logger )
{
logger.log( LogService.LOG_ERROR, "Field [{0}] not found", new Object[]
- { baseMethod.metadata.getField() }, null );
+ { handler.metadata.getField() }, null );
return null;
}
+
+ public boolean fieldExists( final FieldHandler handler, final SimpleLogger logger)
+ {
+ return false;
+ }
}
/**
@@ -520,15 +596,25 @@
{
private static final State INSTANCE = new Resolved();
- public MethodResult invoke( final FieldHandler baseMethod,
+ public MethodResult invoke( final FieldHandler handler,
final METHOD_TYPE mType,
final Object componentInstance,
final BindParameters rawParameter,
final SimpleLogger logger )
throws InvocationTargetException
{
- return baseMethod.updateField( mType, componentInstance, rawParameter, logger );
+ return handler.updateField( mType, componentInstance, rawParameter, logger );
}
+
+ public boolean fieldExists( final FieldHandler handler, final SimpleLogger logger)
+ {
+ return true;
+ }
+ }
+
+ public boolean fieldExists( SimpleLogger logger )
+ {
+ return this.state.fieldExists( this, logger );
}
public static final class ReferenceMethodImpl implements ReferenceMethod {
@@ -571,8 +657,8 @@
{
//??? this resolves which we need.... better way?
if ( refPair.getServiceObject(key) == null
- )
- // TODO: && (handler.valueType == ParamType.serviceType || handler.valueType == ParamType.tuple ) )
+ && handler.fieldExists( logger )
+ && (handler.valueType == ParamType.serviceType || handler.valueType == ParamType.tuple ) )
{
return refPair.getServiceObject(key, context, logger);
}