Zugriff auf MANIFEST Datei

derHarri

Grünschnabel
Hallo,

ich habe folgendes Problem. Ich soll zur Laufzeit Informationen aus einem MANIFEST lesen. Ich habe ein Anwendung die als jar gepackt wird. In ihr befindet sich dementsprechend das zu lesende MANIFEST. Die Klasse, die die Information lesen soll, befindet sich ebenfalls in dem Jar. Ich versuche also nicht auf ein MANIFEST in einem externen jar zuzugreifen sondern auf "das eigene".
Das klingt, als würde es dafür eine simple und elegante Lösung geben. Ich habe sie nur leider bisher nicht gefunden. Wäre cool, wenn mir jemand weiterhelfen könnte.

Danke schonmal

Harri E.
 
Hallo!

Ein (sicherer) Weg waere beispielsweise:
Java:
/**
 * 
 */
package de.tutorials;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

/**
 * @author Tom
 * 
 */
public class ManifestAnalyzer {

	/**
	 * @param args
	 */
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		Manifest manifest = getManifestFileOfJarContaining(ManifestAnalyzer.class);
		System.out.println(manifest.getMainAttributes().getValue("Main-Class"));
	}

	/**
	 * @return
	 * @throws IOException
	 * @throws URISyntaxException
	 */
	public static Manifest getManifestFileOfJarContaining(Class clazz)
			throws IOException, URISyntaxException {
		JarFile jarFile = new JarFile(new File(clazz.getProtectionDomain()
				.getCodeSource().getLocation().toURI()));
		Manifest manifest = jarFile.getManifest();
		jarFile.close();
		return manifest;
	}
}

Code:
C:\>java -jar manifestAnalyzer.jar
de.tutorials.ManifestAnalyzer

Eine andere Moeglichkeit waere ueber den entsprechenden ClassLoader zu gehen... das Problem hierbei ist jedoch, dass der zum Jar gehoerende ClassLoader auch noch andere Jars im Repository hat...:
Java:
URL manifestResource = ManifestAnalyzer.class.getClassLoader()
                .getResource("META-INF/MANIFEST.MF");
        System.out.println(manifestResource);
Liefert beispielsweise:
Code:
C:\>java -jar manifestAnalyzer.jar
jar:file:/C:/Program%20Files/Java/jdk1.5.0_05/jre/lib/rt.jar!/META-INF/MANIFEST.MF

Java:
    Enumeration manifestResources = ManifestAnalyzer.class.getClassLoader()
                .getResources("META-INF/MANIFEST.MF");
        while (manifestResources.hasMoreElements()) {
            System.out.println(manifestResources.nextElement());
        }

Code:
C:\>java -jar manifestAnalyzer.jar
jar:file:/C:/Program%20Files/Java/jdk1.5.0_05/jre/lib/rt.jar!/META-INF/MANIFEST.MF
jar:file:/C:/Program%20Files/Java/jdk1.5.0_05/jre/lib/jsse.jar!/META-INF/MANIFEST.MF
jar:file:/C:/Program%20Files/Java/jdk1.5.0_05/jre/lib/jce.jar!/META-INF/MANIFEST.MF
jar:file:/C:/Program%20Files/Java/jdk1.5.0_05/jre/lib/charsets.jar!/META-INF/MANIFEST.MF
jar:file:/C:/Program%20Files/Java/jdk1.5.0_05/jre/lib/ext/dnsns.jar!/META-INF/MANIFEST.MF
jar:file:/C:/Program%20Files/Java/jdk1.5.0_05/jre/lib/ext/localedata.jar!/META-INF/MANIFEST.MF
jar:file:/C:/Program%20Files/Java/jdk1.5.0_05/jre/lib/ext/sunjce_provider.jar!/META-INF/MANIFEST.MF
jar:file:/C:/Program%20Files/Java/jdk1.5.0_05/jre/lib/ext/sunpkcs11.jar!/META-INF/MANIFEST.MF
jar:file:/C:/manifestAnalyzer.jar!/META-INF/MANIFEST.MF

Gruss Tom
 

Anhänge

Hallo!

Es geht,soweit ich weiss, auch mit dem JarFileInputStream ...
AFAIK ist es egal ob man ueber das JarFile oder ein JarInputStream geht um sich mit getManifest das entsprechende Manifest zu besorgen. Der Punkt ist dass man dazu auf jeden Fall das Jar bzw. die Location des jars kennen muss. Um den Speicherort des Jar Files zu erfahren in dem sich eine spezielle Klasse befindet ist es eben eine Moeglichkeit ueber clazz.getProtectionDomain()
.getCodeSource().getLocation().toURI() zu gehen.

Gruss Tom
 
Hallo Tom,

wieso wird hier das Manifest vom JDK ausgegeben anstatt dessen, von welcher die Main-Class aufgerufen wird?

Java:
import java.io.*;

public class ReadManifest {

	public static void main(String[] args) {
		try {
			InputStream is = ReadManifest.class.getClassLoader()
					.getResourceAsStream("META-INF/MANIFEST.MF");
			BufferedReader in = new BufferedReader(new InputStreamReader(is));
			String s = "";
			while ((s = in.readLine()) != null)
				System.out.println(s);
			in.close();

		} catch (NullPointerException e) {
			System.out.println("Error: " + e.getMessage());
		} catch (IOException e) {
			System.out.println("Error: " + e.getMessage());
		}
	}
}

Ausgabe:
Code:
Manifest-Version: 1.0
Specification-Title: Java Platform API Specificat
Created-By: 1.5.0_04 (Sun Microsystems Inc.)
Implementation-Title: Java Runtime Environment
Specification-Vendor: Sun Microsystems, Inc.
Specification-Version: 1.5
Implementation-Version: 1.5.0_04
Implementation-Vendor: Sun Microsystems, Inc.

Name: javax/swing/JRadioButtonMenuItem.class
Java-Bean: True

Name: javax/swing/JList.class
Java-Bean: True

Name: javax/swing/JPasswordField.class
Java-Bean: True

...


Vg Erdal
 
Hallo!

Wie ich schon sagte, der ClassLoader der fuer "dieses" Jar verantwortlich ist hat auch noch andere Jars in seiner URL Liste. Wenn man nun mit getResource(...) eine Resource sucht, dann schaut der ClassLoader mit dem angegebenen Suchmuster in seine URL Liste und gibt den zuerst gefunden Eintrag zurueck...

Java:
      Enumeration manifestResources = ManifestAnalyzer.class.getClassLoader()
                      .getResources("META-INF/MANIFEST.MF");
              while (manifestResources.hasMoreElements()) {
                  System.out.println(manifestResources.nextElement());
              }
aus meinem Beispiel listet alle Resourcen auf die dem angegebenen Muster entsprechen.

Gruss Tom
 
Zurück