diff --git a/.gitignore b/.gitignore index 430b1ae3..86dfd5b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ .classpath .project .settings +.idea +jandex.iml +target +*~ \ No newline at end of file diff --git a/pom.xml b/pom.xml index ab36ae3f..0691762f 100644 --- a/pom.xml +++ b/pom.xml @@ -47,5 +47,12 @@ jar test + + org.apache.ant + ant + 1.8.1 + provided + true + diff --git a/src/main/java/org/jboss/jandex/JandexAntTask.java b/src/main/java/org/jboss/jandex/JandexAntTask.java new file mode 100644 index 00000000..2fe51e1d --- /dev/null +++ b/src/main/java/org/jboss/jandex/JandexAntTask.java @@ -0,0 +1,108 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2010, Red Hat, Inc., and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.jandex; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.FileSet; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Ant Task that indexes jars, and saves the resulting index + * @author Stuart Douglas + */ +public class JandexAntTask extends Task { + + private final List filesets = new ArrayList(); + + private boolean modify = false; + + private boolean newJar = false; + + private boolean verbose = false; + + private boolean run = true; + + @Override + public void execute() throws BuildException { + if(!run) { + return; + } + if(modify && newJar) { + throw new BuildException("Specifying both modify and newJar does not make sense."); + } + Indexer indexer = new Indexer(); + for(FileSet fileset : filesets) { + String[] files = fileset.getDirectoryScanner(getProject()).getIncludedFiles(); + for(String file : files) { + if(file.endsWith(".jar")) { + try { + JarIndexer.createJarIndex(new File(fileset.getDir().getAbsolutePath() + "/" +file), indexer, modify, newJar,verbose); + } catch (IOException e) { + throw new BuildException(e); + } + } + } + } + + } + + public void addFileset(FileSet fileset) { + filesets.add(fileset); + } + + public boolean isModify() { + return modify; + } + + public void setModify(boolean modify) { + this.modify = modify; + } + + public boolean isVerbose() { + return verbose; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + public boolean isRun() { + return run; + } + + public void setRun(boolean run) { + this.run = run; + } + + public boolean isNewJar() { + return newJar; + } + + public void setNewJar(boolean newJar) { + this.newJar = newJar; + } +} \ No newline at end of file diff --git a/src/main/java/org/jboss/jandex/JarIndexer.java b/src/main/java/org/jboss/jandex/JarIndexer.java new file mode 100644 index 00000000..a4839e4d --- /dev/null +++ b/src/main/java/org/jboss/jandex/JarIndexer.java @@ -0,0 +1,102 @@ +package org.jboss.jandex; + +import java.io.*; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * + * Class which contains utility methods to create an index for a jar file + * + * @author Stuart Douglas + * + */ +public class JarIndexer { + + /** + * Indexes a jar file and saves the result. If the modify flag is try it is saved META-INF/jandex.idx. + * Otherwies an external file is created with a similar name to the original file, however the + * .jar extension is replaced with -jar.idx + * + * @param jarFile The file to index + * @param indexer The indexer to use + * @param modify If the original jar should be modified + * @param verbose If we should print what we are doing to standard out + */ + public static Result createJarIndex(File jarFile, Indexer indexer, boolean modify, boolean newJar, boolean verbose) throws IOException { + File tmpCopy = null; + ZipOutputStream zo = null; + OutputStream out = null; + File outputFile = null; + + JarFile jar = new JarFile(jarFile); + + if (modify) { + tmpCopy = File.createTempFile(jarFile.getName().substring(0, jarFile.getName().lastIndexOf('.')), "jmp"); + out = zo = new ZipOutputStream(new FileOutputStream(tmpCopy)); + } else if (newJar) { + outputFile = new File(jarFile.getAbsolutePath().replace(".jar", "-jandex.jar")); + out = zo = new ZipOutputStream(new FileOutputStream(outputFile)); + } else + { + outputFile = new File(jarFile.getAbsolutePath().replace(".jar", "-jar") + ".idx"); + out = new FileOutputStream( outputFile); + } + + try { + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + if (modify) { + zo.putNextEntry(entry); + copy(jar.getInputStream(entry), zo); + } + + if (entry.getName().endsWith(".class")) { + ClassInfo info = indexer.index(jar.getInputStream(entry)); + if (verbose && info != null) + printIndexEntryInfo(info); + } + } + + if (modify || newJar) { + zo.putNextEntry(new ZipEntry("META-INF/jandex.idx")); + } + + IndexWriter writer = new IndexWriter(out); + Index index = indexer.complete(); + int bytes = writer.write(index); + + + if (modify) { + jarFile.delete(); + tmpCopy.renameTo(jarFile); + tmpCopy = null; + } + return new Result(index, modify ? "META-INF/jandex.idx" : outputFile.getPath(), bytes); + } finally { + out.flush(); + out.close(); + if (tmpCopy != null) + tmpCopy.delete(); + } + } + + private static void printIndexEntryInfo(ClassInfo info) { + System.out.println("Indexed " + info.name() + " (" + info.annotations().size() + " annotations)"); + } + private static void copy(InputStream in, OutputStream out) throws IOException { + byte[] buf = new byte[8192]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + out.flush(); + } + private JarIndexer() { + + } +} diff --git a/src/main/java/org/jboss/jandex/Main.java b/src/main/java/org/jboss/jandex/Main.java index e0c3dc2b..4f88dd02 100644 --- a/src/main/java/org/jboss/jandex/Main.java +++ b/src/main/java/org/jboss/jandex/Main.java @@ -54,29 +54,6 @@ public static void main(String[] args) { main.execute(args); } - private static class Result { - private int annotations; - private int instances; - private int classes; - private int bytes; - private String name; - - private Result(Index index, String name, int bytes) { - annotations = index.annotations.size(); - instances = countInstances(index); - classes = index.classes.size(); - this.bytes = bytes; - this.name = name; - } - - private int countInstances(Index index) { - int c = 0; - for (List list : index.annotations.values()) - c += list.size(); - - return c; - } - } private void execute(String[] args) { try { @@ -89,9 +66,9 @@ private void execute(String[] args) { long start = System.currentTimeMillis(); Indexer indexer = new Indexer(); - Result result = (source.isDirectory()) ? indexDirectory(source, indexer) : indexJar(source, indexer); + Result result = (source.isDirectory()) ? indexDirectory(source, indexer) : JarIndexer.createJarIndex(source, indexer,modify,verbose); double time = (System.currentTimeMillis() - start) / 1000.00; - System.out.printf("Wrote %s in %.4f seconds (%d classes, %d annotations, %d instances, %d bytes)\n", result.name, time, result.classes, result.annotations, result.instances, result.bytes); + System.out.printf("Wrote %s in %.4f seconds (%d classes, %d annotations, %d instances, %d bytes)\n", result.getName(), time, result.getClasses(), result.getAnnotations(), result.getInstances(), result.getBytes()); } catch (Exception e) { if (!verbose && (e instanceof IllegalArgumentException || e instanceof FileNotFoundException)) { System.err.println(e.getMessage() == null ? e.getClass().getSimpleName() : "ERROR: " + e.getMessage()); @@ -142,77 +119,10 @@ private Result indexDirectory(File source, Indexer indexer) throws FileNotFoundE } } - private Result indexJar(File source, Indexer indexer) throws IOException { - boolean modify = this.modify; - boolean verbose = this.verbose; - File tmpCopy = null; - ZipOutputStream zo = null; - OutputStream out = null; - - JarFile jar = new JarFile(source); - - if (modify) { - tmpCopy = File.createTempFile(source.getName().substring(0, source.getName().lastIndexOf('.')), "jmp"); - out = zo = new ZipOutputStream(new FileOutputStream(tmpCopy)); - } else { - if (outputFile == null) { - outputFile = new File(source.getName().replace('.', '-') + ".idx"); - } - out = new FileOutputStream(outputFile); - } - - try { - Enumeration entries = jar.entries(); - while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); - if (modify) { - zo.putNextEntry(entry); - copy(jar.getInputStream(entry), zo); - } - - if (entry.getName().endsWith(".class")) { - ClassInfo info = indexer.index(jar.getInputStream(entry)); - if (verbose && info != null) - printIndexEntryInfo(info); - } - } - - if (modify) { - zo.putNextEntry(new ZipEntry("META-INF/jandex.idx")); - } - - IndexWriter writer = new IndexWriter(out); - Index index = indexer.complete(); - int bytes = writer.write(index); - - - if (modify) { - source.delete(); - tmpCopy.renameTo(source); - tmpCopy = null; - } - return new Result(index, modify ? "META-INF/jandex.idx" : outputFile.getPath(), bytes); - } finally { - out.flush(); - out.close(); - if (tmpCopy != null) - tmpCopy.delete(); - } - } - private void printIndexEntryInfo(ClassInfo info) { System.out.println("Indexed " + info.name() + " (" + info.annotations().size() + " annotations)"); } - private void copy(InputStream in, OutputStream out) throws IOException { - byte[] buf = new byte[8192]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - out.flush(); - } - private void scanFile(File source, Indexer indexer) throws FileNotFoundException, IOException { if (source.isDirectory()) { File[] children = source.listFiles(); diff --git a/src/main/java/org/jboss/jandex/Result.java b/src/main/java/org/jboss/jandex/Result.java new file mode 100644 index 00000000..fc233878 --- /dev/null +++ b/src/main/java/org/jboss/jandex/Result.java @@ -0,0 +1,91 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2010, Red Hat, Inc., and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.jandex; + +import java.util.List; + +/** + * @author Stuart Douglas + */ +class Result { + private int annotations; + private int instances; + private int classes; + private int bytes; + private String name; + + Result(Index index, String name, int bytes) { + annotations = index.annotations.size(); + instances = countInstances(index); + classes = index.classes.size(); + this.bytes = bytes; + this.name = name; + } + + private int countInstances(Index index) { + int c = 0; + for (List list : index.annotations.values()) + c += list.size(); + + return c; + } + + public int getAnnotations() { + return annotations; + } + + public void setAnnotations(int annotations) { + this.annotations = annotations; + } + + public int getBytes() { + return bytes; + } + + public void setBytes(int bytes) { + this.bytes = bytes; + } + + public int getClasses() { + return classes; + } + + public void setClasses(int classes) { + this.classes = classes; + } + + public int getInstances() { + return instances; + } + + public void setInstances(int instances) { + this.instances = instances; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +}