FileDocCategorySizeDatePackage
AnnotationLister.javaAPI DocAndroid 1.5 API9313Wed May 06 22:41:02 BST 2009com.android.dx.command.annotool

AnnotationLister

public class AnnotationLister extends Object
Greps annotations on a set of class files and prints matching elements to stdout. What counts as a match and what should be printed is controlled by the Main.Arguments instance.

Fields Summary
private static final String
PACKAGE_INFO
The string name of the pseudo-class that contains package-wide annotations
private final Main.Arguments
args
current match configuration
HashSet
matchInnerClassesOf
Set of classes whose inner classes should be considered matched
HashSet
matchPackages
set of packages whose classes should be considered matched
Constructors Summary
AnnotationLister(Main.Arguments args)


       
        this.args = args;
    
Methods Summary
private booleanisMatchingInnerClass(java.lang.String s)
Checks to see if a specified class name should be considered a match due to previous matches.

param
s non-null; class name
return
true if this class should be considered a match

        int i;

        while (0 < (i = s.lastIndexOf('$"))) {
            s = s.substring(0, i);
            if (matchInnerClassesOf.contains(s)) {
                return true;
            }
        }

        return false;
    
private booleanisMatchingPackage(java.lang.String s)
Checks to see if a specified package should be considered a match due to previous matches.

param
s non-null; package name
return
true if this package should be considered a match

        int slashIndex = s.lastIndexOf('/");

        String packageName;
        if (slashIndex == -1) {
            packageName = "";
        } else {
            packageName
                    = s.substring(0, slashIndex);
        }

        return matchPackages.contains(packageName);
    
private voidprintMatch(com.android.dx.cf.direct.DirectClassFile cf)
Prints, or schedules for printing, elements related to a matching class.

param
cf non-null; matching class

        for(Main.PrintType pt: args.printTypes) {
            switch (pt) {
                case CLASS:
                    String classname;
                    classname = cf.getThisClass().getClassType().getClassName();
                    classname = classname.replace('/",'.");
                    System.out.println(classname);
                    break;
                case INNERCLASS:
                    matchInnerClassesOf.add(
                            cf.getThisClass().getClassType().getClassName());
                    break;
                case METHOD:
                    //TODO
                    break;
                case PACKAGE:
                    break;
            }
        }
    
private voidprintMatchPackage(java.lang.String packageName)
Prints, or schedules for printing, elements related to a matching package.

param
packageName non-null; name of package

        for(Main.PrintType pt: args.printTypes) {
            switch (pt) {
                case CLASS:
                case INNERCLASS:
                case METHOD:
                    matchPackages.add(packageName);                    
                    break;
                case PACKAGE:
                    System.out.println(packageName.replace('/",'."));
                    break;
            }
        }
    
voidprocess()
Processes based on configuration specified in constructor.

        for (String path: args.files) {
            ClassPathOpener opener;

            opener = new ClassPathOpener(path, true,
                    new ClassPathOpener.Consumer() {
                public boolean processFileBytes(String name, byte[] bytes) {
                    if (!name.endsWith(".class")) {
                        return true;
                    }

                    ByteArray ba = new ByteArray(bytes);
                    DirectClassFile cf
                        = new DirectClassFile(ba, name, true);

                    cf.setAttributeFactory(StdAttributeFactory.THE_ONE);
                    AttributeList attributes = cf.getAttributes();
                    Attribute att;

                    String cfClassName
                            = cf.getThisClass().getClassType().getClassName();

                    if (cfClassName.endsWith(PACKAGE_INFO)) {
                        att = attributes.findFirst(
                                AttRuntimeInvisibleAnnotations.ATTRIBUTE_NAME);

                        for (;att != null; att = attributes.findNext(att)) {
                            BaseAnnotations ann = (BaseAnnotations)att;
                            visitPackageAnnotation(cf, ann);
                        }

                        att = attributes.findFirst(
                                AttRuntimeVisibleAnnotations.ATTRIBUTE_NAME);

                        for (;att != null; att = attributes.findNext(att)) {
                            BaseAnnotations ann = (BaseAnnotations)att;
                            visitPackageAnnotation(cf, ann);
                        }
                    } else if (isMatchingInnerClass(cfClassName)
                            || isMatchingPackage(cfClassName)) {
                        printMatch(cf);
                    } else {
                        att = attributes.findFirst(
                                AttRuntimeInvisibleAnnotations.ATTRIBUTE_NAME);

                        for (;att != null; att = attributes.findNext(att)) {
                            BaseAnnotations ann = (BaseAnnotations)att;
                            visitClassAnnotation(cf, ann);
                        }

                        att = attributes.findFirst(
                                AttRuntimeVisibleAnnotations.ATTRIBUTE_NAME);

                        for (;att != null; att = attributes.findNext(att)) {
                            BaseAnnotations ann = (BaseAnnotations)att;
                            visitClassAnnotation(cf, ann);
                        }
                    }

                    return true;
                }

                public void onException(Exception ex) {
                    throw new RuntimeException(ex);
                }

                public void onProcessArchiveStart(File file) {

                }

            });

            opener.process();
        }
    
private voidvisitClassAnnotation(com.android.dx.cf.direct.DirectClassFile cf, com.android.dx.cf.attrib.BaseAnnotations ann)
Inspects a class annotation.

param
cf non-null; class file
param
ann non-null; annotation


        if (!args.eTypes.contains(ElementType.TYPE)) {
            return;
        }

        for (Annotation anAnn: ann.getAnnotations().getAnnotations()) {
            String annClassName
                    = anAnn.getType().getClassType().getClassName();
            if (args.aclass.equals(annClassName)) {
                printMatch(cf);
            }
        }
    
private voidvisitPackageAnnotation(com.android.dx.cf.direct.DirectClassFile cf, com.android.dx.cf.attrib.BaseAnnotations ann)
Inspects a package annotation

param
cf non-null; class file of "package-info" pseudo-class
param
ann non-null; annotation


        if (!args.eTypes.contains(ElementType.PACKAGE)) {
            return;
        }

        String packageName = cf.getThisClass().getClassType().getClassName();

        int slashIndex = packageName.lastIndexOf('/");

        if (slashIndex == -1) {
            packageName = "";
        } else {
            packageName
                    = packageName.substring(0, slashIndex);
        }


        for (Annotation anAnn: ann.getAnnotations().getAnnotations()) {
            String annClassName
                    = anAnn.getType().getClassType().getClassName();
            if (args.aclass.equals(annClassName)) {
                printMatchPackage(packageName);
            }
        }