All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.annotations.AnnotationParser Maven / Gradle / Ivy

There is a newer version: 1.0-rc5
Show newest version
// ========================================================================
// Copyright (c) 2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at 
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses. 
// ========================================================================
package org.eclipse.jetty.annotations;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;

import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.JarScanner;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.commons.EmptyVisitor;

/**
 * AnnotationParser
 * 
 * Use asm to scan classes for annotations. A SAX-style parsing is done, with
 * a handler being able to be registered to handle each annotation type.
 */
public class AnnotationParser
{ 
    protected List _parsedClassNames = new ArrayList();
    protected Map> _annotationHandlers = new HashMap>();
    protected List _classHandlers = new ArrayList();
    protected List _methodHandlers = new ArrayList();
    protected List _fieldHandlers = new ArrayList();
    
    public static String normalize (String name)
    {
        if (name==null)
            return null;
        
        if (name.startsWith("L") && name.endsWith(";"))
            name = name.substring(1, name.length()-1);
        
        if (name.endsWith(".class"))
            name = name.substring(0, name.length()-".class".length());
        
        return name.replace('/', '.');
    }
    

    
    public abstract class Value
    {
        String _name;
        
        public Value (String name)
        {
            _name = name;
        }
        
        public String getName()
        {
            return _name;
        }
        
        public abstract Object getValue();
           
    }
    
   
 
    
    public class SimpleValue extends Value
    {
        Object _val;
        
        public SimpleValue(String name)
        {
            super(name);
        }
        
        public void setValue(Object val)
        {
            _val=val;
        } 
        public Object getValue()
        {
            return _val;
        } 
        
        public String toString()
        {
            return "("+getName()+":"+_val+")";
        }
    }
    
    public class ListValue extends Value
    {
        List _val;
        
        public ListValue (String name)
        {
            super(name);
            _val = new ArrayList();
        }
      
        public Object getValue()
        {
            return _val;
        }
        
        public List getList()
        {
            return _val;
        }
        
        public void addValue (Value v)
        {
            _val.add(v);
        }
        
        public int size ()
        {
            return _val.size();
        }
        
        public String toString()
        {
            StringBuffer buff = new StringBuffer();
            buff.append("(");
            buff.append(getName());
            buff.append(":");
            for (Value n: _val)
            {
                buff.append(" "+n.toString());
            }
            buff.append(")");
            
            return buff.toString();
        }
    }
    
    
    
    public interface DiscoverableAnnotationHandler
    {
        public void handleClass (String className, int version, int access, 
                                 String signature, String superName, String[] interfaces, 
                                 String annotation, Listvalues);
        
        public void handleMethod (String className, String methodName, int access,  
                                  String desc, String signature,String[] exceptions, 
                                  String annotation, Listvalues);
        
        public void handleField (String className, String fieldName,  int access, 
                                 String fieldType, String signature, Object value, 
                                 String annotation, Listvalues);
    }
    
    
    public interface ClassHandler
    {
        public void handle (String className, int version, int access, String signature, String superName, String[] interfaces);
    }
    
    public interface MethodHandler
    {
        public void handle (String className, String methodName, int access,  String desc, String signature,String[] exceptions);
    }
    
    public interface FieldHandler
    {
        public void handle (String className, String fieldName, int access, String fieldType, String signature, Object value);
    }
    
    public class MyAnnotationVisitor implements AnnotationVisitor
    {
        List _annotationValues;
        String _annotationName;
        
        public MyAnnotationVisitor (String annotationName, List values)
        {
            _annotationValues = values;
            _annotationName = annotationName;
        }
        
        public List getAnnotationValues()
        {
            return _annotationValues;
        }

        /** 
         * Visit a single-valued (name,value) pair for this annotation
         * @see org.objectweb.asm.AnnotationVisitor#visit(java.lang.String, java.lang.Object)
         */
        public void visit(String aname, Object avalue)
        {
           SimpleValue v = new SimpleValue(aname);
           v.setValue(avalue);
           _annotationValues.add(v);
        }

        /** 
         * Visit a (name,value) pair whose value is another Annotation
         * @see org.objectweb.asm.AnnotationVisitor#visitAnnotation(java.lang.String, java.lang.String)
         */
        public AnnotationVisitor visitAnnotation(String name, String desc)
        {
            String s = normalize(desc);
            ListValue v = new ListValue(s);
            _annotationValues.add(v);
            MyAnnotationVisitor visitor = new MyAnnotationVisitor(s, v.getList());
            return visitor; 
        }

        /** 
         * Visit an array valued (name, value) pair for this annotation
         * @see org.objectweb.asm.AnnotationVisitor#visitArray(java.lang.String)
         */
        public AnnotationVisitor visitArray(String name)
        {
            ListValue v = new ListValue(name);
            _annotationValues.add(v);
            MyAnnotationVisitor visitor = new MyAnnotationVisitor(null, v.getList());
            return visitor; 
        }

        /** 
         * Visit a enum-valued (name,value) pair for this annotation
         * @see org.objectweb.asm.AnnotationVisitor#visitEnum(java.lang.String, java.lang.String, java.lang.String)
         */
        public void visitEnum(String name, String desc, String value)
        {
            //TODO
        }
        
        public void visitEnd()
        {   
        }
    }
    
    

    
    /**
     * MyClassVisitor
     *
     * ASM visitor for a class.
     */
    public class MyClassVisitor extends EmptyVisitor
    {
        String _className;
        int _access;
        String _signature;
        String _superName;
        String[] _interfaces;
        int _version;


        public void visit (int version,
                           final int access,
                           final String name,
                           final String signature,
                           final String superName,
                           final String[] interfaces)
        {     
            _className = normalize(name);
            _access = access;
            _signature = signature;
            _superName = superName;
            _interfaces = interfaces;
            _version = version;
            
            _parsedClassNames.add(_className);
            //call all registered ClassHandlers
            String[] normalizedInterfaces = null;
            if (interfaces!= null)
            {
                normalizedInterfaces = new String[interfaces.length];
                int i=0;
                for (String s : interfaces)
                    normalizedInterfaces[i++] = normalize(s);
            }
            
            for (ClassHandler h : AnnotationParser.this._classHandlers)
            {
                h.handle(_className, _version, _access, _signature, normalize(_superName), normalizedInterfaces);
            }
        }

        public AnnotationVisitor visitAnnotation (String desc, boolean visible)
        {                
            MyAnnotationVisitor visitor = new MyAnnotationVisitor(normalize(desc), new ArrayList())
            {
                public void visitEnd()
                {   
                    super.visitEnd();

                    //call all AnnotationHandlers with classname, annotation name + values
                    List handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
                    if (handlers != null)
                    {
                        for (DiscoverableAnnotationHandler h:handlers)
                        {
                            h.handleClass(_className, _version, _access, _signature, _superName, _interfaces, _annotationName, _annotationValues);
                        }
                    }
                }
            };
            
            return visitor;
        }

        public MethodVisitor visitMethod (final int access,
                                          final String name,
                                          final String methodDesc,
                                          final String signature,
                                          final String[] exceptions)
        {   

            return new EmptyVisitor ()
            {
                public AnnotationVisitor visitAnnotation(String desc, boolean visible)
                {
                    MyAnnotationVisitor visitor = new MyAnnotationVisitor (normalize(desc), new ArrayList())
                    {
                        public void visitEnd()
                        {   
                            super.visitEnd();
                            //call all AnnotationHandlers with classname, method, annotation name + values
                            List handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
                            if (handlers != null)
                            {
                                for (DiscoverableAnnotationHandler h:handlers)
                                {
                                    h.handleMethod(_className, name, access, methodDesc, signature, exceptions, _annotationName, _annotationValues);
                                }
                            }
                        }
                    };
                   
                    return visitor;
                }
            };
        }

        public FieldVisitor visitField (final int access,
                                        final String fieldName,
                                        final String fieldType,
                                        final String signature,
                                        final Object value)
        {

            return new EmptyVisitor ()
            {
                public AnnotationVisitor visitAnnotation(String desc, boolean visible)
                {
                    MyAnnotationVisitor visitor = new MyAnnotationVisitor(normalize(desc), new ArrayList())
                    {
                        public void visitEnd()
                        {
                            super.visitEnd();
                            List handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
                            if (handlers != null)
                            {
                                for (DiscoverableAnnotationHandler h:handlers)
                                {
                                    h.handleField(_className, fieldName, access, fieldType, signature, value, _annotationName, _annotationValues);
                                }
                            }
                        }
                    };
                    return visitor;
                }
            };
        }
    }
    
    
    /**
     * Register a handler that will be called back when the named annotation is
     * encountered on a class.
     * 
     * @param annotationName
     * @param handler
     */
    public void registerAnnotationHandler (String annotationName, DiscoverableAnnotationHandler handler)
    {
        List handlers = _annotationHandlers.get(annotationName);
        if (handlers == null)
        {
            handlers = new ArrayList();
            _annotationHandlers.put(annotationName, handlers);
        }
        handlers.add(handler);
    }
    
    public List getAnnotationHandlers(String annotationName)
    {
        List handlers = _annotationHandlers.get(annotationName);
        if (handlers == null)
            return Collections.emptyList();
        return new ArrayList();
    }

    public List getAnnotationHandlers()
    {
        List allHandlers = new ArrayList();
        for (List list:_annotationHandlers.values())
            allHandlers.addAll(list);
        return allHandlers;
    }

    public void registerClassHandler (ClassHandler handler)
    {
        _classHandlers.add(handler);
    }

    public boolean isParsed (String className)
    {
        return _parsedClassNames.contains(className);
    }
    
    public void parse (String className, ClassNameResolver resolver) 
    throws Exception
    {
        if (className == null)
            return;
        
        if (!resolver.isExcluded(className))
        {
            if (!isParsed(className) || resolver.shouldOverride(className))
            {
                className = className.replace('.', '/')+".class";
                URL resource = Loader.getResource(this.getClass(), className, false);
                if (resource!= null)
                    scanClass(resource.openStream());
            }
        }
    }
    
    public void parse (Class clazz, ClassNameResolver resolver, boolean visitSuperClasses)
    throws Exception
    {
        Class cz = clazz;
        while (cz != null)
        {
            if (!resolver.isExcluded(cz.getName()))
            {
                if (!isParsed(cz.getName()) || resolver.shouldOverride(cz.getName()))
                {
                    String nameAsResource = cz.getName().replace('.', '/')+".class";
                    URL resource = Loader.getResource(this.getClass(), nameAsResource, false);
                    if (resource!= null)
                        scanClass(resource.openStream());
                }
            }
            if (visitSuperClasses)
                cz = cz.getSuperclass();
            else
                cz = null;
        }
    }
    
    public void parse (String[] classNames, ClassNameResolver resolver)
    throws Exception
    {
        if (classNames == null)
            return;
       
        parse(Arrays.asList(classNames), resolver); 
    }
    
    public void parse (List classNames, ClassNameResolver resolver)
    throws Exception
    {
        for (String s:classNames)
        {
            if ((resolver == null) || (!resolver.isExcluded(s) &&  (!isParsed(s) || resolver.shouldOverride(s))))
            {            
                s = s.replace('.', '/')+".class"; 
                URL resource = Loader.getResource(this.getClass(), s, false);
                if (resource!= null)
                    scanClass(resource.openStream());
            }
        }
    }
    
    public void parse (Resource dir, ClassNameResolver resolver)
    throws Exception
    {
        if (!dir.isDirectory() || !dir.exists())
            return;
        
        
        String[] files=dir.list();
        for (int f=0;files!=null && f




© 2015 - 2024 Weber Informatics LLC | Privacy Policy