in scr/src/main/java/org/apache/felix/scr/impl/inject/internal/ComponentConstructorImpl.java [56:229]
public ComponentConstructorImpl(final ComponentMetadata componentMetadata,
final Class<S> componentClass,
final ComponentLogger logger)
{
// constructor injection
// get reference parameter map
final Map<Integer, List<ReferenceMetadata>> paramMap = ( componentMetadata.getNumberOfConstructorParameters() > 0 ? new HashMap<Integer, List<ReferenceMetadata>>() : null);
for ( final ReferenceMetadata refMetadata : componentMetadata.getDependencies())
{
if ( refMetadata.getParameterIndex() != null )
{
final int index = refMetadata.getParameterIndex();
if ( index > componentMetadata.getNumberOfConstructorParameters() )
{
// if the index (starting at 0) is equal or higher than the number of constructor arguments
// we log an error and ignore the reference
logger.log(Level.ERROR,
"Ignoring reference {0} for constructor injection. Parameter index is too high.", null,
refMetadata.getName() );
}
else if ( !refMetadata.isStatic() )
{
// if the reference is dynamic, we log an error and ignore the reference
logger.log(Level.ERROR,
"Ignoring reference {0} for constructor injection. Reference is dynamic.", null,
refMetadata.getName() );
}
List<ReferenceMetadata> list = paramMap.get(index);
if ( list == null )
{
list = new ArrayList<>();
paramMap.put(index, list);
}
list.add(refMetadata);
}
}
// Search constructor
Constructor<S> found = null;
ValueType[] foundTypes = null;
ReferenceMetadata[] foundRefs = null;
final Constructor<?>[] constructors = componentClass.getConstructors();
for(final Constructor<?> c : constructors)
{
// we try each constructor with the right number of arguments
if ( c.getParameterTypes().length == componentMetadata.getNumberOfConstructorParameters() )
{
final Constructor<S> check = (Constructor<S>) c;
logger.log(Level.DEBUG,
"Checking constructor {0}", null,
check );
// check argument types
if ( componentMetadata.getNumberOfConstructorParameters() > 0 )
{
boolean hasFailure = false;
final Class<?>[] argTypes = check.getParameterTypes();
foundTypes = new ValueType[argTypes.length];
foundRefs = new ReferenceMetadata[argTypes.length];
for(int i=0; i<foundTypes.length;i++)
{
final List<ReferenceMetadata> refs = paramMap.get(i);
if ( refs == null )
{
foundTypes[i] = ValueUtils.getValueType(argTypes[i]);
if ( foundTypes[i] == ValueType.ignore )
{
logger.log(Level.DEBUG,
"Constructor argument type {0} not supported by constructor injection: {1}", null,
i, argTypes[i] );
}
}
else
{
for(final ReferenceMetadata ref : refs)
{
final ValueType t = ValueUtils.getReferenceValueType(componentClass, ref, argTypes[i], null, logger);
if ( t != null )
{
foundTypes[i] = t;
foundRefs[i] = ref;
break;
}
}
if ( foundTypes[i] == null )
{
foundTypes[i] = ValueType.ignore;
}
else
{
if ( refs.size() > 1 )
{
logger.log(Level.ERROR,
"Several references for constructor injection of parameter {0}. Only {1} will be used out of: {2}.", null,
i, foundRefs[i].getName(), getNames(refs) );
}
}
}
if ( foundTypes[i] == ValueType.ignore )
{
hasFailure = true;
break;
}
}
if ( !hasFailure )
{
found = check;
break;
}
}
else
{
found = (Constructor<S>) c;
break;
}
}
}
this.constructor = found;
this.constructorArgTypes = foundTypes;
this.constructorRefs = foundRefs;
// activation fields
if ( componentMetadata.getActivationFields() != null )
{
activationFieldTypes = new ValueType[componentMetadata.getActivationFields().size()];
activationFields = new Field[activationFieldTypes.length];
int index = 0;
for(final String fieldName : componentMetadata.getActivationFields() )
{
final FieldUtils.FieldSearchResult result = FieldUtils.searchField(componentClass, fieldName, logger);
if ( result == null || result.field == null )
{
activationFieldTypes[index] = null;
activationFields[index] = null;
}
else
{
if ( result.usable )
{
activationFieldTypes[index] = ValueUtils.getValueType(result.field.getType());
activationFields[index] = result.field;
}
else
{
activationFieldTypes[index] = ValueType.ignore;
activationFields[index] = null;
}
}
index++;
}
}
else
{
activationFieldTypes = ValueUtils.EMPTY_VALUE_TYPES;
activationFields = null;
}
if ( constructor == null )
{
logger.log(Level.ERROR,
"Constructor with {0} arguments not found. Component will fail.", null,
componentMetadata.getNumberOfConstructorParameters() );
}
else
{
logger.log(Level.DEBUG,
"Found constructor with {0} arguments : {1}", null,
componentMetadata.getNumberOfConstructorParameters(), found );
}
}