FileDocCategorySizeDatePackage
AnnotationProcessorImpl.javaAPI DocGlassfish v2 API20161Fri May 04 22:30:22 BST 2007com.sun.enterprise.deployment.annotation.impl

AnnotationProcessorImpl

public class AnnotationProcessorImpl extends Object implements com.sun.enterprise.deployment.annotation.AnnotationProcessor
author
dochez

Fields Summary
AnnotationProcessorImpl
delegate
Map
handlers
int
errorCount
Logger
logger
Stack
annotatedElements
Set
visitedPackages
Constructors Summary
public AnnotationProcessorImpl()
Creates a new instance of AnnotationProcessorImpl

    
           
      
        logger = AnnotationUtils.getLogger();
    
Methods Summary
public com.sun.enterprise.deployment.annotation.ProcessingContextcreateContext()

        ProcessingContext ctx = new ProcessingContextImpl(this);
        ctx.setErrorHandler(new DefaultErrorHandler());
        return ctx;
    
private voiddumpProcessingResult(com.sun.enterprise.deployment.annotation.HandlerProcessingResult result)


        if (result==null || !AnnotationUtils.shouldLog("annotation")) {
            return;
        }
   
        Map<Class<? extends Annotation>, ResultType> annotationResults = 
                result.processedAnnotations();
        for (Class annotationType : annotationResults.keySet()) {            
            logger.finer("Annotation " + annotationType + " : " +
                    annotationResults.get(annotationType));
        }
    
public com.sun.enterprise.deployment.annotation.AnnotationHandlergetAnnotationHandler(java.lang.Class type)

        List<AnnotationHandler> currentHandlers = handlers.get(type);
        if (currentHandlers!=null && currentHandlers.size()>0) {
            return currentHandlers.get(0);
        }        
        return null;
    
public java.lang.reflect.AnnotatedElementgetLastAnnotatedElement(java.lang.annotation.ElementType type)

return
the last element pushed on the stack which ElementType was the one passed or null if no stack element is of the given type.

        for (int i=annotatedElements.size();i!=0;i--) {
            StackElement e = annotatedElements.get(i - 1);
            if (e.getElementType().equals(type)) 
                return e.getAnnotatedElement();
        }
        return null;
    
public java.util.StackgetStack()

        return annotatedElements;
    
private java.lang.annotation.ElementTypegetTopElementType()

return
the top annotated elements stack element type

        try {
            StackElement top = annotatedElements.peek();
            return top.getElementType();
        } catch(EmptyStackException ex) {
            return null;
        }
    
public voidlog(java.util.logging.Level level, com.sun.enterprise.deployment.annotation.AnnotationInfo locator, java.lang.String localizedMessage)
Log a message on the default logger

        if (logger!=null && logger.isLoggable(level)){
            if (locator!=null){
                logger.log(level, AnnotationUtils.getLocalString(
                    "enterprise.deployment.annotation.error",
                    "{2}\n symbol: {0}\n location: {1}",
                    new Object[] { locator.getAnnotation().annotationType().getName(), locator.getAnnotatedElement(), localizedMessage}));
            } else{
                logger.log(level, localizedMessage);
            }
        }
    
private voidlogEnd(com.sun.enterprise.deployment.annotation.AnnotatedElementHandler handler, java.lang.annotation.ElementType type, java.lang.reflect.AnnotatedElement c)

        
        if (AnnotationUtils.shouldLog("types")) {
            AnnotationUtils.getLogger().finer(type + " END : " + c);
        }
        
        // pop it from our annotated element stack
        annotatedElements.pop();
        if(delegate!=null) {
            delegate.getStack().pop();
        }
        
        if (handler!=null) {
            handler.endElement(type, c);
        }   
    
private voidlogStart(com.sun.enterprise.deployment.annotation.AnnotatedElementHandler handler, java.lang.annotation.ElementType type, java.lang.reflect.AnnotatedElement c)

        
        if (AnnotationUtils.shouldLog("types")) {
            AnnotationUtils.getLogger().finer(type + " START : " + c);
        }
        
        // push it to our annotated element stack
        annotatedElements.push(new StackElement(type, c));
        if(delegate!=null) {
            delegate.getStack().push(new StackElement(type, c));
        }
        
        if (handler!=null) {
            handler.startElement(type, c);
        }   
    
public voidpopAnnotationHandler(java.lang.Class type)

        List<AnnotationHandler> currentHandlers = handlers.get(type);
        if (currentHandlers!=null) {
            currentHandlers.remove(currentHandlers.size());
        }        
    
private voidprocess(com.sun.enterprise.deployment.annotation.ProcessingContext ctx, com.sun.enterprise.deployment.annotation.AnnotationInfo element, HandlerProcessingResultImpl result)

        
        
        Annotation annotation = element.getAnnotation();
        if (AnnotationUtils.shouldLog("annotation")) {
            logger.finer("Annotation : " + annotation.annotationType().getName() + " delegate = " + delegate);
        }
        result.addResult(annotation.annotationType(), ResultType.UNPROCESSED);
        
        // we ignore all java.* annotations
        Package annPackage = annotation.annotationType().getPackage();
        if (annPackage != null && annPackage.getName().startsWith("java.lang"))
            return;
        
        List<AnnotationHandler> annotationHandlers = handlers.get(annotation.annotationType());
        if (annotationHandlers!=null) {
            for (AnnotationHandler handler : annotationHandlers) {
                
                // here we need to be careful, we are ready to invoke a handler
                // to process a particular annotation type. However, this handler 
                // may have defined a list of annotations that should be processed 
                // (if present on the annotated element) before itself. 
                // do this check and process those annotations first.
                Class<? extends Annotation>[] dependencies = handler.getTypeDependencies();
                if (dependencies!=null) {
                    AnnotatedElement ae = element.getAnnotatedElement();
                    for (Class<? extends Annotation> annotationType : dependencies) {
                        Annotation depAnnotation = ae.getAnnotation(annotationType);
                        if (depAnnotation!=null) {                        
                            ResultType resultType = result.processedAnnotations().get(annotationType);
                            if (resultType==null || resultType==ResultType.UNPROCESSED){
                                // annotation is present, process it.
                                AnnotationInfo info = new AnnotationInfo(ctx, ae, depAnnotation, getTopElementType());
                                process(ctx, info, result);
                            }
                        }
                    }
                }
                
                // at this point, all annotation that I declared depending on
                // are processed
                HandlerProcessingResult processingResult = null;
                try {
                    processingResult = handler.processAnnotation(element);
                } catch(AnnotationProcessorException ape) {
                    // I am logging this exception
                    log(Level.SEVERE, ape.getLocator(), ape.getMessage());
                    
                    // I am not throwing the exception unless it is fatal so annotation
                    // processing can continue and we have a chance to report all 
                    // errors. 
                    if (ape.isFatal()) {
                        throw ape;
                    } 
                    
                    if (++errorCount>100){
                        throw new AnnotationProcessorException(
                                AnnotationUtils.getLocalString(
                                    "enterprise.deployment.annotation.toomanyerror",
                                    "Too many errors, annotation processing abandoned."));
                    }
                    
                    processingResult =
                        HandlerProcessingResultImpl.getDefaultResult(
                        annotation.annotationType(), ResultType.FAILED);
                } catch(Throwable e){
                    AnnotationProcessorException ape = new AnnotationProcessorException(e.getMessage(), element);
                    ape.initCause(e);
                    throw ape;
                }
                result.addAll(processingResult);
            }
        } else {
            if (delegate!=null) {
                delegate.process(ctx, element, result);
            } else {           
                ctx.getErrorHandler().fine(
                        new AnnotationProcessorException("No handler defined for " 
                            + annotation.annotationType()));
            }
        }
    
public com.sun.enterprise.deployment.annotation.ProcessingResultprocess(com.sun.enterprise.deployment.annotation.ProcessingContext ctx)
Starts the annotation processing tool passing the processing context which encapuslate all information necessary for the configuration of the tool.

param
ctx is the initialized processing context
return
the result of the annoations processing

        
        Scanner scanner = ctx.getProcessingInput();
        ProcessingResultImpl result = new ProcessingResultImpl();
        errorCount=0;
        
        for (Class c : scanner.getElements()) {
            
            result.add(process(ctx, c));          
        }
        return result;
    
public com.sun.enterprise.deployment.annotation.ProcessingResultprocess(com.sun.enterprise.deployment.annotation.ProcessingContext ctx, java.lang.Class[] classes)
Process a set of classes from the parameter list rather than from the processing context. This allow the annotation handlers to call be the annotation processing tool when classes need to be processed in a particular context rather than when they are picked up by the scanner.

param
the processing context
param
the list of classes to process
return
the processing result for such classes
throws
AnnotationProcessorException if handlers fail to process an annotation

        
        ProcessingResultImpl result = new ProcessingResultImpl();
        for (Class c : classes) {
            result.add(process(ctx, c));
        }
        return result;
    
private com.sun.enterprise.deployment.annotation.ProcessingResultprocess(com.sun.enterprise.deployment.annotation.ProcessingContext ctx, java.lang.Class c)

        
        Scanner scanner = ctx.getProcessingInput();
        ProcessingResultImpl result = new ProcessingResultImpl();
        
        // let's see first if this package is new to us and annotated.
        Package classPackage = c.getPackage();
        if (classPackage != null && visitedPackages.add(classPackage)) {
            // new package
            result.add(classPackage, 
                    processAnnotations(ctx, ElementType.PACKAGE, classPackage));
        }

        ComponentInfo info = null;
        try {
            info = scanner.getComponentInfo(c);
        } catch (NoClassDefFoundError err) {
            // issue 456: allow verifier to report this issue
            AnnotationProcessorException ape = 
                    new AnnotationProcessorException(
                            AnnotationUtils.getLocalString(
                                    "enterprise.deployment.annotation.classnotfounderror",
                                    "Class [ {0} ] not found. Error while loading [ {1} ]",
                                    new Object[]{err.getMessage(), c}));
            ctx.getErrorHandler().error(ape);
            throw err;
        }

        // process the class itself.
        AnnotatedElementHandler handler= ctx.getHandler();
        logStart(handler, ElementType.TYPE,c);
        result.add(c, processAnnotations(ctx, c));
        
        // now dive into the fields.
        for (Field field : info.getFields()) {
            result.add(field,processAnnotations(ctx, ElementType.FIELD, field));
        }
        
        // constructors...
        for (Constructor constructor : info.getConstructors()) {
            logStart(ctx.getHandler(), ElementType.CONSTRUCTOR, constructor);
            result.add(constructor, processAnnotations(ctx, constructor));
            
            // parameters
            processParameters(ctx, constructor.getParameterAnnotations());
            
            logEnd(ctx.getHandler(), ElementType.CONSTRUCTOR, constructor);
            
        }
        
        // methods...
        for (Method method : info.getMethods()) {
            logStart(ctx.getHandler(), ElementType.METHOD, method);
            result.add(method, processAnnotations(ctx, method));
            
            // parameters
            processParameters(ctx, method.getParameterAnnotations());
            
            logEnd(ctx.getHandler(), ElementType.METHOD, method);
        }
        
        // Because of annotation inheritance, we need to to travel to
        // the superclasses to ensure that annotations defined at the
        // TYPE level are processed at this component level.
        // Note : so far, I am ignoring the implemented interfaces
        Class currentClass = c.getSuperclass();
        while (currentClass!=null && !currentClass.equals(Object.class)) {
            // the trick is to add the results for this class, not
            // for the ones they are defined in...
            result.add(c, processAnnotations(ctx, currentClass));
            currentClass = currentClass.getSuperclass();
        }
        
        // end of class processing, we need to get the top handler
        // since it may have changed during the annotation processing
        logEnd(ctx.getHandler(), ElementType.TYPE, c);  
        
        return result;
    
private com.sun.enterprise.deployment.annotation.HandlerProcessingResultprocessAnnotations(com.sun.enterprise.deployment.annotation.ProcessingContext ctx, java.lang.reflect.AnnotatedElement element)

    
        HandlerProcessingResultImpl result= new HandlerProcessingResultImpl();
        
        for (Annotation annotation : element.getAnnotations()) {
            // initialize the result...
            AnnotationInfo subElement = new AnnotationInfo(ctx, element, annotation, getTopElementType());
            if (!result.processedAnnotations().containsKey(annotation.annotationType())) {
                process(ctx, subElement, result);
            } else {
                if (AnnotationUtils.shouldLog("annotation")) { 
                    logger.finer("Annotation " + annotation.annotationType() + " already processed");
                }
            }       
        }
        return result;
    
private com.sun.enterprise.deployment.annotation.HandlerProcessingResultprocessAnnotations(com.sun.enterprise.deployment.annotation.ProcessingContext ctx, java.lang.annotation.ElementType type, java.lang.reflect.AnnotatedElement element)

        
        AnnotatedElementHandler handler = ctx.getHandler();
        logStart(handler, type, element);
        HandlerProcessingResult result = processAnnotations(ctx, element);
        logEnd(handler, type, element);

        dumpProcessingResult(result);                    
        
        return result;
    
private com.sun.enterprise.deployment.annotation.HandlerProcessingResultprocessParameters(com.sun.enterprise.deployment.annotation.ProcessingContext ctx, java.lang.annotation.Annotation[][] parametersAnnotations)


        HandlerProcessingResultImpl result = new HandlerProcessingResultImpl();
        
        // process the method parameters...
        for (Annotation[] parameterAnnotations : parametersAnnotations) {
            logStart(ctx.getHandler(), ElementType.PARAMETER, null);
            if (parameterAnnotations!=null) {
                for (Annotation annotation : parameterAnnotations) {
                    AnnotationInfo info = new AnnotationInfo(ctx, null, annotation, ElementType.PARAMETER);
                    process(ctx, info, result);
                    dumpProcessingResult(result);
                }
            }
            logEnd(ctx.getHandler(), ElementType.PARAMETER, null);
        }
        return result;        
    
public voidpushAnnotationHandler(com.sun.enterprise.deployment.annotation.AnnotationHandler handler)

        
        Class<? extends Annotation> type = handler.getAnnotationType();
        List<AnnotationHandler> currentHandlers = handlers.get(type);
        if (currentHandlers==null) {
            currentHandlers = new ArrayList<AnnotationHandler>();
            handlers.put(type, currentHandlers);
        }
        currentHandlers.add(handler);
    
public voidsetDelegate(com.sun.enterprise.deployment.annotation.impl.AnnotationProcessorImpl delegate)

        this.delegate = delegate;