解析zip或Jar项目

时间:2013-04-25 22:42:24

标签: java parsing jar qdox

我需要返回java项目(zip / jar)包含的所有包,类。我猜QDox可以做到这一点。我找到了课程: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("-------------------------");
        }

    }
}

它包含一个名为checkZipOrJarFile(File file)的方法,也许它可以帮助我。但我找不到任何关于如何使用它的示例或教程。

欢迎任何帮助。

1 个答案:

答案 0 :(得分:1)

不幸的是,QDox无法为您做到这一点(我来到这里寻找QDox对罐子的支持)。您在上面列出的QDox源代码仅用于测试是否可以通过QDox成功解析给定jar中的类。但是,该代码确实为您提供了如何使用标准java apis来做你想做的事情的线索:枚举在jar中的类。

以下是我正在使用的一些代码(我在这里提出了另一个答案: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

如果你真的不想像我那样反省这个类,你可以停在getName()。此外,如果您特别想要查找包,可以在zip条目上使用zipEntry.isDirectory()