Parse zip or Jar project

900 views Asked by At

I need to return all the packages, classes ... that a java project (zip/jar) contains. I guess QDox can do that. I found that class : http://www.jarvana.com/jarvana/view/com/ning/metrics.serialization-all/2.0.0-pre5/metrics.serialization-all-2.0.0-pre5-jar-with-dependencies-sources.jar!/com/thoughtworks/qdox/tools/QDoxTester.java?format=ok

package com.thoughtworks.qdox.tools;

import com.thoughtworks.qdox.JavaDocBuilder;
import com.thoughtworks.qdox.directorywalker.DirectoryScanner;
import com.thoughtworks.qdox.directorywalker.FileVisitor;
import com.thoughtworks.qdox.directorywalker.SuffixFilter;
import com.thoughtworks.qdox.parser.ParseException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * Tool for testing that QDox can parse Java source code.
 *
 * @author Joe Walnes
 */
public class QDoxTester {

    public static interface Reporter {
        void success(String id);

        void parseFailure(String id, int line, int column, String reason);

        void error(String id, Throwable throwable);
    }

    private final Reporter reporter;

    public QDoxTester(Reporter reporter) {
        this.reporter = reporter;
    }

    public void checkZipOrJarFile(File file) throws IOException {
        ZipFile zipFile = new ZipFile(file);
        Enumeration entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry zipEntry = (ZipEntry) entries.nextElement();
            InputStream inputStream = zipFile.getInputStream(zipEntry);
            try {
                verify(file.getName() + "!" + zipEntry.getName(), inputStream);
            } finally {
                inputStream.close();
            }
        }
    }

    public void checkDirectory(File dir) throws IOException {
        DirectoryScanner directoryScanner = new DirectoryScanner(dir);
        directoryScanner.addFilter(new SuffixFilter(".java"));
        directoryScanner.scan(new FileVisitor() {
            public void visitFile(File file) {
                try {
                    checkJavaFile(file);
                } catch (IOException e) {
                    // ?
                }
            }
        });
    }

    public void checkJavaFile(File file) throws IOException {
        InputStream inputStream = new FileInputStream(file);
        try {
            verify(file.getName(), inputStream);
        } finally {
            inputStream.close();
        }
    }

    private void verify(String id, InputStream inputStream) {
        try {
            JavaDocBuilder javaDocBuilder = new JavaDocBuilder();
            javaDocBuilder.addSource(new BufferedReader(new InputStreamReader(inputStream)));
            reporter.success(id);
        } catch (ParseException parseException) {
            reporter.parseFailure(id, parseException.getLine(), parseException.getColumn(), parseException.getMessage());
        } catch (Exception otherException) {
            reporter.error(id, otherException);
        }
    }

    public static void main(String[] args) throws IOException {
        if (args.length == 0) {
            System.err.println("Tool that verifies that QDox can parse some Java source.");
            System.err.println();
            System.err.println("Usage: java " + QDoxTester.class.getName() + " src1 [src2] [src3]...");
            System.err.println();
            System.err.println("Each src can be a single .java file, or a directory/zip/jar containing multiple source files");
            System.exit(-1);
        }

        ConsoleReporter reporter = new ConsoleReporter(System.out);
        QDoxTester qDoxTester = new QDoxTester(reporter);
        for (int i = 0; i < args.length; i++) {
            File file = new File(args[i]);
            if (file.isDirectory()) {
                qDoxTester.checkDirectory(file);
            } else if (file.getName().endsWith(".java")) {
                qDoxTester.checkJavaFile(file);
            } else if (file.getName().endsWith(".jar") || file.getName().endsWith(".zip")) {
                qDoxTester.checkZipOrJarFile(file);
            } else {
                System.err.println("Unknown input <" + file.getName() + ">. Should be zip, jar, java or directory");
            }
        }
        reporter.writeSummary();
    }

    private static class ConsoleReporter implements Reporter {

        private final PrintStream out;

        private int success;
        private int failure;
        private int error;

        private int dotsWrittenThisLine;

        public ConsoleReporter(PrintStream out) {
            this.out = out;
        }

        public void success(String id) {
            success++;
            if (++dotsWrittenThisLine > 80) {
                newLine();
            }
            out.print('.');
        }

        private void newLine() {
            dotsWrittenThisLine = 0;
            out.println();
            out.flush();
        }

        public void parseFailure(String id, int line, int column, String reason) {
            newLine();
            out.println("* " + id);
            out.println("  [" + line + ":" + column + "] " + reason);
            failure++;
        }

        public void error(String id, Throwable throwable) {
            newLine();
            out.println("* " + id);
            throwable.printStackTrace(out);
            error++;
        }

        public void writeSummary() {
            newLine();
            out.println("-- Summary --------------");
            out.println("Success: " + success);
            out.println("Failure: " + failure);
            out.println("Error  : " + error);
            out.println("Total  : " + (success + failure + error));
            out.println("-------------------------");
        }

    }
}

It contains a method called checkZipOrJarFile(File file), maybe it could help me. but I can't find any examples or tutorials on how to use it.

Any help is welcomed.

1

There are 1 answers

0
Rhubarb On

QDox cannot do that for you, unfortunately (I came here looking for QDox support for jars). The source code for QDox that you list above is only for testing if the classes in the given jar can be parsed successfully by QDox. That code does, however, give you a clue on how to use standard java apis to do what you want: enumerate over classed in a jar.

Here's some code I'm using (which I cribbed from another SO answer here: analyze jar file programmatically)

// Your jar file
JarFile jar = new JarFile(jarFile);
// Getting the files into the jar
Enumeration<? extends JarEntry> enumeration = jar.entries();

// Iterates into the files in the jar file
while (enumeration.hasMoreElements()) {
    ZipEntry zipEntry = enumeration.nextElement();

    // Is this a class?
    if (zipEntry.getName().endsWith(".class")) {

    // Relative path of file into the jar.
    String className = zipEntry.getName();

    // Complete class name
    className = className.replace(".class", "").replace("/", ".");

    // Load class definition from JVM - you may not need this, but I want to introspect the class
    try {
        Class<?> clazz = getClass().getClassLoader().loadClass(className);
        // ... I then go on to do some intropsection

If you don't actually want to introspect the class as I do, you can stop at getName(). Also, if you specifically want to find packages, you could use zipEntry.isDirectory() on your zip entries.