public ComponentConstructorImpl()

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