2010-09-02 8 views
12

La question dit tout. La spécialité dans mon cas est que le répertoire de travail actuel n'est pas l'emplacement du fichier jar mais c:\Windows\system32 (Mon fichier jar est démarré par windows en utilisant le menu contextuel, je veux passer le chemin d'un dossier en tant que paramètre au pot).Chargement d'un fichier relatif au fichier jar en cours d'exécution

Maintenant, je veux charger un fichier de configuration appelé config.xml qui se trouve dans le même dossier que le fichier jar. Le but du fichier est, bien sûr, de fournir des paramètres pour le pot. Il est important pour moi que le fichier xml soit en dehors de du fichier jar pour faciliter l'édition.

J'ai du mal à charger ce fichier. Windows exécute la ligne

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

L'appel de la chose entière avec cmd /k laisse les fenêtres invite de commande ouverte afin que je puisse voir la sortie du pot.

Je ne peux pas utiliser new File(".") ou System.getProperty("user.dir") pour le chemin relatif, car ces fonctions renvoient C:\Windows\system32\. et C:\Windows\system32, respectivement (ce qui est le dossier de travail pour tout ce que les fenêtres exécute AFAIK).

Je n'ai pas eu de succès avec Launcher.class.getResourceAsStream("/../config.xml") non plus. Puisque ce chemin commence par /, la recherche commence au nœud racine du pot. Aller à ../config.xml point exactement à ce fichier, mais l'appel renvoie null.

Quelqu'un peut-il me diriger dans la bonne direction? Je suis vraiment coincé ici. Ce fichier stuff chargement vraiment me tracasse chaque fois ...

Exigences de moi-même:

  • Je ne veux pas coder en dur le chemin dans le code source java
  • Je ne veux pas passer la chemin de fichier en tant que paramètre à l'appel java -jar (ni comme au main(String[] args) param ni en utilisant -Dpath=d:\... pour définir une propriété système)

En plus du problème original, j'ai eu du mal à avoir maven2 place Class-Path: . dans le MANIFEST.MF (La solution que BalusC a publié) lors de l'utilisation jar-with-dependencies. Le problème était que la ligne apparaissait dans le fichier MANIFEST du fichier jar, mais pas dans le fichier MANIFEST de jar-with-dependencies.jar (2 fichiers jar sont générés). Pour tous ceux qui se soucie comment je l'ai fait:

<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> 

Répondre

6

Pour obtenir Launcher.class.getResourceAsStream("/../config.xml") au travail, vous devez ajouter son chemin à l'entrée Class-Path du fichier MANIFEST.MF du JAR. C'est la pratique normale.

+1

semble plus joli :-) –

+0

Dois-je placer le chemin absolu dans le fichier 'MANIFEST.MF' ou est-ce que' ..' suffit? Ce dernier serait souhaitable. Désolé de demander au lieu d'essayer, je n'ai pas mon IDE sur cette machine. – f1sh

+1

Non, le chemin relatif au fichier JAR lui-même. Si vous voulez avoir le 'config.xml' dans le même dossier que le fichier JAR lui-même, alors" Class-Path:. "Suffit (n'oubliez pas d'ajouter une ligne vide à la fin de' MANIFEST.MF'!) . Ensuite, vous pouvez obtenir 'config.xml' par' getResourceAsStream ("config.xml") '. Keep it simple :) – BalusC

11

Voici une solution possible en utilisant 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 peut être remplacée par une classe dans votre pot.


Des Class.getProtectionDomain() docs:

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

C'est vraiment bon à savoir au cas où j'aurais besoin du chemin dans le code. Actuellement, je ne le fais pas, alors je vais essayer d'utiliser la réponse de BalusC. – f1sh