Java : programmatically determine all of the package names loaded on the classpath

会有一股神秘感。 提交于 2019-12-01 03:19:01

If you do need to mount and scan jar files commons-vfs has this built in. That might make things a little easier if you have to go that route.

EDIT #1: You can get the classpath like so (from the example here):

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

From there you can look at the local file system classes, jars, etc.

EDIT #2: Here is a solution with 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 );
                }
            }
        }
    }
}

Give http://code.google.com/p/reflections/ a shot.

Reflections scans your classpath, indexes the metadata, allows you to query it on runtime and may save and collect that information for many modules within your project.

This code will give you all classpath-entries (including the jre libraries):

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

ClassPath is part of apache bcel and can be found as an internal (but usable) class in the jre (com.sun.org.apache.bcel.internal.util). AFAIK, the class is "internal" to avoid conflicts when a project requires the "real" bcel library.

You may want to filter the libraries of the JRE (they're included as this is the real classpath)

The next step would be looking at each (JarFile-)entry, visit all subdirectories (recursivly) and if (and only if) a directory contains at least one class file, the name of this directory (relative to the classpath entry) can be converted to a package name (example: META_INF is a directory in all jar files but not a package name...)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!