/* * Copyright open knowledge GmbH * * 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 de.openknowledge.cdi.scope; import java.lang.annotation.Annotation; import java.util.HashMap; import java.util.Map; import javax.enterprise.context.spi.Context; import javax.enterprise.event.Observes; import javax.enterprise.inject.spi.AfterBeanDiscovery; import javax.enterprise.inject.spi.Annotated; import javax.enterprise.inject.spi.AnnotatedField; import javax.enterprise.inject.spi.AnnotatedMethod; import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.ProcessBean; import de.openknowledge.cdi.common.qualifier.Corresponding; import de.openknowledge.cdi.common.spi.CorrespondingLiteral; import de.openknowledge.cdi.common.spi.SingletonBean; /** * The DestroyableContextExtension. Scans for {@link Begin} and {@link End} annotations and creates the * {@link DefaultDestroyableContext} for every annotated class. * * @author Arne Limburg - open knowledge GmbH (arne.limburg@openknowledge.de) */ public class DestroyableContextExtension implements Extension { private Map<Class<? extends Annotation>, Bean<?>> destroyableBeans = new HashMap<Class<? extends Annotation>, Bean<?>>(); public void registerBean(@Observes ProcessBean<?> beanEvent, BeanManager beanManager) { End end = getAnnotation(End.class, beanEvent.getAnnotated(), beanManager); if (end != null) { for (Class<? extends Annotation> scope : end.value()) { this.destroyableBeans.put(scope, beanEvent.getBean()); } } Begin begin = getAnnotation(Begin.class, beanEvent.getAnnotated(), beanManager); if (begin != null) { for (Class<? extends Annotation> scope : begin.value()) { this.destroyableBeans.put(scope, beanEvent.getBean()); } } } public void registerContexts(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) { for (Map.Entry<Class<? extends Annotation>, Bean<?>> entry : this.destroyableBeans.entrySet()) { Context context = new DefaultDestroyableContext(entry.getValue(), entry.getKey(), beanManager); afterBeanDiscovery.addContext(context); Corresponding corresponding = new CorrespondingLiteral(entry.getKey()); Bean<?> contextBean = new SingletonBean(entry.getKey().getName(), context, beanManager, corresponding); afterBeanDiscovery.addBean(contextBean); } } private <A extends Annotation> A getAnnotation(Class<A> annotationType, Annotated annotated, BeanManager beanManager) { A annotation = annotated.getAnnotation(annotationType); if (annotation != null) { return annotation; } else if (annotated instanceof AnnotatedType) { AnnotatedType<?> annotatedType = (AnnotatedType<?>) annotated; for (AnnotatedMethod<?> method : annotatedType.getMethods()) { annotation = method.getAnnotation(annotationType); if (annotation != null) { return annotation; } } return null; } else if (annotated instanceof AnnotatedField) { AnnotatedField<?> field = (AnnotatedField<?>) annotated; Annotated fieldType = beanManager.createAnnotatedType(field.getJavaMember().getType()); return getAnnotation(annotationType, fieldType, beanManager); } else if (annotated instanceof AnnotatedMethod) { AnnotatedMethod<?> method = (AnnotatedMethod<?>) annotated; Annotated returnType = beanManager.createAnnotatedType(method.getJavaMember().getReturnType()); return getAnnotation(annotationType, returnType, beanManager); } else { return null; } } }