Name der JAR-Datei herausfinden
-
Hallo,
wie bekomme ich den Namen der JAR-Datei heraus, in der die aktuelle Klasse gestartet wurde.Umständlich geht es so:
getClass().getResource("")Und dann in "jar:file:/...name.jar!/..." nach der JAR-Datei parsen.
Muss ich, um zu bestimmen, ob aus einer JAR-Datei gestartet wurde (oder aus einer "unverpackten" Klasse), immer den obigen String parsen, oder kann man auch anders herausfinden, ob man sich in einer JAR-datei befindet?
Vielen Dank.
-
Mich würde mal der Anwendungsfall interessieren, der dich dazu bringt das machen zu müssen
-
Ich greife auf eine Konfigurationsdatei zu. Entwedere sie liegt im Verzeichnis (wenn die Anwendung nicht in einer JAR-Datei liegt) oder sie liegt mit in der JAR-Datei.
Wenn sie in der JAR-Datei liegt, muss ich diese öffnen und die Konfigurationsdatei auslesen.
-
Na so ein Zufall, da habe ich ja gerade etwas. Ist allerdings schon Java 1.5-Code.
package controller; import java.util.*; import java.util.jar.*; import java.io.*; import java.net.*; import container.*; import io.*; public class ResourceLoader { private final LinkedList<File> directoryList; private final LinkedList<JarFile> jarList; public ResourceLoader() { directoryList = new LinkedList<File> (); jarList = new LinkedList<JarFile> (); } public void loadStandardResources() { final String className = getClass().getName().replace('.','/'); final String resourceString = className + ".class"; final URL location = ClassLoader.getSystemResource(resourceString); final String locationString = location.toString(); try { if (locationString.startsWith("jar:")) { final int jarEnd = locationString.indexOf("!"); final String jarString = locationString.substring(4,jarEnd); loadResources(new JarFile(new File(new URI(jarString)))); } else { final int baseEnd = locationString.indexOf("/" + resourceString); final String baseString = locationString.substring (0,baseEnd); loadResources(new File (new URI(baseString))); } } catch (URISyntaxException e) { } catch (IOException e) { } } public boolean loadResources(final JarFile jarFile) { if (jarFile == null) return false; if (jarList.contains(jarFile)) return false; jarList.add(jarFile); return true; } public boolean loadResources(final File directory) { if (directory == null) return false; if (!directory.isDirectory()) return false; if (directoryList.contains(directory)) return false; directoryList.add(directory); return true; } public List<URL> getResourceURLs() { return getResourceURLs(new AcceptAllURLFilter()); } public List<BufferedInputStream> getResourceStreams () { return getResourceStreams(new AcceptAllURLFilter()); } public List<Pair<URL,URL>> getResourceBaseURLPairs () { return getResourceBaseURLPairs(new AcceptAllURLFilter()); } public List<URL> getResourceURLs(final URLFilter filter) { assert(filter != null); return getResources(filter,new URLDescriptor()); } public List<BufferedInputStream> getResourceStreams (final URLFilter filter) { assert(filter != null); return getResources(filter,new StreamDescriptor()); } public List<Pair<URL,URL>> getResourceBaseURLPairs (final URLFilter filter) { assert(filter != null); return getResources(filter,new BaseURLPairDescriptor()); } private <DescriptionType> List<DescriptionType> getResources(final URLFilter filter, final ResourceDescriptor<DescriptionType> descriptor) { final List<DescriptionType> list = new LinkedList<DescriptionType> (); for (final File directory : directoryList) { assert(directory != null); addFileResources(list,filter,descriptor,directory,directory); } for (final JarFile jarFile : jarList) { assert(jarFile != null); addJarResources(list,filter,descriptor,jarFile); } return list; } private static <DescriptionType> void addFileResources(final List<DescriptionType> list, final URLFilter filter, final ResourceDescriptor<DescriptionType> descriptor, final File directory, final File baseDirectory) { assert(list != null); assert(filter != null); assert(descriptor != null); assert(baseDirectory != null); for (final File file : directory.listFiles()) { if (file.isDirectory()) { addFileResources(list,filter,descriptor,file,baseDirectory); continue; } try { final URL url = file.toURL(); if (!filter.acceptsURL(url)) continue; final DescriptionType resource = descriptor.getFileResource(baseDirectory,file,url); if (resource == null) continue; list.add(resource); } catch (MalformedURLException e) { } } } private static <DescriptionType> void addJarResources(final List<DescriptionType> list, final URLFilter filter, final ResourceDescriptor<DescriptionType> descriptor, final JarFile jarFile) { assert(list != null); assert(descriptor != null); final Enumeration jarEntries = jarFile.entries (); final String urlPrefix = "jar:file:" + jarFile.getName() + "!/"; while (jarEntries.hasMoreElements()) { final JarEntry entry = (JarEntry)jarEntries.nextElement(); try { final URL url = new URL(urlPrefix + entry.getName()); if (!filter.acceptsURL(url)) continue; final DescriptionType resource = descriptor.getJarResource(jarFile,entry,url); if (resource == null) continue; list.add(resource); } catch (MalformedURLException e) { } } } private static abstract class ResourceDescriptor<DescriptionType> { public abstract DescriptionType getFileResource (final File baseDirectory, final File file, final URL url); public abstract DescriptionType getJarResource (final JarFile jar, final JarEntry entry, final URL url); } private static class StreamDescriptor extends ResourceDescriptor<BufferedInputStream> { @Overrides public BufferedInputStream getFileResource (final File baseDirectory, final File file, final URL url) { try { return new BufferedInputStream(new FileInputStream (file)); } catch (IOException e) { assert(false); } return null; } @Overrides public BufferedInputStream getJarResource (final JarFile jar, final JarEntry entry, final URL url) { try { return new BufferedInputStream (jar.getInputStream(entry)); } catch (IOException e) { assert(false); } return null; } } private static class URLDescriptor extends ResourceDescriptor<URL> { @Overrides public URL getFileResource (final File baseDirectory, final File file, final URL url) { return url; } @Overrides public URL getJarResource (final JarFile jar, final JarEntry entry, final URL url) { return url; } } private static class BaseURLPairDescriptor extends ResourceDescriptor<Pair<URL,URL>> { @Overrides public Pair<URL,URL> getFileResource (final File baseDirectory, final File file, final URL url) { try { return new Pair<URL,URL> (baseDirectory.toURL(),url); } catch (MalformedURLException e) { assert(false); } return null; } @Overrides public Pair<URL,URL> getJarResource (final JarFile jar, final JarEntry entry, final URL url) { try { return new Pair<URL,URL> (new URL("file:" + jar.getName()), url); } catch (MalformedURLException e) { assert(false); } return null; } } private static class AcceptAllURLFilter implements URLFilter { public boolean acceptsURL (final URL url) { return true; } } }
Ich mache es also letztendlich genauso wie du.
@Cengiz: Komisch, ich wurde auf www.javacore.de auch schon nach dem Sinn davon gefragt. Aber anscheinend gibt es doch noch ein paar andere Leute, die das gleiche Problem haben. Ich benötige das in erster Linie für meinen Plugin-Mechanismus.
-
Ich wollte damit nicht sagen, es sein sinnlos so etwas zu tun. Hat mich halt interessiert
-
@Gregor
Wie ich sehe parst du auch den String um den Namen der JAR-Datei herrauszubekommen. Wahrscheinlich gibt es dann keine elegantere Lösung. Weisst du vielleicht auch, wie (oder ob) ich eine einzelne Datei innerhalb der gestarteten JAR aktualisieren kann?Auslesen tue ich sie aus der JAR-Datei so:
ZipInputStream tmpZipInputStream = new ZipInputStream(new FileInputStream(tmpJARFileName)); ZipEntry tmpZipEntry = tmpZipInputStream.getNextEntry(); // Search the configuration file while(!tmpZipEntry.getName().equals("configuration.properties")){ tmpZipEntry = tmpZipInputStream.getNextEntry(); } Properties tmpProperties = new Properties(); tmpProperties.load(tmpZipInputStream); // Close the input stream tmpZipInputStream.close(); // Read the entries Map.Entry tmpEntry; for(Iterator tmpIterator = tmpProperties.entrySet().iterator(); tmpIterator.hasNext();){ tmpEntry = (Map.Entry)tmpIterator.next(); htConfiguration.put(tmpEntry.getKey(), tmpEntry.getValue()); }
Aber mit dem Schreiben klappt es nicht.
-
Die JAR-Dateien werden wohl zur Laufzeit geschützt sein. Sonst könnte ja jeder einfach Klassen während das Programm läuft austauschen und evtl. vorhandene Sicherheitskriterien umgehen. Ich könnte mir allerdings vorstellen dass man eine JAR-Datei kopieren, die Änderungen da drin machen und bei Programmende die Originaldatei durch die neue ersetzen kann ... ja irgendwie so müsste das gehen.
-
Das habe ich befürchtet. Dann lege ich die Konfigurationsdatei wohl besser nach draussen.
-
Die JAR-Dateien werden wohl zur Laufzeit geschützt sein.
Nur wenn in der security policy entprechende Einträge gemacht wurden.
...lege ich die Konfigurationsdatei wohl besser nach draussen.
Wird wohl sowieso besser sein.
Ich stelle mir gerade vor wie mein UNIX-Admin auf der Arbeit reagieren würden, wenn ein "Benutzer" Schreibrechte für ein Programm unter /opt oder /usr erhalten sollte.
Aber das ist deine Entscheidung.Ich glaube nicht dass das Sicherheitsmodel von Java die Änderungen an der Datei verhindern würde.
Mein Tip: Probier einmal eine Datei in einem Zip Archiv zu ändern. Wenn das Funktioniert Übertrage das Vorgehen auf dein Jar Archiv.