Ich muss die Manifest
Datei lesen , die meine Klasse geliefert hat, aber wenn ich benutze:
getClass().getClassLoader().getResources(...)
Ich bekomme das MANIFEST
von der ersten .jar
in die Java Runtime geladen.
Meine App wird über ein Applet oder einen Webstart ausgeführt,
sodass ich vermutlich keinen Zugriff auf meine eigene .jar
Datei habe.
Ich möchte eigentlich das Export-package
Attribut lesen , von dem aus .jar
Felix OSGi gestartet wurde, damit ich diese Pakete Felix zugänglich machen kann. Irgendwelche Ideen?
java
osgi
manifest.mf
apache-felix
Houtman
quelle
quelle
Antworten:
Sie können eines von zwei Dingen tun:
Rufen Sie
getResources()
die zurückgegebene URL-Sammlung auf, durchlaufen Sie sie und lesen Sie sie als Manifest, bis Sie Ihre finden:Sie können versuchen zu überprüfen, ob
getClass().getClassLoader()
es sich um eine Instanz von handeltjava.net.URLClassLoader
. Die Mehrheit der Sun-Klassenlader sind, einschließlichAppletClassLoader
. Sie können es dann umwandeln undfindResource()
das bekannte - zumindest für Applets - aufrufen , um das benötigte Manifest direkt zurückzugeben:quelle
Sie finden zuerst die URL für Ihre Klasse. Wenn es sich um eine JAR handelt, laden Sie das Manifest von dort. Beispielsweise,
quelle
classPath.replace("org/example/MyClass.class", "META-INF/MANIFEST.MF"
getSimpleName
der Name der äußeren Klasse entfernt wird. Dies funktioniert für innere Klassen :clazz.getName().replace (".", "/") + ".class"
.Sie können
Manifests
aus jcabi-Manifesten verwenden und jedes Attribut aus jeder verfügbaren MANIFEST.MF-Datei mit nur einer Zeile lesen:Die einzige Abhängigkeit, die Sie benötigen, ist:
Weitere Informationen finden Sie in diesem Blogbeitrag: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html
quelle
<logger name="com.jcabi.manifests" level="OFF"/>
Ich gebe vorab zu, dass diese Antwort nicht die ursprüngliche Frage beantwortet, nämlich allgemein auf das Manifest zugreifen zu können. Wenn jedoch wirklich eines von mehreren "Standard" -Manifestattributen gelesen werden muss, ist die folgende Lösung viel einfacher als die oben genannten. Ich hoffe also, dass der Moderator dies zulässt. Beachten Sie, dass sich diese Lösung in Kotlin und nicht in Java befindet, aber ich würde erwarten, dass ein Port nach Java trivial ist. (Obwohl ich zugebe, dass ich das Java-Äquivalent von ".`package`" nicht kenne.
In meinem Fall wollte ich das Attribut "Implementation-Version" lesen, also begann ich mit den oben angegebenen Lösungen, um den Stream zu erhalten, und las ihn dann, um den Wert zu erhalten. Während diese Lösung funktionierte, zeigte mir ein Mitarbeiter, der meinen Code überprüfte, einen einfacheren Weg, um das zu tun, was ich wollte. Beachten Sie, dass sich diese Lösung in Kotlin und nicht in Java befindet.
Beachten Sie erneut, dass dies nicht die ursprüngliche Frage beantwortet, insbesondere "Export-Paket" scheint nicht eines der unterstützten Attribute zu sein. Es gibt jedoch einen myPackage.name, der einen Wert zurückgibt. Vielleicht kann jemand, der dies besser versteht als ich, kommentieren, ob dies den Wert zurückgibt, den das Originalplakat anfordert.
quelle
String implementationVersion = MyApplication.class.getPackage().getImplementationVersion();
Ich glaube, der am besten geeignete Weg, um das Manifest für ein Bundle (einschließlich des Bundles, das eine bestimmte Klasse geladen hat) zu erhalten, ist die Verwendung des Bundle- oder BundleContext-Objekts.
Beachten Sie, dass das Bundle-Objekt auch das
getEntry(String path)
Nachschlagen von Ressourcen in einem bestimmten Bundle bietet, anstatt den gesamten Klassenpfad dieses Bundles zu durchsuchen.Wenn Sie bündelspezifische Informationen wünschen, verlassen Sie sich im Allgemeinen nicht auf Annahmen über die Klassenladeprogramme, sondern verwenden Sie einfach die OSGi-APIs direkt.
quelle
Der folgende Code funktioniert mit mehreren Arten von Archiven (jar, war) und mehreren Arten von Klassenladeprogrammen (jar, url, vfs, ...).
quelle
clz.getResource(resource).toString()
Backslashes sein?Der einfachste Weg ist die Verwendung der JarURLConnection-Klasse:
Da in einigen Fällen
...class.getProtectionDomain().getCodeSource().getLocation();
Pfad mit angibtvfs:/
, sollte dies zusätzlich behandelt werden.quelle
Sie können getProtectionDomain (). GetCodeSource () folgendermaßen verwenden:
quelle
getCodeSource
kann zurückkehrennull
. Was sind die Kriterien, damit dies funktioniert? Die Dokumentation erklärt dies nicht.DataUtilities
importiert? Es scheint nicht im JDK zu sein.Warum schließen Sie den Schritt getClassLoader ein? Wenn Sie "this.getClass (). GetResource ()" sagen, sollten Sie Ressourcen relativ zur aufrufenden Klasse abrufen. Ich habe ClassLoader.getResource () noch nie verwendet. Wenn Sie sich jedoch die Java-Dokumente ansehen, erhalten Sie die erste Ressource dieses Namens, die in einem aktuellen Klassenpfad gefunden wird.
quelle
class.getResource("myresource.txt")
wird beim Aufruf versucht, diese Ressource zu ladencom/mypackage/myresource.txt
. Wie genau werden Sie diesen Ansatz verwenden, um das Manifest zu erhalten?quelle
cl.getResourceAsStream("META-INF/MANIFEST.MF")
.classLoader.getResource(..)
undurl.openStream()
völlig irrelevant und fehleranfällig ist, da er versucht, dasselbe zu tun wie erclassLoader.getResourceAsStream(..)
.ClassLoader classLoader = cl.getClassLoader(); return new Manifest(classLoader.getResourceAsStream("/META-INF/MANIFEST.MF"));
Ich habe die Lösung von Anthony Juckel verwendet, aber in MANIFEST.MF muss der Schlüssel mit Großbuchstaben beginnen.
Meine MANIFEST.MF-Datei enthält also einen Schlüssel wie:
Mykey: Wert
Dann können Sie im Aktivator oder einer anderen Klasse den Code von Anthony verwenden, um die Datei MANIFEST.MF und den Wert zu lesen, den Sie benötigen.
quelle
Ich habe diese seltsame Lösung, die Kriegsanwendungen auf einem eingebetteten Jetty-Server ausführt, aber diese Apps müssen auch auf Standard-Tomcat-Servern ausgeführt werden, und wir haben einige spezielle Eigenschaften im Manfest.
Das Problem war, dass in Tomcat das Manifest gelesen werden konnte, aber in der Anlegestelle ein zufälliges Manifest aufgenommen wurde (das die besonderen Eigenschaften verfehlte).
Basierend auf der Antwort von Alex Konshin habe ich die folgende Lösung gefunden (der Inputstream wird dann in einer Manifest-Klasse verwendet):
quelle