2011-03-04 10 views
68

¿Cómo puedo usar ClassLoader.getResources() para encontrar recursos recursivos de mi classpath?Cómo usar ClassLoader.getResources() correctamente?

E.g.

  • encontrar todos los recursos del "directorio" META-INF: imaginar algo como

    getClass().getClassLoader().getResources("META-INF")

    Por desgracia, esto no solamente recuperar un URL a exactamente este "directorio".

  • todos los recursos con nombre bla.xml (recursivamente)

    getClass().getClassLoader().getResources("bla.xml")

    Pero esto devuelve un vacío Enumeration.

Y como una pregunta extra: ¿Cómo se diferencian de ClassLoader.getResources()ClassLoader.getResource()?

+12

@ Andrew, una gran cantidad de marcos para iterar algunos archivos basados ​​en nombre o extensiones en los archivos para automatizar algunos procesos, como encontrar los ActionBeans de Stripes o los archivos hbm.xml para hibernar. – bestsss

+2

Ver http://stackoverflow.com/questions/1429172/how-do-i-list-the-files-inside-a-jar-file/ – Vadzim

+0

El motivo por el que te confunde es que getResources funciona en un cargador de clases que puede tener varios JAR en el classpath. Entonces, si tienes varios JAR con el mismo recurso, obtienes todo. Sin embargo, NO está destinado a buscar dentro de directorios. Con getResources ("META-INF") obtienes todos los directorios META-INFO en la ruta de búsqueda de la CL y si CL es un solo cargador de clases de archivos jar, a lo sumo obtienes una entrada. – eckes

Respuesta

18

No hay forma de buscar recursivamente a través del classpath. Necesita saber la ruta de acceso completa de un recurso para poder recuperarlo de esta manera. El recurso puede estar en un directorio en el sistema de archivos o en un archivo jar, por lo que no es tan simple como realizar una lista de directorios de "classpath". Deberá proporcionar la ruta completa del recurso, p. '/com/mypath/bla.xml'.

Para su segunda pregunta, getResource devolverá el primer recurso que coincida con el nombre del recurso proporcionado. El orden en el que se busca la ruta de clase se da en the javadoc for getResource.

+11

* No hay forma de buscar recursivamente a través del classpath * ... Claro, es posible. Por ejemplo: 'URLClassLoader.getURLs()'. Abra el JarFile, itere a través de. – bestsss

+3

@bestsss: ¿y si la URL no apunta a JarFile, sino a un directorio? – MRalwasser

+6

@bestsss, @MRalwasser: ¿o peor, si apunta a una url de HTTP? –

5

MRalwasser, le doy una pista, envíe el URL.getConnection() al JarURLConnection. Luego use JarURLConnection.getJarFile() y listo! Usted tiene JarFile y puede acceder a los recursos internos.

El resto te dejo.

Espero que esto ayude!

+0

¿Qué quiere decir con 'URL.getConnection()'? No puedo encontrar este método de todos modos. – m0skit0

15

Este es el wat más sencilla de obtener el objeto de archivo en el que un determinado objeto URL está apuntando a:

File file=new File(url.toURI()); 

Ahora, para sus preguntas concretas:

  • encontrar todos los recursos el "directorio" META-INF:

Puede inde ed obtener el objeto File que apunta a esta URL

Enumeration<URL> en=getClass().getClassLoader().getResources("META-INF"); 
if (en.hasMoreElements()) { 
    URL metaInf=en.nextElement(); 
    File fileMetaInf=new File(metaInf.toURI()); 

    File[] files=fileMetaInf.listFiles(); 
    //or 
    String[] filenames=fileMetaInf.list(); 
} 
  • todos los recursos con nombre bla.xml (recursivamente)

En este caso, tendrá que hacer algún código personalizado. Aquí está un ejemplo ficticio:

final List<File> foundFiles=new ArrayList<File>(); 

FileFilter customFilter=new FileFilter() { 
    @Override 
    public boolean accept(File pathname) { 

     if(pathname.isDirectory()) { 
      pathname.listFiles(this); 
     } 
     if(pathname.getName().endsWith("bla.xml")) { 
      foundFiles.add(pathname); 
      return true; 
     } 
     return false; 
    } 

};  
//rootFolder here represents a File Object pointing the root forlder of your search 
rootFolder.listFiles(customFilter); 

Cuando se ejecuta el código, obtendrá todas las ocurrencias que se encuentran en la Lista de foundFiles.

+9

Dudo que esto funcione en ningún caso para cada tipo de ClassLoaders (por ejemplo, clases dentro de archivos jar) – MRalwasser

+23

Probé, obtengo una excepción: java.lang.IllegalArgumentException: URI no es jerárquico. No se puede crear un objeto File desde un URI opaco como "jar: ..." – cn1h

9

Aquí está basada en un código de respuesta bestsss':

Enumeration<URL> en = getClass().getClassLoader().getResources(
      "META-INF"); 
    List<String> profiles = new ArrayList<>(); 
    if (en.hasMoreElements()) { 
     URL url = en.nextElement(); 
     JarURLConnection urlcon = (JarURLConnection) (url.openConnection()); 
     try (JarFile jar = urlcon.getJarFile();) { 
      Enumeration<JarEntry> entries = jar.entries(); 
      while (entries.hasMoreElements()) { 
       String entry = entries.nextElement().getName(); 
       System.out.println(entry); 
      } 
     } 
    } 
+2

Al principio, la estructura de este tipo me confundió. Parece como si el único propósito de getClass(). GetClassLoader(). GetResources ("META-INF") es obtener una referencia a algún archivo arbitrario en el jar, que luego usamos para obtener el JarURLConnection. Originalmente pensé que esto iteraría sobre los archivos en el directorio META-INF, pero realmente itera sobre cada archivo en el contenedor completo. –

+0

No funciona para mí. Muestra solo el contenido del primer archivo jar 'J' en la ruta de la clase, de modo que' J' contiene una entrada que comienza con el método 'path' dado a' getResources (path) '. Por lo tanto, el resultado de su fragmento de código es incompleto y depende del orden de los elementos en la ruta de la clase. Entonces, @krock tenía razón cuando dijo que _No hay forma de buscar recursivamente a través del classpath_ – Readren

31

El Spring Framework tiene una clase que permite buscar de forma recursiva a través de la ruta de clases:

PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 
resolver.getResources("classpath*:some/package/name/**/*.xml"); 
+0

Si está tratando de resolver los recursos dentro de un jar, y no está seguro de cómo debería verse el patrón, ejecute 'jar tf myjar.jar'. Terminé con 'PathMatchinResourcePatternResolver (" definitions/**/*. Json ")'. – MatrixManAtYrService

Cuestiones relacionadas