/*
* JBoss, Home of Professional Open Source
* Copyright 2010, 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.seam.solder.core;
import java.util.ArrayList;
import java.util.Collection;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AnnotatedConstructor;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
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.inject.Named;
import org.jboss.seam.solder.literal.NamedLiteral;
import org.jboss.seam.solder.reflection.Reflections;
import org.jboss.seam.solder.reflection.annotated.AnnotatedTypeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Extension to install the "core" extensions. Core extensions are those that
* add additional abilities to CDI applications via annotations.
*
* @author Stuart
* @author Pete Muir
* @author Gavin King
*
*/
public class CoreExtension implements Extension
{
private final Collection<Bean<?>> additionalBeans;
static final Logger log = LoggerFactory.getLogger(CoreExtension.class);
CoreExtension()
{
this.additionalBeans = new ArrayList<Bean<?>>();
}
<X> void processAnnotatedType(@Observes final ProcessAnnotatedType<X> pat, BeanManager beanManager)
{
// Support for @Veto
if (pat.getAnnotatedType().isAnnotationPresent(Veto.class))
{
pat.veto();
log.info("Preventing " + pat.getAnnotatedType().getJavaClass() + " from being installed as bean due to @Veto annotation");
return;
}
// support for @Requires
if (pat.getAnnotatedType().isAnnotationPresent(Requires.class))
{
String[] classes = pat.getAnnotatedType().getAnnotation(Requires.class).value();
for (String i : classes)
{
try
{
Reflections.classForName(i, pat.getAnnotatedType().getJavaClass().getClassLoader());
}
catch (ClassNotFoundException e)
{
log.info("Preventing " + pat.getAnnotatedType().getJavaClass() + " from being installed as required class " + i + " could not be found");
pat.veto();
}
catch (LinkageError e)
{
// LinkageError is a superclass of NoClassDefFoundError
log.info("Preventing " + pat.getAnnotatedType().getJavaClass() + " from being installed as a linkage error occurred loading required class " + i + ". The linkage error was " + e.toString());
pat.veto();
}
}
}
AnnotatedTypeBuilder<X> builder = null;
// support for @Named packages
Package pkg = pat.getAnnotatedType().getJavaClass().getPackage();
if (pkg.isAnnotationPresent(Named.class) && !pat.getAnnotatedType().isAnnotationPresent(Named.class))
{
if (builder == null)
{
builder = new AnnotatedTypeBuilder<X>().readFromType(pat.getAnnotatedType());
}
builder.addToClass(new NamedLiteral(""));
}
// support for @Exact
// fields
for (AnnotatedField<? super X> f : pat.getAnnotatedType().getFields())
{
if (f.isAnnotationPresent(Exact.class))
{
Class<?> type = f.getAnnotation(Exact.class).value();
if (builder == null)
{
builder = new AnnotatedTypeBuilder<X>().readFromType(pat.getAnnotatedType());
}
builder.overrideFieldType(f, type);
}
}
// method parameters
for (AnnotatedMethod<? super X> m : pat.getAnnotatedType().getMethods())
{
for (AnnotatedParameter<? super X> p : m.getParameters())
{
if (p.isAnnotationPresent(Exact.class))
{
Class<?> type = p.getAnnotation(Exact.class).value();
if (builder == null)
{
builder = new AnnotatedTypeBuilder<X>().readFromType(pat.getAnnotatedType());
}
builder.overrideParameterType(p, type);
}
}
}
// constructor parameters
for (AnnotatedConstructor<X> c : pat.getAnnotatedType().getConstructors())
{
for (AnnotatedParameter<? super X> p : c.getParameters())
{
if (p.isAnnotationPresent(Exact.class))
{
Class<?> type = p.getAnnotation(Exact.class).value();
if (builder == null)
{
builder = new AnnotatedTypeBuilder<X>().readFromType(pat.getAnnotatedType());
}
builder.overrideParameterType(p, type);
}
}
}
if (builder != null)
{
pat.setAnnotatedType(builder.create());
}
}
void afterBeanDiscovery(@Observes AfterBeanDiscovery abd)
{
for (Bean<?> bean : additionalBeans)
{
abd.addBean(bean);
}
}
}