You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by tj...@apache.org on 2017/05/01 17:15:48 UTC
svn commit: r1793378 -
/felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java
Author: tjwatson
Date: Mon May 1 17:15:48 2017
New Revision: 1793378
URL: http://svn.apache.org/viewvc?rev=1793378&view=rev
Log:
FELIX-5628 : Global lock in FieldHandler.NotResolved::resolve method can cause deadlock
Modified:
felix/trunk/scr/src/main/java/org/apache/felix/scr/impl/inject/FieldHandler.java
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=1793378&r1=1793377&r2=1793378&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 Mon May 1 17:15:48 2017
@@ -93,9 +93,10 @@ public class FieldHandler
* @param f The field or {@code null}.
* @param logger The logger
*/
- private void setField( final Field f, final SimpleLogger logger )
+ synchronized private void setField( final FieldInfo f, final SimpleLogger logger )
{
- this.field = f;
+ this.field = f.getField();
+ this.valueType = f.getType();
if ( f != null )
{
@@ -259,10 +260,15 @@ public class FieldHandler
* Validate the field, type etc.
* @param f The field
* @param logger The logger
- * @return The field if it's valid, {@code null} otherwise.
+ * @return The FieldInfo, the field info will have a type of {@link ParamType#ignore}
+ * if the field is not valid.
*/
- private Field validateField( final Field f, final SimpleLogger logger )
+ private FieldInfo validateField( final Field f, final SimpleLogger logger )
{
+ if (f == null)
+ {
+ return new FieldInfo(f, ParamType.ignore);
+ }
final Class<?> fieldType = f.getType();
final Class<?> referenceType = ClassUtils.getClassFromComponentClassLoader(
this.componentClass, metadata.getInterface(), logger);
@@ -272,45 +278,45 @@ public class FieldHandler
{
logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be static", new Object[]
{metadata.getField(), this.componentClass}, null );
- valueType = ParamType.ignore;
- return f;
+ return new FieldInfo(f, ParamType.ignore);
}
+ ParamType type = null;
// unary reference
if ( !metadata.isMultiple() )
{
if ( fieldType.isAssignableFrom(referenceType) )
{
- valueType = ParamType.serviceType;
+ type = ParamType.serviceType;
}
else if ( fieldType == ClassUtils.SERVICE_REFERENCE_CLASS )
{
- valueType = ParamType.serviceReference;
+ type = ParamType.serviceReference;
}
else if ( fieldType == ClassUtils.COMPONENTS_SERVICE_OBJECTS_CLASS )
{
- valueType = ParamType.serviceObjects;
+ type = ParamType.serviceObjects;
}
else if ( fieldType == ClassUtils.MAP_CLASS )
{
- valueType = ParamType.map;
+ type = ParamType.map;
}
else if ( fieldType == ClassUtils.MAP_ENTRY_CLASS )
{
- valueType = ParamType.tuple;
+ type = ParamType.tuple;
}
else
{
logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}", new Object[]
{metadata.getField(), this.componentClass, fieldType.getName()}, null );
- valueType = ParamType.ignore;
+ type = ParamType.ignore;
}
// if the field is dynamic, it has to be volatile (field is ignored, case logged) (112.3.8.1)
if ( !metadata.isStatic() && !Modifier.isVolatile(f.getModifiers()) ) {
logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must be declared volatile to handle a dynamic reference", new Object[]
{metadata.getField(), this.componentClass}, null );
- valueType = ParamType.ignore;
+ type = ParamType.ignore;
}
// the field must not be final (field is ignored, case logged) (112.3.8.1)
@@ -318,30 +324,30 @@ public class FieldHandler
{
logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be declared as final", new Object[]
{metadata.getField(), this.componentClass}, null );
- valueType = ParamType.ignore;
+ type = ParamType.ignore;
}
}
else
{
if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICE.equals(metadata.getFieldCollectionType()) )
{
- valueType = ParamType.serviceType;
+ type = ParamType.serviceType;
}
else if ( ReferenceMetadata.FIELD_VALUE_TYPE_REFERENCE.equals(metadata.getFieldCollectionType()) )
{
- valueType = ParamType.serviceReference;
+ type = ParamType.serviceReference;
}
else if ( ReferenceMetadata.FIELD_VALUE_TYPE_SERVICEOBJECTS.equals(metadata.getFieldCollectionType()) )
{
- valueType = ParamType.serviceObjects;
+ type = ParamType.serviceObjects;
}
else if ( ReferenceMetadata.FIELD_VALUE_TYPE_PROPERTIES.equals(metadata.getFieldCollectionType()) )
{
- valueType = ParamType.map;
+ type = ParamType.map;
}
else if ( ReferenceMetadata.FIELD_VALUE_TYPE_TUPLE.equals(metadata.getFieldCollectionType()) )
{
- valueType = ParamType.tuple;
+ type = ParamType.tuple;
}
// multiple cardinality, field type must be collection or subtype
@@ -349,7 +355,7 @@ public class FieldHandler
{
logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}", new Object[]
{metadata.getField(), this.componentClass, fieldType.getName()}, null );
- valueType = ParamType.ignore;
+ type = ParamType.ignore;
}
// additional checks for replace strategy:
@@ -360,7 +366,7 @@ public class FieldHandler
{
logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must be declared volatile to handle a dynamic reference", new Object[]
{metadata.getField(), this.componentClass}, null );
- valueType = ParamType.ignore;
+ type = ParamType.ignore;
}
// replace strategy: field must not be final (field is ignored, case logged) (112.3.8.1)
@@ -370,14 +376,14 @@ public class FieldHandler
logger.log( LogService.LOG_ERROR, "Field {0} in component {1} has unsupported type {2}."+
" It must be one of java.util.Collection or java.util.List.",
new Object[] {metadata.getField(), this.componentClass, fieldType.getName()}, null );
- valueType = ParamType.ignore;
+ type = ParamType.ignore;
}
if ( Modifier.isFinal(f.getModifiers()) )
{
logger.log( LogService.LOG_ERROR, "Field {0} in component {1} must not be declared as final", new Object[]
{metadata.getField(), this.componentClass}, null );
- valueType = ParamType.ignore;
+ type = ParamType.ignore;
}
}
}
@@ -386,9 +392,9 @@ public class FieldHandler
{
logger.log( LogService.LOG_ERROR, "Update strategy for field {0} in component {1} only allowed for non static field references.", new Object[]
{metadata.getField(), this.componentClass}, null );
- valueType = ParamType.ignore;
+ type = ParamType.ignore;
}
- return f;
+ return new FieldInfo(f, type);
}
private enum METHOD_TYPE
@@ -818,28 +824,25 @@ public class FieldHandler
{
private static final State INSTANCE = new NotResolved();
- private synchronized void resolve( final FieldHandler handler, final SimpleLogger logger )
+ private void resolve( final FieldHandler handler, final SimpleLogger logger )
{
logger.log( LogService.LOG_DEBUG, "getting field: {0}", new Object[]
{handler.metadata.getField()}, null );
// resolve the field
- Field field = null;
+ FieldInfo fieldInfo = null;
try
{
- field = handler.findField( logger );
- if ( field != null ) {
- field = handler.validateField( field, logger );
- }
+ fieldInfo = handler.validateField(handler.findField(logger), logger);
}
catch ( final InvocationTargetException ex )
{
logger.log( LogService.LOG_WARNING, "{0} cannot be found", new Object[]
{handler.metadata.getField()}, ex.getTargetException() );
- field = null;
+ fieldInfo = new FieldInfo(null, ParamType.ignore);
}
- handler.setField( field, logger );
+ handler.setField(fieldInfo, logger );
}
@Override
@@ -1026,4 +1029,22 @@ public class FieldHandler
}
};
}
+
+ private static final class FieldInfo {
+ private final Field m_field;
+ private final ParamType m_type;
+ public FieldInfo(Field m_field, ParamType m_type)
+ {
+ this.m_field = m_field;
+ this.m_type = m_type;
+ }
+
+ Field getField() {
+ return m_field;
+ }
+
+ ParamType getType() {
+ return m_type;
+ }
+ }
}