Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Any suggestions as to how to approach how I would find out a list of package names that exist on the current classpath?

This needs to be done programmatically at run time by one of the classes loaded (and executing) on the classpath (i.e. inside out, not outside in).


More details:

One approach I considered was to use reflection on each of the classes loaded thus far by the class loader, and extract the package names from them. However, my application already runs into thousands of classes, so I need a more efficient approach.

Another thing I considered was something analogous to finding out what JAR files were in the class path, and then do the directory listing parallel for each JAR. However, I don't know if this is possible from within the application/ how to do it.

Bonus points

Bonus points for anyone who suggests a way that can filter by top-level packages. E.g. show all packages that come under com.xyz ==> com.xyz.*, com.xyz.*.*

Thanks!

like image 221
bguiz Avatar asked Nov 18 '10 06:11

bguiz


People also ask

How do I get all classes in a ClassPath?

E.g. to get all classes in a particular package: ClassLoader cl = getClass(). getClassLoader(); Set<ClassPath. ClassInfo> classesInPackage = ClassPath.

How can you directly access all classes in the packages in Java?

1) Using packagename.* If you use package.* then all the classes and interfaces of this package will be accessible but not subpackages. The import keyword is used to make the classes and interface of another package accessible to the current package.

What is the package name of class?

The package for a class can be obtained using the java. lang. Class. getPackage() method with the help of the class loader of the class.

How do I get Java packages?

If you want a list of packages in the standard installation, just go to the Javadocs and look in the upper left corner. If you want to see the . class files, they're in lib\rt. jar in the JRE directory ( .


2 Answers

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 );
                }
            }
        }
    }
}
like image 85
javamonkey79 Avatar answered Oct 12 '22 23:10

javamonkey79


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.

like image 36
Mike Samuel Avatar answered Oct 13 '22 01:10

Mike Samuel