2012-06-06 11 views
8

Ho bisogno di una classe [] di tutti i file di classe contenuti in uno dei miei pacchetti sorgente in Java.Ottenere una serie di file di classe all'interno di un pacchetto in Java

Non sono riuscito a trovare un metodo standard per farlo in un solo colpo. Se qualcuno può scrivere una funzione per recuperare quella lista sarebbe davvero utile.

Class[] myClasses = yourfunction(); // Return a list of class inside a source package in the currently working project in java 
+0

Non esiste un modo standard per enumerare tutte le classi in un determinato pacchetto. In alcuni casi non è nemmeno possibile (si pensi a un URLClassLoader che carica le classi da un URL HTTP: non esiste un modo standardizzato per enumerare i file in una cartella). –

+1

Vedi qui per una soluzione manuale (non è infallibile) - http://stackoverflow.com/questions/176527/how-can-i-enumerate-all-classes-in-a-package-and-add-them- to-a-list – Perception

risposta

7

Sono in grado di risolvere questo problema utilizzando il normale file I/O e il meccanismo di ricerca. Puoi controllare la risposta come postata qui.

private static List<Class> getClassesForPackage(Package pkg) { 
    String pkgname = pkg.getName(); 

    List<Class> classes = new ArrayList<Class>(); 

    // Get a File object for the package 
    File directory = null; 
    String fullPath; 
    String relPath = pkgname.replace('.', '/'); 

    //System.out.println("ClassDiscovery: Package: " + pkgname + " becomes Path:" + relPath); 

    URL resource = ClassLoader.getSystemClassLoader().getResource(relPath); 

    //System.out.println("ClassDiscovery: Resource = " + resource); 
    if (resource == null) { 
     throw new RuntimeException("No resource for " + relPath); 
    } 
    fullPath = resource.getFile(); 
    //System.out.println("ClassDiscovery: FullPath = " + resource); 

    try { 
     directory = new File(resource.toURI()); 
    } catch (URISyntaxException e) { 
     throw new RuntimeException(pkgname + " (" + resource + ") does not appear to be a valid URL/URI. Strange, since we got it from the system...", e); 
    } catch (IllegalArgumentException e) { 
     directory = null; 
    } 
    //System.out.println("ClassDiscovery: Directory = " + directory); 

    if (directory != null && directory.exists()) { 

     // Get the list of the files contained in the package 
     String[] files = directory.list(); 
     for (int i = 0; i < files.length; i++) { 

      // we are only interested in .class files 
      if (files[i].endsWith(".class")) { 

       // removes the .class extension 
       String className = pkgname + '.' + files[i].substring(0, files[i].length() - 6); 

       //System.out.println("ClassDiscovery: className = " + className); 

       try { 
        classes.add(Class.forName(className)); 
       } catch (ClassNotFoundException e) { 
        throw new RuntimeException("ClassNotFoundException loading " + className); 
       } 
      } 
     } 
    } else { 
     try { 
      String jarPath = fullPath.replaceFirst("[.]jar[!].*", ".jar").replaceFirst("file:", ""); 
      JarFile jarFile = new JarFile(jarPath); 
      Enumeration<JarEntry> entries = jarFile.entries(); 
      while (entries.hasMoreElements()) { 
       JarEntry entry = entries.nextElement(); 
       String entryName = entry.getName(); 
       if (entryName.startsWith(relPath) && entryName.length() > (relPath.length() + "/".length())) { 

        //System.out.println("ClassDiscovery: JarEntry: " + entryName); 
        String className = entryName.replace('/', '.').replace('\\', '.').replace(".class", ""); 

        //System.out.println("ClassDiscovery: className = " + className); 
        try { 
         classes.add(Class.forName(className)); 
        } catch (ClassNotFoundException e) { 
         throw new RuntimeException("ClassNotFoundException loading " + className); 
        } 
       } 
      } 
     } catch (IOException e) { 
      throw new RuntimeException(pkgname + " (" + directory + ") does not appear to be a valid package", e); 
     } 
    } 
    return classes; 
} 
+4

Così grande, ci deve essere un modo più semplice ... – Illidanek

+0

@Illidanek ya puoi sicuramente ridurre alcune linee di codice da questo codice e potrebbe anche esistere una soluzione migliore, anche io vorrei vedere alcuni più brevi e codice più efficiente che fa lo stesso lavoro. – AurA

+0

Una buona risposta ... ha risparmiato molto tempo –

3

Non provate questo su tutte le macchine virtuali, ma in un recente Oracle VM c'è un modo più breve:

Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources("package/name/with/slashes/instead/dots"); 
    while (resources.hasMoreElements()) { 
     URL url = resources.nextElement(); 
     System.out.println(url); 
     System.out.println(new Scanner((InputStream) url.getContent()).useDelimiter("\\A").next()); 
    } 

Questo stamperà i nomi delle risorse nel pacchetto, in modo da poter utilizzare getResource(...) su di loro. La chiamata url.getContent() restituirà un'istanza di sun.net.www.content.text.PlainTextInputStream che è una classe VM specifica.

+2

Questo non funziona con jar in jdk 1.8. 'sun.net.www.protocol.jar.JarURLConnection $ JarURLInputStream' lancia NPE nel tentativo di leggere da esso. – Vadzim

Problemi correlati