/* * JBoss, Home of Professional Open Source * Copyright 2015, Red Hat, Inc., and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed 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.jboss.weld.injection; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Collection; import java.util.Collections; import java.util.Set; import javax.enterprise.inject.spi.AnnotatedField; import javax.enterprise.inject.spi.AnnotatedMember; import javax.enterprise.inject.spi.AnnotatedMethod; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.InjectionPoint; import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedField; import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedMethod; import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType; import org.jboss.weld.bean.builtin.ee.StaticEEResourceProducerField; import org.jboss.weld.bootstrap.api.Service; import org.jboss.weld.injection.spi.ResourceReferenceFactory; import org.jboss.weld.logging.UtilLogger; import org.jboss.weld.manager.BeanManagerImpl; import org.jboss.weld.util.collections.ImmutableSet; import org.jboss.weld.util.reflection.Reflections; /** * Abstract stateless resource injection processor. * * @author Martin Kouba * * @param <S> * @param <C> processor context */ public abstract class ResourceInjectionProcessor<S extends Service, C> { /** * @param fieldInjectionPoint * @param beanManager * @return {@link ResourceInjection} for static producer field or <code>null</code> if required services are not supported or the field is not annotated * with the specific marker annotation * @see StaticEEResourceProducerField */ protected <T, X> ResourceInjection<T> createStaticProducerFieldResourceInjection(FieldInjectionPoint<T, X> fieldInjectionPoint, BeanManagerImpl beanManager) { S injectionServices = getInjectionServices(beanManager); C processorContext = getProcessorContext(beanManager); if (injectionServices != null && fieldInjectionPoint.getAnnotated().isAnnotationPresent(getMarkerAnnotation(processorContext)) && accept(fieldInjectionPoint.getAnnotated(), processorContext)) { return createFieldResourceInjection(fieldInjectionPoint, injectionServices, processorContext); } return null; } /** * * @param declaringBean * @param type * @param manager * @return the set of {@link ResourceInjection}s for the specified bean and type */ protected <T> Set<ResourceInjection<?>> createResourceInjections(Bean<?> declaringBean, EnhancedAnnotatedType<T> type, BeanManagerImpl manager) { S injectionServices = getInjectionServices(manager); C processorContext = getProcessorContext(manager); if (injectionServices == null) { return Collections.emptySet(); } Class<? extends Annotation> marker = getMarkerAnnotation(processorContext); final Collection<EnhancedAnnotatedField<?, ? super T>> fields = type.getDeclaredEnhancedFields(marker); final Collection<EnhancedAnnotatedMethod<?, ? super T>> methods = type.getDeclaredEnhancedMethods(marker); return createResourceInjections(fields, methods, declaringBean, type.getJavaClass(), manager); } /** * * @param fieldInjectionPoint * @param beanManager * @return {@link ResourceInjection} for the given field */ private <T, X> ResourceInjection<T> createFieldResourceInjection(FieldInjectionPoint<T, X> fieldInjectionPoint, S injectionServices, C processorContext) { return new FieldResourceInjection<T, X>(fieldInjectionPoint, Reflections.<ResourceReferenceFactory<T>> cast(getResourceReferenceFactory( fieldInjectionPoint, injectionServices, processorContext))); } /** * * @param methodInjectionPoint * @param beanManager * @return {@link ResourceInjection} for the given setter method */ private <T, X> ResourceInjection<T> createSetterResourceInjection(ParameterInjectionPoint<T, X> parameterInjectionPoint, S injectionServices, C processorContext) { return new SetterResourceInjection<T, X>(parameterInjectionPoint, Reflections.<ResourceReferenceFactory<T>> cast(getResourceReferenceFactory( parameterInjectionPoint, injectionServices, processorContext))); } public Class<? extends Annotation> getMarkerAnnotation(BeanManagerImpl manager) { return getMarkerAnnotation(getProcessorContext(manager)); } protected abstract <T> ResourceReferenceFactory<T> getResourceReferenceFactory(InjectionPoint injectionPoint, S injectionServices, C processorContext); protected abstract Class<? extends Annotation> getMarkerAnnotation(C processorContext); protected abstract C getProcessorContext(BeanManagerImpl manager); protected abstract S getInjectionServices(BeanManagerImpl manager); protected <T> Set<ResourceInjection<?>> createResourceInjections(Iterable<EnhancedAnnotatedField<?, ? super T>> fields, Iterable<EnhancedAnnotatedMethod<?, ? super T>> methods, Bean<?> declaringBean, Class<?> declaringClass, BeanManagerImpl manager) { ImmutableSet.Builder<ResourceInjection<?>> resourceInjections = ImmutableSet.builder(); S injectionServices = getInjectionServices(manager); C processorContext = getProcessorContext(manager); for (EnhancedAnnotatedField<?, ? super T> field : fields) { if (accept(field, processorContext)) { resourceInjections.add(createFieldResourceInjection( InjectionPointFactory.silentInstance().createFieldInjectionPoint(field, declaringBean, declaringClass, manager), injectionServices, processorContext)); } } for (EnhancedAnnotatedMethod<?, ?> method : methods) { if (method.getParameters().size() != 1) { throw UtilLogger.LOG.resourceSetterInjectionNotAJavabean(method); } if (accept(method, processorContext)) { resourceInjections.add(createSetterResourceInjection( InjectionPointFactory.silentInstance().createParameterInjectionPoint(method.getEnhancedParameters().get(0), declaringBean, declaringClass, manager), injectionServices, processorContext)); } } return resourceInjections.build(); } /** * Allows an implementation to indicate whether it accepts a given injection point annotated with the marker annotation. */ protected boolean accept(AnnotatedMember<?> member, C processorContext) { return true; } protected Type getResourceInjectionPointType(AnnotatedMember<?> member) { if (member instanceof AnnotatedField<?>) { return member.getBaseType(); } if (member instanceof AnnotatedMethod<?>) { AnnotatedMethod<?> method = (AnnotatedMethod<?>) member; if (method.getParameters().size() != 1) { throw UtilLogger.LOG.resourceSetterInjectionNotAJavabean(method); } return method.getParameters().get(0).getBaseType(); } throw new IllegalArgumentException("Unknown member " + member); } }