2010-11-18 2 views
10

классов Любых предложений относительно того, как подойти, как бы я узнать список имен пакетов , которые существуют на токе классов?Java: программно определить все имена пакетов, загруженных на

Это должно быть сделано программно во время выполнения одним из классов, загруженных (и выполняющихся) в пути к классам (то есть наизнанку, а не снаружи).


Подробнее:

Один подход я считал, чтобы использовать отражение в каждом из классов, загруженных до настоящего времени загрузчик классов, и извлекать имена пакетов из них. Однако мое приложение уже запускается в тысячи классов, поэтому мне нужен более эффективный подход.

Еще одна вещь, которую я рассматривал, была чем-то аналогичным тому, чтобы узнать, какие файлы JAR были в пути к классу, а затем сделать список каталогов параллельным для каждого JAR. Однако я не знаю, возможно ли это из приложения/как это сделать.

Бонусные баллы

Бонусные баллы для тех, кто предполагает путь, который может фильтровать пакеты на высшем уровне. Например. показать все упаковки, которые подпадают под com.xyz ==>com.xyz.*, com.xyz.*.*

Спасибо!

ответ

6

Если вам нужно смонтировать и сканировать файлы jar, то commons-vfs имеет этот встроенный модуль. Это может сделать вещи немного проще, если вам нужно пройти этот маршрут.

EDIT # 1: Вы можете получить так, как путь к классам (из примера here):

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

Оттуда вы можете посмотреть на локальных классов файловой системы, банки и т.д.

EDIT # 2: Вот решение с 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

Я знаю VFS, но не знаю об этой функциональности. Не могли бы вы дать подсказку, какой класс помогает сканировать путь к классам? – AlexR

3

Дайте http://code.google.com/p/reflections/ выстрел.

Размышление сканирует, пути к классам индексируют метаданные, позволяет запрашивать у него на время выполнения и может сохранять и собирать эту информацию для многих модулей в рамках вашего проекта.

2

Этот код даст вам все пути к классам-записи (в том числе библиотеки JRE):

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

ClassPath является частью апача BCEL и может быть найден как внутренний (но пригодном) класса в JRE (com.sun.org.apache.bcel.internal.util). AFAIK, класс является «внутренним», чтобы избежать конфликтов, когда проект требует «реальной» библиотеки bcel.

Вы можете фильтровать библиотеки в JRE (они включены в это реальный классам)

Следующим шагом будет смотреть на каждую запись (JarFile-), посетить все подкаталоги (рекурсивно), и если (и только если) каталог содержит по крайней мере один файл класса, имя этого каталога (относительно записи пути к классу) можно преобразовать в имя пакета (например: META_INF - это каталог во всех файлах jar, но не название пакета ...)