lunes, 8 de enero de 2018

Java: Localizar la carpeta que incluye a un proyecto java o a un jar

Lo que voy a decir es un pequeño resumen de lo que se ha comentado en StackOverflow.


Primeramente veamos algunas de las posibilidades manejadas:

1. System.getProperty("user.dir")

En este caso nos indica el directorio donde estamos ahora. Poe ejemplo si estamos en /home/ximo y ejecutamos en la consola : java -jar ./misAplicaciones/aplicacion01.jar , el resultado será /home/ximo y no donde está la aplicación. Por tanto puede ser problemático.


2.  System.getProperty("java.class.path")

Aquí nos indica cada una de las rutas para localizar los jars utilizados. Por tanto a bote pronto, creo que no nos puede servir mucho.

3. La mayor parte de las opciones parten de localizar una clase, y a partir de esta localización ya se busca lo que se quiere. Para obtener la clase desde un método no estático basta con:

    this.getClass()

Pero si estamos en un método estático , las soluciones aportadas en StackOverflow son:


  • MyClass.class(): Permite refactorización, es la más rápida pero no funciona con copia y pega entre 2 clases.
  • MethodHandles.lookup().lookupClass(): Desde Java 7. Parece ser la mejor alternativa, ya que aunque no es tan rápida como la anterior, si permite copia y pega. A continuación ser detallan otras alternativas (para obtener el nombre de la clases) pero su rendimiento puede dar mucho que desear:
  • new Object() { }.getClass().getEnclosingClass().getName();
  • Thread.currentThread().getStackTrace()[1].getClassName();
  • System.getSecurityManager().getClassContext()[0].getName();


4. Si estamos en un jar, se puede obtener la carpeta que contiene el jar, a partir de nuestra clase de esta forma:

   CodeSource codeSource = aClass.getProtectionDomain().getCodeSource();
    File jarFile;
    jarFile = new File(codeSource.getLocation().toURI());
    String s=jarFile.getParentFile().getAbsolutePath();

5. Si estamos en un proyecto MAVEN y ejecutamos un main dentro de Eclipse, hay que tener en cuenta que las clase se guardan en el directorio target y por tanto para obtener la carpeta que incluye a la carpeta que es nuestro proyecto, tenemos que subir 2 veces en el árbol de directorios:

    String path = aClass.getResource(aClass.getSimpleName() + ".class").getPath();
    String jarFilePath = path.substring(path.indexOf(":") + 1, path.indexOf("!"));
    jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
    jarFile = new File(jarFilePath);
    String s=jarFile.getParentFile().getAbsolutePath();
    if (s.endsWith(File.separator+"target")) { // Maven target directory for 
                                               // compiled classes
s=s.substring(0, s.lastIndexOf(File.separator));
s=s.substring(0, s.lastIndexOf(File.separator));
    }

Finalmente si creamos una clase de utilidades nos queda:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package ximodante.utils;

import java.io.File;
import java.lang.invoke.MethodHandles;
import java.net.URLDecoder;
import java.security.CodeSource;

public class FileUtils {

 /**
  * Folder that contains jar file or folder that contains project folder
  * @return
  * @throws Exception
  */
 public static String getJarContainingFolder() throws Exception {
  Class<?> aClass=MethodHandles.lookup().lookupClass();
  CodeSource codeSource = aClass.getProtectionDomain().getCodeSource();

  File jarFile;

  if (codeSource.getLocation() != null) {
   jarFile = new File(codeSource.getLocation().toURI());
  } else { // It is not a Jar file 
   String path = aClass.getResource(aClass.getSimpleName() + ".class").getPath();
      String jarFilePath = path.substring(path.indexOf(":") + 1, path.indexOf("!"));
      jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
      jarFile = new File(jarFilePath);
  }
  String s=jarFile.getParentFile().getAbsolutePath();
  System.out.println("S------>:" + s);
  if (s.endsWith(File.separator+"target")) { // Maven target directory for compiled classes
   s=s.substring(0, s.lastIndexOf(File.separator));
   s=s.substring(0, s.lastIndexOf(File.separator));
  } 
  return s;
 }
 
 /**
  * test in main class
  * @param args
  */
 public static void main(String[] args) {
  try {
   System.out.println(getJarContainingFolder());
   System.out.println(System.getProperty("java.class.path"));
   System.out.println(System.getProperty("user.dir"));
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

 }

}


No hay comentarios :

Publicar un comentario