2011-03-04 13 views
68

Come posso utilizzare ClassLoader.getResources() per trovare risorse ricorsivamente dal mio classpath?Come utilizzare ClassLoader.getResources() correttamente?

E.g.

  • trovare tutte le risorse nella "directory" META-INF: Immaginate qualcosa di simile

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

    Purtroppo, questo non recupera solo URL esattamente questo "directory".

  • tutte le risorse di nome bla.xml (recursivly)

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

    Ma questo restituisce un vuoto Enumeration.

E come una questione bonus: Come si fa ClassLoader.getResources() differiscono da ClassLoader.getResource()?

+12

@Andrew, un sacco di quadri iterare per alcuni file basati su nomi o estensioni negli archivi per automatizzare alcuni processi, come trovare ActionBeans of Stripes oi file hbm.xml per la sospensione. – bestsss

+2

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

+0

Il motivo per cui si confonde è che getResources funziona su un caricatore di classe che può avere più JAR nel classpath. Quindi se hai più JAR con la stessa risorsa, ottieni tutto. Tuttavia NON è destinato a cercare all'interno delle directory. Con getResources ("META-INF") si ottengono tutte le directory META-INFO nel percorso di ricerca del CL e se il CL è un caricatore di classi di file jar singolo, al massimo si ottiene una voce. – eckes

risposta

18

Non è possibile cercare in modo ricorsivo nel classpath. È necessario conoscere il percorso completo di una risorsa per poterlo recuperare in questo modo. La risorsa può trovarsi in una directory nel file system o in un file jar, quindi non è così semplice come eseguire un elenco di directory di "classpath". Dovrai fornire il percorso completo della risorsa, ad es. '/com/mypath/bla.xml'.

Per la seconda domanda, getResource restituirà la prima risorsa che corrisponde al nome di risorsa specificato. L'ordine di ricerca del percorso della classe è the javadoc for getResource.

+11

* Non c'è modo di cercare ricorsivamente attraverso il classpath * ... Certo, è possibile. Ad esempio: 'URLClassLoader.getURLs()'. Apri il file Jar, esegui l'iterazione. – bestsss

+3

@bestsss: cosa succede se l'URL non punta a un JarFile, ma a una directory? – MRalwasser

+6

@bestsss, @MRalwasser: o peggio ancora, se punta a un url HTTP? –

5

MRalwasser, vorrei darti un suggerimento, trasmettere lo URL.getConnection() allo JarURLConnection. Quindi utilizzare JarURLConnection.getJarFile() e voilà! Hai il JarFile e sei libero di accedere alle risorse interne.

Il resto vi lascio.

Spero che questo aiuti!

+0

Cosa intendi con 'URL.getConnection()'? Non riesco a trovare questo metodo comunque. – m0skit0

15

Questo è il wat più semplice per ottenere l'oggetto del file a cui un determinato oggetto URL sta indicando:

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

Ora, per le vostre domande concrete:

  • trovare tutte le risorse in la "directory" META-INF:

È possibile inde Ed ottenere il puntamento oggetto File a questo 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(); 
} 
  • tutte le risorse di nome bla.xml (recursivly)

In questo caso, dovrete fare un po 'di codice personalizzato. Ecco un esempio fittizio:

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

Quando viene eseguito il codice, avrai tutte le occorrenze trovate la lista foundFiles.

+9

Dubito che questo funzionerà in ogni caso per ogni tipo di ClassLoaders (ad esempio classi all'interno di jar-file) – MRalwasser

+23

Ho testato, ottengo un'eccezione: java.lang.IllegalArgumentException: URI non è gerarchico. Non è possibile creare un oggetto File da un URI opaco come "jar: ..." – cn1h

9

Ecco il codice in base alla risposta 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

La struttura di questo tipo di mi ha confuso all'inizio. Sembra che l'unico scopo di getClass(). GetClassLoader(). GetResources ("META-INF") è ottenere un riferimento ad un file arbitrario nel jar, che useremo per ottenere JarURLConnection. Inizialmente pensavo che questo avrebbe iterato sui file nella directory META-INF, ma in realtà itera su ogni singolo file nell'intero jar. –

+0

Non funziona per me. Mostra solo il contenuto del primo file jar 'J' nel percorso della classe in modo tale che' J' contenga una voce che inizia con il 'percorso' dato al metodo' getResources (percorso) '. Quindi, il risultato dello snippet di codice è incompleto e dipende dall'ordine degli elementi nel percorso della classe. Quindi, @krock aveva ragione quando diceva che _Non c'è modo di cercare ricorsivamente attraverso il classpath_ – Readren

31

La Spring Framework ha una classe che consente di ricercare in modo ricorsivo attraverso il percorso di classe:

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

Se stai provando a risolvere le risorse all'interno di un barattolo, e non sei sicuro di come dovrebbe apparire il pattern, esegui 'jar tf myjar.jar'. Ho finito con 'PathMatchinResourcePatternResolver (" definizioni/**/*. Json ")'. – MatrixManAtYrService

Problemi correlati