2010-09-02 23 views
12

La pregunta lo dice todo.Cargando un archivo relacionado con el archivo jar de ejecución

La especialidad en mi caso es que el directorio de trabajo actual no es la ubicación del archivo jar pero c:\Windows\system32 (Mi archivo jar se inicia mediante Windows utilizando el menú contextual, quiero pasar la ruta de una carpeta como parámetro para el contenedor).

Ahora quiero cargar un archivo de configuración llamado config.xml que está en la misma carpeta que el contenedor. El objetivo del archivo es, por supuesto, proporcionar configuraciones para el contenedor. Es importante para mí que el archivo xml sea fuera del del archivo jar para poder editarlo fácilmente.

Tengo dificultades para cargar el archivo. Ventanas ejecuta la línea de

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

Llamando todo el asunto con cmd /k deja las ventanas abiertas símbolo del sistema para que pueda ver la salida de la jarra.

no puedo usar new File(".") o System.getProperty("user.dir") para la ruta relativa ya que estas funciones devuelven C:\Windows\system32\. y C:\Windows\system32, respectivamente (que es la carpeta de trabajo por todo lo que ejecuta Windows yo sepa).

Tampoco he tenido éxito con Launcher.class.getResourceAsStream("/../config.xml"). Como esa ruta comienza con /, la búsqueda comienza en el nodo raíz del contenedor. Ir a ../config.xml apunta exactamente a ese archivo, pero la llamada devuelve null.

¿Puede alguien señalarme en la dirección correcta? Estoy realmente atrapado aquí. Este material de carga de archivos realmente me molesta cada vez que ...

requisitos por mí mismo:

  • no quiero a codificar la ruta en el código fuente de Java
  • que no quieren pasar el ruta de archivo como un parámetro a la llamada java -jar (ni como un parámetro a la main(String[] args) ni usando -Dpath=d:\... para establecer una propiedad del sistema)

Además del problema original, tuve un momento difícil para tener maven2 lugar Class-Path: . en el MANIFEST.MF (La solución que BalusC publicó) al usar jar-with-dependencies. El problema era que la línea aparecía en el archivo MANIFEST del archivo jar normal, pero no en el archivo MANIFEST de jar-with-dependencies.jar (se generan 2 archivos jar). Para cualquier persona que le importa cómo lo hice:

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

Respuesta

6

Para obtener Launcher.class.getResourceAsStream("/../config.xml") a trabajar, es necesario agregar a su paso a la entrada de Class-Path archivo JAR del MANIFEST.MF. Esta es la práctica normal.

+1

suena más bonito :-) –

+0

¿Debo colocar la ruta absoluta en 'MANIFEST.MF' o basta' ..''? Esto último sería deseable. Perdón por preguntar en lugar de intentar, no tengo mi IDE en esta máquina. – f1sh

+1

No, la ruta relativa al archivo JAR en sí. Si desea tener 'config.xml' en la misma carpeta que el archivo JAR, entonces' Class-Path: .' basta (¡no olvide agregar una línea en blanco al final de 'MANIFEST.MF'!) . Luego puede obtener 'config.xml' por' getResourceAsStream ("config.xml") '. Mantenlo simple :) – BalusC

11

Aquí es una solución posible 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 puede ser sustituido por cualquier clase en su frasco.


De los documentos Class.getProtectionDomain():

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

Esto es realmente bueno saber en caso de que necesite la ruta en el código. Actualmente no lo hago, entonces intentaré usar la respuesta de BalusC. – f1sh

Cuestiones relacionadas