2010-09-02 26 views
12

La domanda dice tutto.Caricamento di un file relativo al file jar in esecuzione

La specialità nel mio caso è che la directory di lavoro corrente non è la posizione del file jar ma c:\Windows\system32 (Il mio file jar è avviato da Windows utilizzando il menu di scelta rapida, voglio passare il percorso di una cartella come parametro per il vaso).

Ora voglio caricare un file di configurazione chiamato config.xml che si trova nella stessa cartella del jar. Lo scopo del file è, ovviamente, quello di fornire le impostazioni per il jar. Per me è importante che il file xml sia all'esterno dello del file jar per una facile modifica.

Ho difficoltà a caricare quel file. Di Windows esegue la linea

cmd /k java -jar D:\pathToJarfile\unpacker-0.0.1-SNAPSHOT-jar-with-dependencies.jar 

Chiamando il tutto con cmd /k lascia le finestre prompt dei comandi aperta in modo che io possa vedere l'uscita del vaso.

Non posso usare new File(".") o System.getProperty("user.dir") per il percorso relativo come queste funzioni restituiscono C:\Windows\system32\. e C:\Windows\system32, rispettivamente (che è la cartella di lavoro per tutto ciò che le finestre esegue AFAIK).

Non ho avuto alcun successo con Launcher.class.getResourceAsStream("/../config.xml") entrambi. Poiché il percorso inizia con /, la ricerca inizia dal nodo radice del jar. Andando a ../config.xml puntare esattamente a quel file, ma la chiamata restituisce null.

Qualcuno può indicarmi la giusta direzione? Sono davvero bloccato qui. Questa roba caricamento del file ogni volta che mi davvero bug ...

Requisiti per me stesso:

  • Non voglio hardcoded il percorso nel codice sorgente Java
  • non voglio passare il il percorso del file come parametro alla chiamata java -jar (né come param alla main(String[] args) né utilizzando -Dpath=d:\... per impostare una proprietà di sistema)

Oltre al problema originale, ho avuto difficoltà ad avere Maven2 nella posizione Class-Path: . nella MANIFEST.MF (la soluzione che BalusC ha pubblicato) quando si utilizza jar-with-dependencies. Il problema era che la riga appariva nel file MANIFEST del normale jar, ma non nel file MANIFEST di jar-with-dependencies.jar (vengono generati 2 file jar). Per chiunque abbia a cuore come ho fatto:

<plugin> 
    <artifactId>maven-assembly-plugin</artifactId> 
    <version>2.2-beta-5</version> 
    <configuration> 
     <archive> 
     <manifest> 
      <mainClass>${mainClass}</mainClass> 
      <addClasspath>true</addClasspath> 
      <!--at first, i tried to place the Class-Path entry 
       right here using <manifestEntries>. see below --> 
     </manifest> 
     </archive> 
     <descriptorRefs> 
     <descriptorRef>jar-with-dependencies</descriptorRef> 
     </descriptorRefs> 
    </configuration> 
    <executions> 
     <execution> 
     <goals> 
      <goal>attached</goal> 
     </goals> 
     <phase>package</phase> 
     <configuration> 
      <descriptorRefs> 
      <descriptorRef>jar-with-dependencies</descriptorRef> 
      </descriptorRefs> 
      <archive> 
      <manifest> 
       <mainClass>${mainClass}</mainClass> 
      </manifest> 
      <!--this is the correct placement --> 
      <manifestEntries> 
       <Class-Path>.</Class-Path> 
      </manifestEntries> 
      </archive> 
     </configuration> 
     </execution> 
    </executions> 
    </plugin> 

risposta

6

Per arrivare Launcher.class.getResourceAsStream("/../config.xml") a lavorare, è necessario aggiungere il suo percorso alla Class-Path ingresso del fascicolo della JAR MANIFEST.MF. Questa è la pratica normale.

+1

suoni più belli :-) –

+0

Devo posizionare il percorso assoluto nel 'MANIFEST.MF' o '..' è sufficiente? Quest'ultimo sarebbe auspicabile. Scusami per aver chiesto invece di provare, non ho il mio IDE su questa macchina. – f1sh

+1

No, il percorso relativo al file JAR stesso. Se vuoi avere il 'config.xml' nella stessa cartella del file JAR stesso, allora' Class-Path: .' è sufficiente (non dimenticare di aggiungere una riga vuota alla fine di 'MANIFEST.MF'!) . Quindi puoi ottenere 'config.xml' da' getResourceAsStream ("config.xml") '. Rendilo semplice :) – BalusC

11

Ecco una possibile soluzione usando Class.getProtectionDomain():

final Class<?> referenceClass = YourMainClass.class; 
final URL url = 
    referenceClass.getProtectionDomain().getCodeSource().getLocation(); 

try{ 
    final File jarPath = new File(url.toURI()).getParentFile(); 
    System.out.println(jarPath); // this is the path you want 
} catch(final URISyntaxException e){ 
    // etc. 
} 

YourMainClass può essere sostituito da qualsiasi classe nel vostro vaso.


Dalle Class.getProtectionDomain() documentazione:

Returns the ProtectionDomain of this class. 
If there is a security manager installed, this method first calls 
the security manager's checkPermission method with a 
RuntimePermission("getProtectionDomain") permission to ensure it's 
ok to get the ProtectionDomain. 

Returns: 
    the ProtectionDomain of this class 
Throws: 
    SecurityException - if a security manager exists and its 
    checkPermission method doesn't allow getting the ProtectionDomain. 
+1

Questo è davvero bello sapere nel caso in cui avrò bisogno del percorso nel codice. Al momento non lo faccio, quindi cercherò di usare la risposta di BalusC. – f1sh

Problemi correlati