2010-11-18 9 views
10

Eventuali suggerimenti su come avvicinarsi quanto avrei trovato un elenco di nomi di pacchetti che esiste sul classpath corrente?Java: programmazione di determinare tutti i nomi dei pacchetti caricati sul classpath

Questo deve essere eseguito a livello di programmazione in fase di esecuzione da una delle classi caricate (ed eseguite) sul classpath (ad esempio all'interno di, non all'esterno in).


Maggiori dettagli:

Un approccio ho considerato è stato quello di utilizzare la riflessione su ciascuna delle classi caricate finora dal caricatore di classe, ed estrarre i nomi dei pacchetti da loro. Tuttavia, la mia applicazione gira già in migliaia di classi, quindi ho bisogno di un approccio più efficiente.

Un'altra cosa che ho considerato era qualcosa di analogo a scoprire quali file JAR fossero nel percorso classe e quindi fare la directory che elenca paralleli per ogni JAR. Tuttavia, non so se questo è possibile dall'interno dell'applicazione/come farlo.

punti bonus

punti bonus per chiunque suggerisce un modo che può filtrare da pacchetti di alto livello. Per esempio. mostra tutti i pacchetti sotto com.xyz ==>com.xyz.*, com.xyz.*.*

Grazie!

risposta

6

Se è necessario montare e scansionare i file jar commons-vfs ha incorporato questo. Ciò potrebbe rendere le cose un po 'più semplici se si deve seguire questa strada.

EDIT # 1: È possibile ottenere il percorso di classe in questo modo (dall'esempio here):

String strClassPath = System.getProperty("java.class.path"); 
System.out.println("Classpath is " + strClassPath); 

Da lì si può guardare le classi di file system locali, barattoli, ecc

EDIT # 2: Ecco una soluzione con VFS:

import java.util.HashSet; 

import org.apache.commons.lang.StringUtils; 
import org.apache.commons.vfs.FileObject; 
import org.apache.commons.vfs.FileSystemManager; 
import org.apache.commons.vfs.FileType; 
import org.apache.commons.vfs.VFS; 

public class PackageLister { 

    private static HashSet<String> packageNames = new HashSet<String>(); 
    private static String localFilePath; 

    /** 
    * @param args 
    * @throws Throwable 
    */ 
    public static void main(final String[] args) throws Throwable { 
     FileSystemManager fileSystemManager = VFS.getManager(); 

     String[] pathElements = System.getProperty("java.class.path").split(";"); 
     for(String element : pathElements) { 
      if (element.endsWith("jar")) { 
       FileObject fileObject = fileSystemManager.resolveFile("jar://" + element); 
       addPackages(fileObject); 
      } 
      else { 
       FileObject fileObject = fileSystemManager.resolveFile(element); 
       localFilePath = fileObject.getName().getPath(); 

       addPackages(fileObject); 
      } 
     } 

     for(String name : packageNames) { 
      System.out.println(name); 
     } 
    } 

    private static void addPackages(final FileObject fileObject) throws Throwable { 
     FileObject[] children = fileObject.getChildren(); 
     for(FileObject child : children) { 
      if (!child.getName().getBaseName().equals("META-INF")) { 
       if (child.getType() == FileType.FOLDER) { 
        addPackages(child); 
       } 
       else if (child.getName().getExtension().equals("class")) { 
        String parentPath = child.getParent().getName().getPath(); 
        parentPath = StringUtils.remove(parentPath, localFilePath); 
        parentPath = StringUtils.removeStart(parentPath, "/"); 
        parentPath = parentPath.replaceAll("/", "."); 

        packageNames.add(parentPath); 
       } 
      } 
     } 
    } 
} 
+0

Conosco VFS ma non conoscevo questa funzionalità. Potresti dare un suggerimento su quale classe aiuta a scannerizzare il classpath? – AlexR

3

Dare http://code.google.com/p/reflections/ un colpo.

Riflessioni scansiona classpath, indici i metadati, si permette di interrogazione su runtime e può salvare e raccogliere tali dati, per molti moduli all'interno del progetto.

2

Questo codice vi darà tutte le classpath-voci (tra cui le librerie JRE):

String[] entries = ClassPath.getClassPath().split(";"); 
for (String entry:entries) 
    System.out.println(entry); 

ClassPath fa parte di apache BCEL e può essere trovato in una classe interna (ma utilizzabile) in JRE (com.sun.org.apache.bcel.internal.util). AFAIK, la classe è "interna" per evitare conflitti quando un progetto richiede la "vera" libreria bcel.

Si consiglia di filtrare le biblioteche del JRE (sono inclusi in quanto questo è il vero classpath)

Il passo successivo sarebbe guardando ogni voce (JarFile-), visitare tutte le sottodirectory (in modo ricorsivo) e se (e solo se) una directory contiene almeno un file di classe, il nome di questa directory (relativo alla voce classpath) può essere convertito in un nome pacchetto (esempio: META_INF è una directory in tutti i file jar ma non un nome di pacchetto ...)

Problemi correlati