/* * JBoss, Home of Professional Open Source * Copyright 2008, 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.bean; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Collections; import java.util.Set; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.event.Observes; import javax.enterprise.inject.Default; import javax.enterprise.inject.Disposes; import javax.enterprise.inject.Produces; import javax.enterprise.inject.Specializes; import javax.enterprise.inject.spi.AnnotatedMethod; import javax.enterprise.inject.spi.AnnotatedParameter; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.Decorator; import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.spi.Interceptor; import javax.inject.Inject; import javax.inject.Qualifier; import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedMethod; import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedParameter; import org.jboss.weld.annotated.enhanced.MethodSignature; import org.jboss.weld.bootstrap.Validator; import org.jboss.weld.injection.InjectionPointFactory; import org.jboss.weld.injection.MethodInjectionPoint; import org.jboss.weld.injection.MethodInjectionPoint.MethodInjectionPointType; import org.jboss.weld.injection.MethodInvocationStrategy; import org.jboss.weld.injection.ParameterInjectionPoint; import org.jboss.weld.logging.BeanLogger; import org.jboss.weld.manager.BeanManagerImpl; import org.jboss.weld.metadata.cache.MetaAnnotationStore; import org.jboss.weld.resolution.QualifierInstance; import org.jboss.weld.util.reflection.Formats; import org.jboss.weld.util.reflection.Reflections; public class DisposalMethod<X, T> { private static final Set<Class<? extends Annotation>> SPECIAL_PARAM_MARKERS = Collections.singleton(Disposes.class); private static final String DISPOSER_ANNOTATION = "@Disposes"; private final BeanManagerImpl beanManager; private final AbstractClassBean<X> declaringBean; private final MethodInjectionPoint<T, ? super X> disposalMethodInjectionPoint; private final AnnotatedParameter<? super X> disposesParameter; private final Set<QualifierInstance> requiredQualifiers; private final MethodInvocationStrategy invocationStrategy; public static <X, T> DisposalMethod<X, T> of(BeanManagerImpl manager, EnhancedAnnotatedMethod<T, ? super X> method, AbstractClassBean<X> declaringBean) { return new DisposalMethod<X, T>(manager, method, declaringBean); } protected DisposalMethod(BeanManagerImpl beanManager, EnhancedAnnotatedMethod<T, ? super X> enhancedAnnotatedMethod, AbstractClassBean<X> declaringBean) { this.disposalMethodInjectionPoint = InjectionPointFactory.instance().createMethodInjectionPoint(MethodInjectionPointType.DISPOSER, enhancedAnnotatedMethod, declaringBean, declaringBean.getBeanClass(), SPECIAL_PARAM_MARKERS, beanManager); this.beanManager = beanManager; this.declaringBean = declaringBean; EnhancedAnnotatedParameter<?, ? super X> enhancedDisposesParameter = getEnhancedDisposesParameter(enhancedAnnotatedMethod); this.disposesParameter = enhancedDisposesParameter.slim(); this.requiredQualifiers = getRequiredQualifiers(enhancedDisposesParameter); checkDisposalMethod(enhancedAnnotatedMethod, declaringBean); this.invocationStrategy = MethodInvocationStrategy.forDisposer(disposalMethodInjectionPoint, beanManager); } private EnhancedAnnotatedParameter<?, ? super X> getEnhancedDisposesParameter(EnhancedAnnotatedMethod<T, ? super X> enhancedAnnotatedMethod) { return enhancedAnnotatedMethod.getEnhancedParameters(Disposes.class).get(0); } public AnnotatedParameter<? super X> getDisposesParameter() { return disposesParameter; } public AnnotatedMethod<? super X> getAnnotated() { return disposalMethodInjectionPoint.getAnnotated(); } public void invokeDisposeMethod(Object receiver, Object instance, CreationalContext<?> creationalContext) { invocationStrategy.invoke(receiver, disposalMethodInjectionPoint, instance, beanManager, creationalContext); } private void checkDisposalMethod(EnhancedAnnotatedMethod<T, ? super X> enhancedAnnotatedMethod, AbstractClassBean<X> declaringBean) { if (enhancedAnnotatedMethod.getEnhancedParameters(Disposes.class).size() > 1) { throw BeanLogger.LOG .multipleDisposeParams(disposalMethodInjectionPoint, Formats.formatAsStackTraceElement(enhancedAnnotatedMethod.getJavaMember())); } if (enhancedAnnotatedMethod.getEnhancedParameters(Observes.class).size() > 0) { throw BeanLogger.LOG.inconsistentAnnotationsOnMethod("@Observes", DISPOSER_ANNOTATION, disposalMethodInjectionPoint, Formats.formatAsStackTraceElement(enhancedAnnotatedMethod.getJavaMember())); } if (enhancedAnnotatedMethod.getAnnotation(Inject.class) != null) { throw BeanLogger.LOG.inconsistentAnnotationsOnMethod("@Inject", DISPOSER_ANNOTATION, disposalMethodInjectionPoint, Formats.formatAsStackTraceElement(enhancedAnnotatedMethod.getJavaMember())); } if (enhancedAnnotatedMethod.getAnnotation(Produces.class) != null) { throw BeanLogger.LOG.inconsistentAnnotationsOnMethod("@Produces", DISPOSER_ANNOTATION, disposalMethodInjectionPoint, Formats.formatAsStackTraceElement(enhancedAnnotatedMethod.getJavaMember())); } if (enhancedAnnotatedMethod.getAnnotation(Specializes.class) != null) { throw BeanLogger.LOG.inconsistentAnnotationsOnMethod("@Specialized", DISPOSER_ANNOTATION, disposalMethodInjectionPoint, Formats.formatAsStackTraceElement(enhancedAnnotatedMethod.getJavaMember())); } if (declaringBean instanceof SessionBean<?>) { SessionBean<?> sessionBean = (SessionBean<?>) declaringBean; Set<MethodSignature> localBusinessMethodSignatures = sessionBean.getLocalBusinessMethodSignatures(); Set<MethodSignature> remoteBusinessMethodSignatures = sessionBean.getRemoteBusinessMethodSignatures(); if (!localBusinessMethodSignatures.contains(enhancedAnnotatedMethod.getSignature()) || remoteBusinessMethodSignatures .contains(enhancedAnnotatedMethod.getSignature())) { throw BeanLogger.LOG.methodNotBusinessMethod("Disposer", enhancedAnnotatedMethod, declaringBean, Formats.formatAsStackTraceElement(enhancedAnnotatedMethod.getJavaMember())); } } for (ParameterInjectionPoint<?, ?> ip : disposalMethodInjectionPoint.getParameterInjectionPoints()) { Class<?> rawType = Reflections.getRawType(ip.getType()); if (Bean.class.equals(rawType) || Interceptor.class.equals(rawType) || Decorator.class.equals(rawType)) { Validator.checkBeanMetadataInjectionPoint(this, ip, getDisposesParameter().getBaseType()); } } } public Type getGenericType() { return getDisposesParameter().getBaseType(); } public Set<QualifierInstance> getRequiredQualifiers() { return requiredQualifiers; } public AbstractClassBean<X> getDeclaringBean() { return declaringBean; } @Override public String toString() { return "Disposer method [" + getDisposesParameter().getDeclaringCallable() + "]"; } public Set<InjectionPoint> getInjectionPoints() { return disposalMethodInjectionPoint.getInjectionPoints(); } /** * A disposer method is bound to a producer if the producer is assignable to the disposed parameter. * * @param enhancedDisposedParameter * @return the set of required qualifiers for the given disposed parameter */ private Set<QualifierInstance> getRequiredQualifiers(EnhancedAnnotatedParameter<?, ? super X> enhancedDisposedParameter) { Set<Annotation> disposedParameterQualifiers = enhancedDisposedParameter.getMetaAnnotations(Qualifier.class); if (disposedParameterQualifiers.isEmpty()) { disposedParameterQualifiers = Collections.<Annotation> singleton(Default.Literal.INSTANCE); } return beanManager.getServices().get(MetaAnnotationStore.class).getQualifierInstances(disposedParameterQualifiers); } }