Infrastructure at your Service

Middleware Team

Java get Class names from package String in classpath

As a Java developer you probably used to know about reflexion. However, in order to keep your software architecture flexible, some functionalities are sometimes not provided out of the box by the JVM.
In my particular case, I needed to find out every Class and Sub-Classes inside a package, thus reparteed within several Jars.
Internet has lots of solution, but it remains complicated for everybody to reach this goal. After googleing, I found a link which provided a partial solution. I would like to thank the website author:

http://www.java2s.com/Code/Java/Reflection/Attemptstolistalltheclassesinthespecifiedpackageasdeterminedbythecontextclassloader.htm

Some other solution invited us to deploy external libraries as well. But I was not interested to manage another lib in my soft just for that purpose.
So, the solution was to recover all jars from the context classloader and loop on them in order to find out the classes we are looking for.
Following, you will see a complete Java class resolving this issue:

import java.io.File;

import java.io.IOException;

import java.io.UnsupportedEncodingException;

import java.net.URL;

import java.net.URLClassLoader;

import java.net.URLDecoder;

import java.util.ArrayList;

import java.util.Enumeration;

import java.util.HashMap;

import java.util.List;

import java.util.jar.JarEntry;

import java.util.jar.JarFile;

/**

 *

 *

 *

 * @author Philippe Schweitzer dbi services Switzerland

 *

 */

public class ClassFinder {

    public static void main(String[] args) throws ClassNotFoundException {

        List<Class> classes = ClassFinder.getClassesFromPackage(“YOUR PACKAGE NAME”);

        System.out.println(“START ClassList:”);

        for (Class c : classes) {

            System.out.println(c.toString());// + ” ” + c.getCanonicalName());

        }

        System.out.println(“END ClassList:”);

    }

    /**

     *

     * Attempts to list all the classes in the specified package as determined     *

     * by the context class loader…

     *

     * @param pckgname the package name to search

     * @return a list of classes that exist within that package

     * @throws ClassNotFoundException if something went wrong

     *

     */

    public static List getClassesFromPackage(String pckgname) throws ClassNotFoundException {

        ArrayList result = new ArrayList();

        ArrayList<File> directories = new ArrayList();

        HashMap packageNames = null;

        try {

            for (URL jarURL : ((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURLs()) {

                System.out.println(“JAR: ” + jarURL.getPath());

                getClassesInSamePackageFromJar(result, pckgname, jarURL.getPath());

                String path = pckgname;

                Enumeration<URL> resources = cld.getResources(path);

                File directory = null;

                while (resources.hasMoreElements()) {

                    String path2 = resources.nextElement().getPath();

                    directory = new File(URLDecoder.decode(path2, “UTF-8”));

                    directories.add(directory);

                }

                if (packageNames == null) {

                    packageNames = new HashMap();

                }

                packageNames.put(directory, pckgname);

            }

        } catch (NullPointerException x) {

            throw new ClassNotFoundException(pckgname + ” does not appear to be a valid package (Null pointer exception)”);

        } catch (UnsupportedEncodingException encex) {

            throw new ClassNotFoundException(pckgname + ” does not appear to be a valid package (Unsupported encoding)”);

        } catch (IOException ioex) {

            throw new ClassNotFoundException(“IOException was thrown when trying to get all resources for ” + pckgname);

        }

        for (File directory : directories) {

            if (directory.exists()) {

                String[] files = directory.list();

                for (String file : files) {

                    if (file.endsWith(“.class”)) {

                        try {

                      //      System.out.println(packageNames.get(directory).toString() + ‘.’ + file.substring(0, file.length() – 6));

                            result.add(Class.forName(packageNames.get(directory).toString() + ‘.’ + file.substring(0, file.length() – 6)));

                        } catch (Throwable e) {

                        }

                    }

                }

            } else {

                throw new ClassNotFoundException(pckgname + ” (” + directory.getPath() + “) does not appear to be a valid package”);

            }

        }

        return result;

    }

    /**

     *

     * Returns the list of classes in the same directories as Classes in

     * classes.

     *

     * @param result

     * @param classes

     * @param jarPath

     *

     */

    private static void getClassesInSamePackageFromJar(List result, String packageName, String jarPath) {

        JarFile jarFile = null;

        try {

            jarFile = new JarFile(jarPath);

            Enumeration<JarEntry> en = jarFile.entries();

            while (en.hasMoreElements()) {

                JarEntry entry = en.nextElement();

                String entryName = entry.getName();

                packageName = packageName.replace(‘.’, ‘/’);

                if (entryName != null && entryName.endsWith(“.class”) && entryName.startsWith(packageName)) {

                    try {

                        Class entryClass = Class.forName(entryName.substring(0, entryName.length() – 6).replace(‘/’, ‘.’));

                        if (entryClass != null) {

                            result.add(entryClass);

                        }

                    } catch (Throwable e) {

// do nothing, just continue processing classes

                    }

                }

            }

        } catch (Exception e) {

        } finally {

            try {

                if (jarFile != null) {

                    jarFile.close();

                }

            } catch (Exception e) {

            }

        }

    }

}

2 Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Middleware Team
Middleware Team