/* * JBoss, Home of Professional Open Source * Copyright 2013, 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 static org.jboss.weld.util.reflection.Reflections.getRawType; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import javax.annotation.Resource; import javax.enterprise.inject.spi.AnnotatedMember; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.InjectionPoint; import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType; import org.jboss.weld.bootstrap.api.Service; import org.jboss.weld.injection.spi.JaxwsInjectionServices; import org.jboss.weld.injection.spi.JpaInjectionServices; import org.jboss.weld.injection.spi.ResourceInjectionServices; import org.jboss.weld.injection.spi.ResourceReferenceFactory; import org.jboss.weld.logging.BeanLogger; import org.jboss.weld.manager.BeanManagerImpl; import org.jboss.weld.persistence.PersistenceApiAbstraction; import org.jboss.weld.util.reflection.Reflections; import org.jboss.weld.ws.WSApiAbstraction; /** * Factory class that produces {@link ResourceInjection} instances for resource fields and setter methods. * * @author Martin Kouba */ public final class ResourceInjectionFactory implements Service, Iterable<ResourceInjectionProcessor<?, ?>> { private final List<ResourceInjectionProcessor<?, ?>> resourceInjectionProcessors; public ResourceInjectionFactory() { this.resourceInjectionProcessors = new CopyOnWriteArrayList<>(); initializeProcessors(); } public void addResourceInjectionProcessor(ResourceInjectionProcessor<?, ?> processor) { resourceInjectionProcessors.add(processor); } /** * * @param declaringBean * @param type * @param manager * @return resource injections for the given bean */ public List<Set<ResourceInjection<?>>> getResourceInjections(Bean<?> declaringBean, EnhancedAnnotatedType<?> type, BeanManagerImpl manager) { List<Set<ResourceInjection<?>>> result = new ArrayList<Set<ResourceInjection<?>>>(); // Iterate through the type hierarchy for (EnhancedAnnotatedType<?> actualType = type; actualType != null && !actualType.getJavaClass().equals(Object.class); actualType = actualType .getEnhancedSuperclass()) { Set<ResourceInjection<?>> resourceInjections = discoverType(declaringBean, actualType, manager); if (!resourceInjections.isEmpty()) { result.add(resourceInjections); } } Collections.reverse(result); return result; } /** * * * @param fieldInjectionPoint * @param beanManager * @return the corresponding resource injection for the given field injection point, or <code>null</code> if no such * resource injection exists */ public <T, X> ResourceInjection<T> getStaticProducerFieldResourceInjection(FieldInjectionPoint<T, X> fieldInjectionPoint, BeanManagerImpl beanManager) { ResourceInjection<T> resourceInjection = null; for (ResourceInjectionProcessor<?, ?> processor : resourceInjectionProcessors) { resourceInjection = processor.createStaticProducerFieldResourceInjection(fieldInjectionPoint, beanManager); if (resourceInjection != null) { break; } } return resourceInjection; } private void initializeProcessors() { resourceInjectionProcessors.add(new PersistenceUnitResourceInjectionProcessor()); resourceInjectionProcessors.add(new PersistenceContextResourceInjectionProcessor()); resourceInjectionProcessors.add(new ResourceResourceInjectionProcessor()); resourceInjectionProcessors.add(new WebServiceResourceInjectionProcessor()); } /** * JPA persistence unit resource injection processor. * */ private static class PersistenceUnitResourceInjectionProcessor extends ResourceInjectionProcessor<JpaInjectionServices, PersistenceApiAbstraction> { @Override protected <T> ResourceReferenceFactory<T> getResourceReferenceFactory(InjectionPoint injectionPoint, JpaInjectionServices injectionServices, PersistenceApiAbstraction apiAbstraction) { if (!injectionPoint.getType().equals(apiAbstraction.ENTITY_MANAGER_FACTORY_CLASS)) { throw BeanLogger.LOG.invalidResourceProducerType(injectionPoint.getAnnotated(), apiAbstraction.ENTITY_MANAGER_FACTORY_CLASS); } return Reflections.<ResourceReferenceFactory<T>> cast(injectionServices .registerPersistenceUnitInjectionPoint(injectionPoint)); } @Override protected Class<? extends Annotation> getMarkerAnnotation(PersistenceApiAbstraction apiAbstraction) { return apiAbstraction.PERSISTENCE_UNIT_ANNOTATION_CLASS; } @Override protected PersistenceApiAbstraction getProcessorContext(BeanManagerImpl manager) { return manager.getServices().get(PersistenceApiAbstraction.class); } @Override protected JpaInjectionServices getInjectionServices(BeanManagerImpl manager) { return manager.getServices().get(JpaInjectionServices.class); } @Override protected boolean accept(AnnotatedMember<?> member, PersistenceApiAbstraction apiAbstraction) { // ugly hack that allows application servers to support hibernate session injection while at the same time // the injection points are validated by Weld for invalid types (required by the TCK) return !apiAbstraction.SESSION_FACTORY_NAME.equals(getRawType(getResourceInjectionPointType(member)).getName()); } } /** * JPA persistence context resource injection processor. */ private static class PersistenceContextResourceInjectionProcessor extends ResourceInjectionProcessor<JpaInjectionServices, PersistenceApiAbstraction> { @Override protected <T> ResourceReferenceFactory<T> getResourceReferenceFactory(InjectionPoint injectionPoint, JpaInjectionServices injectionServices, PersistenceApiAbstraction apiAbstraction) { if (!injectionPoint.getType().equals(apiAbstraction.ENTITY_MANAGER_CLASS)) { throw BeanLogger.LOG.invalidResourceProducerType(injectionPoint.getAnnotated(), apiAbstraction.ENTITY_MANAGER_CLASS); } return Reflections.<ResourceReferenceFactory<T>> cast(injectionServices .registerPersistenceContextInjectionPoint(injectionPoint)); } @Override protected Class<? extends Annotation> getMarkerAnnotation(PersistenceApiAbstraction apiAbstraction) { return apiAbstraction.PERSISTENCE_CONTEXT_ANNOTATION_CLASS; } @Override protected PersistenceApiAbstraction getProcessorContext(BeanManagerImpl manager) { return manager.getServices().get(PersistenceApiAbstraction.class); } @Override protected JpaInjectionServices getInjectionServices(BeanManagerImpl manager) { return manager.getServices().get(JpaInjectionServices.class); } @Override protected boolean accept(AnnotatedMember<?> member, PersistenceApiAbstraction apiAbstraction) { // ugly hack that allows application servers to support hibernate session injection while at the same time // the injection points are validated by Weld for invalid types (required by the TCK) return !apiAbstraction.SESSION_NAME.equals(getRawType(getResourceInjectionPointType(member)).getName()); } } /** * Resource injection processor. */ private static class ResourceResourceInjectionProcessor extends ResourceInjectionProcessor<ResourceInjectionServices, Object> { @Override protected <T> ResourceReferenceFactory<T> getResourceReferenceFactory(InjectionPoint injectionPoint, ResourceInjectionServices injectionServices, Object processorContext) { return Reflections.<ResourceReferenceFactory<T>> cast(injectionServices .registerResourceInjectionPoint(injectionPoint)); } @Override protected Class<? extends Annotation> getMarkerAnnotation(Object processorContext) { return Resource.class; } @Override protected Object getProcessorContext(BeanManagerImpl manager) { return null; } @Override protected ResourceInjectionServices getInjectionServices(BeanManagerImpl manager) { return manager.getServices().get(ResourceInjectionServices.class); } } /** * JAX-WS resource injection processor. */ private static class WebServiceResourceInjectionProcessor extends ResourceInjectionProcessor<JaxwsInjectionServices, WSApiAbstraction> { @Override protected <T> ResourceReferenceFactory<T> getResourceReferenceFactory(InjectionPoint injectionPoint, JaxwsInjectionServices injectionServices, WSApiAbstraction apiAbstraction) { return Reflections.<ResourceReferenceFactory<T>> cast(injectionServices .registerWebServiceRefInjectionPoint(injectionPoint)); } @Override protected Class<? extends Annotation> getMarkerAnnotation(WSApiAbstraction apiAbstraction) { return apiAbstraction.WEB_SERVICE_REF_ANNOTATION_CLASS; } @Override protected WSApiAbstraction getProcessorContext(BeanManagerImpl manager) { return manager.getServices().get(WSApiAbstraction.class); } @Override protected JaxwsInjectionServices getInjectionServices(BeanManagerImpl manager) { return manager.getServices().get(JaxwsInjectionServices.class); } } /** * * @param bean * @param type * @param manager * @return found resource injections for the given bean and type */ private Set<ResourceInjection<?>> discoverType(Bean<?> bean, EnhancedAnnotatedType<?> type, BeanManagerImpl manager) { Set<ResourceInjection<?>> resourceInjections = new HashSet<ResourceInjection<?>>(); for (ResourceInjectionProcessor<?, ?> processor : resourceInjectionProcessors) { resourceInjections.addAll(processor.createResourceInjections(bean, type, manager)); } return resourceInjections; } @Override public void cleanup() { } @Override public Iterator<ResourceInjectionProcessor<?, ?>> iterator() { return resourceInjectionProcessors.iterator(); } }