/* * 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.Constructor; import java.lang.reflect.Field; import java.util.Map; import org.apache.felix.scr.impl.inject.ValueUtils.ValueType; import org.apache.felix.scr.impl.inject.field.FieldUtils; import org.apache.felix.scr.impl.manager.ComponentContextImpl; import org.apache.felix.scr.impl.metadata.ReferenceMetadata; /** * This implementation is used to construct a component instance object, * call the constructor and set the activation fields. */ public class ConstructorMethodImpl<T> implements ConstructorMethod<T> { private volatile boolean m_initialized = false; private volatile ValueType[] m_paramTypes; private volatile Field[] m_fields; private volatile Constructor<T> m_constructor; private volatile ValueType[] m_constructorArgTypes; @SuppressWarnings("unchecked") @Override public <S> T newInstance(Class<T> componentClass, ComponentContextImpl<T> componentContext, Map<Integer, ReferencePair<S>> parameterMap) throws Exception { if ( !m_initialized ) { // activation fields if ( componentContext.getComponentMetadata().getActivationFields() != null ) { m_paramTypes = new ValueType[componentContext.getComponentMetadata().getActivationFields().size()]; m_fields = new Field[m_paramTypes.length]; int index = 0; for(final String fieldName : componentContext.getComponentMetadata().getActivationFields() ) { final FieldUtils.FieldSearchResult result = FieldUtils.searchField(componentClass, fieldName, componentContext.getLogger()); if ( result == null || result.field == null ) { m_paramTypes[index] = null; m_fields[index] = null; } else { if ( result.usable ) { m_paramTypes[index] = ValueUtils.getValueType(result.field.getType()); m_fields[index] = result.field; } else { m_paramTypes[index] = ValueType.ignore; m_fields[index] = null; } } index++; } } else { m_paramTypes = ValueUtils.EMPTY_VALUE_TYPES; m_fields = null; } // constructor injection if ( componentContext.getComponentMetadata().isActivateConstructor() ) { // TODO search constructor m_constructor = null; boolean hasFailure = false; final Class<?>[] argTypes = m_constructor.getParameterTypes(); m_constructorArgTypes = new ValueType[argTypes.length]; for(int i=0;i<m_constructorArgTypes.length;i++) { final ReferencePair<S> pair = parameterMap.get(i); ReferenceMetadata reference = pair == null ? null : pair.dependencyManager.getReferenceMetadata(); if ( reference == null ) { m_constructorArgTypes[i] = ValueUtils.getValueType(argTypes[i]); } else { m_constructorArgTypes[i] = ValueUtils.getReferenceValueType(componentClass, reference, argTypes[i], null, componentContext.getLogger()); } if ( m_constructorArgTypes[i] == ValueType.ignore ) { hasFailure = true; break; } } if ( hasFailure ) { m_constructor = null; } } // done m_initialized = true; } // if we have fields and one is in state failure (type == null) we can directly throw int index = 0; for(final ValueType t : m_paramTypes) { if ( t == null ) { throw new InstantiationException("Field " + componentContext.getComponentMetadata().getActivationFields().get(index) + " not found; Component will fail"); } index++; } // constructor final T component; if ( componentContext.getComponentMetadata().isActivateConstructor() ) { if ( m_constructor == null ) { throw new InstantiationException("Constructor not found; Component will fail"); } final Object[] args = new Object[m_constructorArgTypes.length]; for(int i=0; i<args.length; i++) { // TODO - get ref pair final ReferencePair<S> pair = parameterMap.get(i); args[i] = ValueUtils.getValue(componentClass.getName(), m_constructorArgTypes[i], m_constructor.getParameterTypes()[i], componentContext, null); } component = m_constructor.newInstance(args); } else { component = (T)ConstructorMethod.DEFAULT.newInstance((Class<Object>)componentClass, (ComponentContextImpl<Object>)componentContext, null); } // activation fields for(int i = 0; i<m_paramTypes.length; i++) { if ( m_paramTypes[i] != ValueType.ignore ) { final Object value = ValueUtils.getValue(componentClass.getName(), m_paramTypes[i], m_fields[i].getType(), componentContext, null); FieldUtils.setField(m_fields[i], component, value, componentContext.getLogger()); } } return component; } }