FileDocCategorySizeDatePackage
ClassPathOpener.javaAPI DocAndroid 5.1 API8951Thu Mar 12 22:18:30 GMT 2015com.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
{@code non-null;} pathname to start with
private final Consumer
consumer
{@code 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.
private FileNameFilter
filter
public static final FileNameFilter
acceptAll
An accept all filter.
Constructors Summary
public ClassPathOpener(String pathname, boolean sort, Consumer consumer)
Constructs an instance.

param
pathname {@code 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 {@code non-null;} callback interface


                                                 
           
        this(pathname, sort, acceptAll, consumer);
    
public ClassPathOpener(String pathname, boolean sort, FileNameFilter filter, Consumer consumer)
Constructs an instance.

param
pathname {@code 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 {@code non-null;} callback interface

        this.pathname = pathname;
        this.sort = sort;
        this.consumer = consumer;
        this.filter = filter;
    
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 {@code non-null;} first class name
param
b {@code non-null;} second class name
return
{@code 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 {@code Consumer.processFileBytes()}.

        File file = new File(pathname);

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

param
file {@code 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();
            if (filter.accept(path)) {
                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, one.getTime(), bytes);
            }
        }

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

param
dir {@code 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 {@code 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);
            }
            if (filter.accept(path)) {
                byte[] bytes = FileUtils.readFile(file);
                return consumer.processFileBytes(path, file.lastModified(), bytes);
            } else {
                return false;
            }
        } catch (Exception ex) {
            consumer.onException(ex);
            return false;
        }