# Jar Archiv nach Manifest Dateien durchsuchen



## cHrIzMaStEr (23. Oktober 2006)

Hallo und Guten Tag,

ich habe folgendes Problem:

Ich habe irgendwo auf dem Dateisystem ein .jar Archiv liegen (z.B. test.jar). Diese Archiv enthält weitere .jar Archive (oder auch .war - z.B. 1.jar / 2.jar / 3.war / ...) und natürlich den META-INF/MANIFEST.MF Ordner mit der Manifest Datei. 
Die Ausgabe dieser ersten Manifest Datei (aus test.jar) ist auch kein Problem, allerdings möchte ich auf alle Manifest Dateien der Jar Archive innerhalb des test.jar Archivs zugreifen, also auch auf die Manifest Dateien aus den .jar Archiven (1.jar / 2.jar / 3.war / ...) die im ersten Archiv (test.jar) enthalten sind!

Leider bekomme ich das nur hin, wenn ich erst jedes Archiv entpacke und dann auf dem Dateisystem nach der MANIFEST.MF suche.... Gibt es eine Möglichkeit ohne jedes Archiv zu entpacken auf die Dateien zuzugriefen!! Dazu müsste ich ja quasi beim rekursiven Aufruf der Methode welche die JAR Einträge auflistet, die jeweilig akutelle Datei angeben (also 1.jar / 2.jar / 3.war / ...) Oder!?

Vlt könnt ihr mir ja helfen oder mir sagen das es nur funktioniert wenn man das Archiv entpackt 

Gruß und Danke schonmal...
chrizmaster


----------



## Thomas Darimont (23. Oktober 2006)

Hallo!

Eine Möglichkeit sähe so aus:

```
/**
 * 
 */
package de.tutorials;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

/**
 * @author Thomas.Darimont
 */
public class JarFileAnalyzer {

  /**
   * @param args
   */
  public static void main(String[] args) throws Exception {
    JarFile jarFile = new JarFile("c:/tmp/commons.jar");
    List<Manifest> manifests = lookForManifestFiles(jarFile, true);
    for (Manifest manifest : manifests) {
      System.out.println(manifest.getMainAttributes().getValue("Implementation-Title"));
    }

  }


  private static List<Manifest> lookForManifestFiles(JarFile jarFile, boolean pseudoRecursive) throws Exception {
    List<Manifest> manifests = new ArrayList<Manifest>();
    manifests.add(jarFile.getManifest());
    if (pseudoRecursive) {
      Enumeration<JarEntry> jarEntries = jarFile.entries();
      while (jarEntries.hasMoreElements()) {
        JarEntry jarEntry = jarEntries.nextElement();
        if (jarEntry.getName().toLowerCase().matches(".*\\.jar$")) {
          JarInputStream jarInputStream = new JarInputStream(jarFile.getInputStream(jarEntry));
          manifests.add(jarInputStream.getManifest());
          jarInputStream.close();
        }
      }
    }

    return manifests;
  }
}
```
...das wäre mal die dummy-Implementierung für den Fall, dass die Verschachtelung nicht größer als 1 (-> jar in jar) ist.

Gruß Tom


----------



## cHrIzMaStEr (23. Oktober 2006)

Danke schonmal für die schnelle Antwort... werde mir das gleich mal anschauen und versuchen umzusetzen...!

Leider kann es aber sein, das die Verschachtelung noch tiefer geht....

z.B.

xxx.jar
xxx.war​xxx.jar​xxx.jar​xxx.jar​xxx.jar​xxx.jar​xxx.jar​

gruß
chrizmaster


----------



## cHrIzMaStEr (23. Oktober 2006)

Gut, habs bissl auf mein Programm umgebaut und das klappt soweit schonmal...! DANKE!

nur das er noch tiefer geht....!


----------



## cHrIzMaStEr (23. Oktober 2006)

Oder gibt es eine Möglichkeit von JarEntry zu JarFile zu konvertieren!!

Dann könnte man der Methode welche das JarFile übergeben kriegt und die Entry's ausließt, dass akutelle Entry als JarFile beim rekursiven Aufruf übergeben....!?

mhhh oder gibt es noch eine andere Möglichkeit...!!

gruß und danke
chrizmaster


----------



## Thomas Darimont (23. Oktober 2006)

Hallo!

schau mal hier:

```
/**
 * 
 */
package de.tutorials;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

/**
 * @author Thomas.Darimont
 */
public class JarFileAnalyzer {

  /**
   * @param args
   */
  public static void main(String[] args) throws Exception {
    JarFile jarFile = new JarFile("c:/tmp/base.jar");
    List<Manifest> manifests = lookForManifestFiles(jarFile, true);
    for (Manifest manifest : manifests) {
      System.out.println(manifest.getMainAttributes().getValue("Implementation-Title"));
    }

  }


  private static List<Manifest> lookForManifestFiles(JarFile jarFile, boolean recursive) throws Exception {
    List<Manifest> manifests = new ArrayList<Manifest>();
    manifests.add(jarFile.getManifest());
    if (recursive) {
      Enumeration<JarEntry> jarEntries = jarFile.entries();
      while (jarEntries.hasMoreElements()) {
        JarEntry jarEntry = jarEntries.nextElement();
        if (jarEntry.getName().toLowerCase().matches(".*\\.(jar|war)$")) {
          System.out.println("nested jarEntry: " + jarEntry.getName());
          JarInputStream jarInputStream = new JarInputStream(jarFile.getInputStream(jarEntry));
          manifests.add(jarInputStream.getManifest());
          lookForManifestFilesInNestedJarEntry(jarInputStream, manifests);
          jarInputStream.close();
        }
      }
    }

    return manifests;
  }


  private static void lookForManifestFilesInNestedJarEntry(JarInputStream jarInputStream,
    List<Manifest> manifests) throws Exception {
    JarEntry nestedJarEntry = null;
    while ((nestedJarEntry = jarInputStream.getNextJarEntry()) != null) {
      if (nestedJarEntry.getName().toLowerCase().matches(".*\\.(jar|war)$")) {
        System.out.println("nested jarEntry: " + nestedJarEntry.getName());
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int len = 0;
        byte[] buffer = new byte[32768];
        while ((len = jarInputStream.read(buffer)) > 0) {
          byteArrayOutputStream.write(buffer, 0, len);
        }
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        JarInputStream nestedJarInputStream = new JarInputStream(byteArrayInputStream);
        manifests.add(nestedJarInputStream.getManifest());
        lookForManifestFilesInNestedJarEntry(nestedJarInputStream, manifests);
        nestedJarInputStream.close();
      }
      jarInputStream.closeEntry();
    }
  }

}
```

Ausgabe:

```
nested jarEntry: inner.jar
nested jarEntry: innerinner.jar
nested jarEntry: innerinnerinner.war
base
inner
innerinner
innerinnerinner
```

Gruß Tom


----------



## cHrIzMaStEr (23. Oktober 2006)

Besten Dank werd's mir mal anschauen!!

gruß
chrizmaster


----------



## cHrIzMaStEr (24. Oktober 2006)

Hallo, ich nochmal....

also habs soweit eingebunden und bissl verändert und läuft alles bestens! Nochmal zum Verständnis, wozu die folgenden Zeilen da sind:


```
...
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[32768];
while ((len = jarInputStream.read(buffer)) > 0) {
byteArrayOutputStream.write(buffer, 0, len);
}
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
JarInputStream nestedJarInputStream = new JarInputStream(byteArrayInputStream
...
```

Wozu dient der ByteArrayInput/OutputStream

gruß
chrizmaster


----------



## Thomas Darimont (24. Oktober 2006)

Hallo!

Damit entpacke ich die genesteten Jars temporär in den Speicher... du wolltest sie ja nicht auf der Platte haben, jedoch müssen sie zum Untersuchen eben entpackt werden. Also vorsicht damit ;-)

Gruß Tom


----------

