/*
* JBoss, Home of Professional Open Source
* Copyright 2007, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.deployment;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jboss.deployers.vfs.spi.structure.VFSDeploymentUnit;
import org.jboss.metadata.annotation.creator.AbstractCreator;
import org.jboss.metadata.annotation.creator.AnnotationContext;
import org.jboss.metadata.annotation.creator.client.ApplicationClient5MetaDataCreator;
import org.jboss.metadata.annotation.creator.ejb.jboss.JBoss50Creator;
import org.jboss.metadata.annotation.finder.AnnotationFinder;
import org.jboss.metadata.annotation.finder.DefaultAnnotationFinder;
import org.jboss.metadata.client.spec.ApplicationClientMetaData;
import org.jboss.metadata.ejb.jboss.JBossMetaData;
import org.jboss.metadata.ejb.spec.EjbJarMetaData;
import org.jboss.metadata.web.spec.WebMetaData;
import org.jboss.scanning.annotations.spi.AnnotationIndex;
import org.jboss.scanning.annotations.spi.AnnotationRepository;
import org.jboss.scanning.annotations.spi.Element;
import org.jboss.vfs.VirtualFile;
/**
* A POST_CLASSLOADER deployer which generates metadata from annotations.
* Optimized option to its super class.
*
* @author Ales.Justin@jboss.org
*/
public class OptAnnotationMetaDataDeployer extends AnnotationMetaDataDeployer
{
public OptAnnotationMetaDataDeployer()
{
super();
setInput(AnnotationIndex.class);
}
protected void processMetaData(VFSDeploymentUnit unit, WebMetaData webMetaData, ApplicationClientMetaData clientMetaData, List<VirtualFile> classpath) throws Exception
{
AnnotationFinder<AnnotatedElement> finder = new DefaultAnnotationFinder<AnnotatedElement>();
// don't do webMetaData anymore (rev 96033)
String mainClassName = getMainClassName(unit);
if (mainClassName != null && mainClassName.length() > 0)
processJBossClientMetaData(unit, finder, mainClassName);
else
processJBossMetaData(unit, finder);
}
/**
* Process jboss app client meta data.
*
* @param unit the deployment unit
* @param finder the finder
* @param mainClassName the main class name
* @throws ClassNotFoundException for any error
*/
protected void processJBossClientMetaData(VFSDeploymentUnit unit, AnnotationFinder<AnnotatedElement> finder, String mainClassName) throws ClassNotFoundException
{
ApplicationClient5MetaDataCreator creator = new ApplicationClient5MetaDataCreator(finder, mainClassName);
Collection<Class<?>> classes = new ArrayList<Class<?>>(1);
Class<?> mainClass = unit.getClassLoader().loadClass(mainClassName);
classes.add(mainClass);
ApplicationClientMetaData annotationMetaData = creator.create(classes);
if(annotationMetaData != null)
unit.addAttachment(CLIENT_ANNOTATED_ATTACHMENT_NAME, annotationMetaData, ApplicationClientMetaData.class);
}
/**
* Process jboss meta data.
*
* @param unit the deployment unit
* @param finder the finder
*/
protected void processJBossMetaData(VFSDeploymentUnit unit, AnnotationFinder<AnnotatedElement> finder)
{
// Create the metadata model from the annotations
EjbJarMetaData ejbJarMetaData = unit.getAttachment(EjbJarMetaData.class);
JBoss50Creator creator = new JBoss50Creator(ejbJarMetaData, unit.getClassLoader(), finder);
Collection<Class<?>> classes = getClasses(unit, creator);
JBossMetaData annotationMetaData = creator.create(classes);
if(annotationMetaData != null)
unit.addAttachment(EJB_ANNOTATED_ATTACHMENT_NAME, annotationMetaData, JBossMetaData.class);
}
/**
* Get the classes for creator to process.
*
* @param unit the deployment unit
* @param creator the creator
* @return classes to process
*/
@SuppressWarnings("unchecked")
protected Collection<Class<?>> getClasses(VFSDeploymentUnit unit, AbstractCreator creator)
{
boolean trace = log.isTraceEnabled();
AnnotationRepository env = unit.getAttachment(AnnotationIndex.class);
if (env == null)
{
if (trace)
log.trace("Cannot scan classes, missing AnnotationRepository as attachment: " + unit.getName());
return Collections.emptySet();
}
String creatorInfo = creator.toString();
AnnotationContext context = creator.getAnnotationContext();
Set<Class<?>> classes = new HashSet<Class<?>>();
Collection<Class<? extends Annotation>> typeAnnotations = context.getTypeAnnotations();
if (trace)
log.trace("Creator: " + creatorInfo + ", type annotations: " + typeAnnotations);
for(Class<? extends Annotation> annotation : typeAnnotations)
{
Class<Annotation> annotationClass = (Class<Annotation>)annotation;
Set<Element<Annotation, Class<?>>> elements = env.classIsAnnotatedWith(annotationClass);
for(Element<Annotation, Class<?>> elt : elements)
classes.add(elt.getOwner());
}
Collection<Class<? extends Annotation>> methodAnnotations = context.getMethodAnnotations();
if (trace)
log.trace("Creator: " + creatorInfo + ", method annotations: " + methodAnnotations);
for(Class<? extends Annotation> annotation : methodAnnotations)
{
Class<Annotation> annotationClass = (Class<Annotation>)annotation;
Set<Element<Annotation, Method>> elements = env.classHasMethodAnnotatedWith(annotationClass);
for(Element<Annotation, Method> elt : elements)
classes.add(elt.getOwner());
}
Collection<Class<? extends Annotation>> fieldAnnotations = context.getFieldAnnotations();
if (trace)
log.trace("Creator: " + creatorInfo + ", field annotations: " + fieldAnnotations);
for(Class<? extends Annotation> annotation : fieldAnnotations)
{
Class<Annotation> annotationClass = (Class<Annotation>)annotation;
Set<Element<Annotation, Field>> elements = env.classHasFieldAnnotatedWith(annotationClass);
for(Element<Annotation, Field> elt : elements)
classes.add(elt.getOwner());
}
if (trace)
log.trace("Annotated classes [" + unit.getName() + ", " + creatorInfo + "]: " + classes);
return classes;
}
}