/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and/or its affiliates, 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.solder.servlet.logging;
import java.util.Collection;
import java.util.HashSet;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
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.ProcessAnnotatedType;
import javax.enterprise.inject.spi.ProcessProducerMethod;
import org.jboss.solder.bean.NarrowingBeanBuilder;
import org.jboss.solder.literal.MessageBundleLiteral;
import org.jboss.solder.logging.MessageLogger;
import org.jboss.solder.messages.MessageBundle;
/**
* Adds TypedMessageBundleAndLoggerProducers to the deployment, and detects and installs beans for any typed loggers defined.
* <p/>
* <strong>TEMPORARY UNTIL GLASSFISH-15735 is resolved</strong>
*
* @author Pete Muir
*/
public class TypedMessageBundleAndLoggerExtension implements Extension {
private final Collection<AnnotatedType<?>> messageLoggerTypes;
private final Collection<AnnotatedType<?>> messageBundleTypes;
private Bean<Object> loggerProducerBean;
private Bean<Object> bundleProducerBean;
private boolean processTypesInModule = false;
private static final String MODULE_PACKAGE_PREFIX = "org.jboss.solder.servlet.";
public TypedMessageBundleAndLoggerExtension() {
this.messageLoggerTypes = new HashSet<AnnotatedType<?>>();
this.messageBundleTypes = new HashSet<AnnotatedType<?>>();
Package cdi = BeanManager.class.getPackage();
processTypesInModule = System.getProperty("glassfish.version") != null && cdi.getImplementationTitle().contains("Weld")
&& cdi.getImplementationVersion().equals("20110114-1644");
}
void detectInterfaces(@Observes ProcessAnnotatedType<?> event, BeanManager beanManager) {
if (processTypesInModule) {
AnnotatedType<?> type = event.getAnnotatedType();
if (type.getJavaClass().getPackage().getName().startsWith(MODULE_PACKAGE_PREFIX)) {
if (type.isAnnotationPresent(MessageLogger.class)) {
messageLoggerTypes.add(type);
}
if (type.isAnnotationPresent(MessageBundle.class)) {
messageBundleTypes.add(type);
}
}
}
}
// according to the Java EE 6 javadoc (the authority according to the powers that be),
// this is the correct order of type parameters
void detectProducers(@Observes ProcessProducerMethod<Object, TypedMessageBundleAndLoggerProducers> event) {
captureProducers(event.getAnnotatedProducerMethod(), event.getBean());
}
// according to JSR-299 spec, this is the correct order of type parameters
@Deprecated
void detectProducersInverted(@Observes ProcessProducerMethod<TypedMessageBundleAndLoggerProducers, Object> event) {
captureProducers(event.getAnnotatedProducerMethod(), event.getBean());
}
@SuppressWarnings("unchecked")
void captureProducers(AnnotatedMethod<?> method, Bean<?> bean) {
if (processTypesInModule) {
if (method.isAnnotationPresent(TypedMessageLogger.class)) {
this.loggerProducerBean = (Bean<Object>) bean;
}
if (method.isAnnotationPresent(TypedMessageBundle.class)) {
this.bundleProducerBean = (Bean<Object>) bean;
}
}
}
void installBeans(@Observes AfterBeanDiscovery event, BeanManager beanManager) {
if (processTypesInModule) {
for (AnnotatedType<?> type : messageLoggerTypes) {
event.addBean(createMessageLoggerBean(loggerProducerBean, type, beanManager));
}
for (AnnotatedType<?> type : messageBundleTypes) {
event.addBean(createMessageBundleBean(bundleProducerBean, type, beanManager));
}
}
}
private static <T> Bean<T> createMessageLoggerBean(Bean<Object> delegate, AnnotatedType<T> type, BeanManager beanManager) {
return new NarrowingBeanBuilder<T>(delegate, beanManager).readFromType(type).types(type.getBaseType(), Object.class)
.create();
}
private static <T> Bean<T> createMessageBundleBean(Bean<Object> delegate, AnnotatedType<T> type, BeanManager beanManager) {
return new NarrowingBeanBuilder<T>(delegate, beanManager).readFromType(type).types(type.getBaseType(), Object.class)
.addQualifier(MessageBundleLiteral.INSTANCE).create();
}
void cleanup(@Observes AfterDeploymentValidation event) {
// defensively clear the set to help with gc
this.messageLoggerTypes.clear();
this.messageBundleTypes.clear();
}
}