FileDocCategorySizeDatePackage
ClassPathOpener.javaAPI DocAndroid 1.5 API7589Wed May 06 22:41:02 BST 2009com.android.dx.cf.direct

ClassPathOpener

public class ClassPathOpener extends Object
Opens all the class files found in a class path element. Path elements can point to class files, {jar,zip,apk} files, or directories containing class files.

Fields Summary
private final String
pathname
non-null; pathname to start with
private final Consumer
consumer
non-null; callback interface
private final boolean
sort
If true, sort such that classes appear before their inner classes and "package-info" occurs before all other classes in that package.
Constructors Summary
public ClassPathOpener(String pathname, boolean sort, Consumer consumer)
Constructs an instance.

param
pathname non-null; path element to process
param
sort if true, sort such that classes appear before their inner classes and "package-info" occurs before all other classes in that package.
param
consumer non-null; callback interface

        this.pathname = pathname;
        this.sort = sort;
        this.consumer = consumer;
    
Methods Summary
private static intcompareClassNames(java.lang.String a, java.lang.String b)
Sorts java class names such that outer classes preceed their inner classes and "package-info" preceeds all other classes in its package.

param
a non-null; first class name
param
b non-null; second class name
return
compareTo()-style result

        // Ensure inner classes sort second
        a = a.replace('$",'0");
        b = b.replace('$",'0");

        /*
         * Assuming "package-info" only occurs at the end, ensures package-info
         * sorts first.
         */
        a = a.replace("package-info", "");
        b = b.replace("package-info", "");

        return a.compareTo(b);
    
public booleanprocess()
Processes a path element.

return
the OR of all return values from Consumer.processFileBytes().

        File file = new File(pathname);

        return processOne(file, true);
    
private booleanprocessArchive(java.io.File file)
Processes the contents of an archive (.zip, .jar, or .apk).

param
file non-null; archive file to process
return
whether any processing actually happened
throws
IOException on i/o problem

        ZipFile zip = new ZipFile(file);
        ByteArrayOutputStream baos = new ByteArrayOutputStream(40000);
        byte[] buf = new byte[20000];
        boolean any = false;

        ArrayList<? extends java.util.zip.ZipEntry> entriesList 
                = Collections.list(zip.entries());

        if (sort) {
            Collections.sort(entriesList, new Comparator<ZipEntry>() {
               public int compare (ZipEntry a, ZipEntry b) {
                   return compareClassNames(a.getName(), b.getName());
               }
            });
        }

        consumer.onProcessArchiveStart(file);

        for (ZipEntry one: entriesList) {

            if (one.isDirectory()) {
                continue;
            }

            String path = one.getName();
            InputStream in = zip.getInputStream(one);

            baos.reset();
            for (;;) {
                int amt = in.read(buf);
                if (amt < 0) {
                    break;
                }

                baos.write(buf, 0, amt);
            }

            in.close();

            byte[] bytes = baos.toByteArray();
            any |= consumer.processFileBytes(path, bytes);
        }

        zip.close();
        return any;
    
private booleanprocessDirectory(java.io.File dir, boolean topLevel)
Processes a directory recursively.

param
dir non-null; file representing the directory
param
topLevel whether this is a top-level directory (that is, specified directly on the commandline)
return
whether any processing actually happened

        if (topLevel) {
            dir = new File(dir, ".");
        }

        File[] files = dir.listFiles();
        int len = files.length;
        boolean any = false;

        if (sort) {
            Arrays.sort(files, new Comparator<File>() {
                public int compare(File a, File b) {
                    return compareClassNames(a.getName(), b.getName());
                }
            });
        }

        for (int i = 0; i < len; i++) {
            any |= processOne(files[i], false);
        }

        return any;
    
private booleanprocessOne(java.io.File file, boolean topLevel)
Processes one file.

param
file non-null; the file to process
param
topLevel whether this is a top-level file (that is, specified directly on the commandline)
return
whether any processing actually happened

        try {
            if (file.isDirectory()) {
                return processDirectory(file, topLevel);
            }

            String path = file.getPath();

            if (path.endsWith(".zip") ||
                    path.endsWith(".jar") ||
                    path.endsWith(".apk")) {
                return processArchive(file);
            }

            byte[] bytes = FileUtils.readFile(file);
            return consumer.processFileBytes(path, bytes);
        } catch (Exception ex) {
            consumer.onException(ex);
            return false;
        }