How do I locate resources on the classpath in java? Specifically stuff that ends in .hbm.xml.

My goal is to get a List of all resources on the classpath that end with ".hbm.xml".

3 Answers

3
erickson On Best Solutions

You have to get a classloader, and test whether it's a URLClassLoader. If so, downcast and get its URLs. From there, open each as a JarFile and look at its entries. Apply a regex to each entry and see if it's one that interests you.

Clearly, this isn't fast. It's best to be given a name to be looked up in the classpath, perhaps listed in a standard file name in the META-INF directory of each classpath element, similar to the technique used by the ServiceProvider facility. Note that you can list all files with a given name on the classpath.

-2
anjanb On

MyClass.class.getClassLoader().getResourceAsStream("Person.hbm.xml") is one way to look for it.

1
Maxim Veksler On

Method findClasses from our ClassLoaderUtil might be a good starting point to adapt to your needs.

public class ClassLoaderUtil {
    /**
     * Recursive method used to find all classes in a given path (directory or zip file url).  Directories
     * are searched recursively.  (zip files are
     * Adapted from http://snippets.dzone.com/posts/show/4831 and extended to support use of JAR files
     *
     * @param path   The base directory or url from which to search.
     * @param packageName The package name for classes found inside the base directory
     * @param regex       an optional class name pattern.  e.g. .*Test
     * @return The classes
     */
    private static TreeSet<String> findClasses(String path, String packageName, Pattern regex) throws Exception {
        TreeSet<String> classes = new TreeSet<String>();
        if (path.startsWith("file:") && path.contains("!")) {
            String[] split = path.split("!");
            URL jar = new URL(split[0]);
            ZipInputStream zip = new ZipInputStream(jar.openStream());
            ZipEntry entry;
            while ((entry = zip.getNextEntry()) != null) {
                if (entry.getName().endsWith(".class")) {
                    String className = entry.getName().replaceAll("[$].*", "").replaceAll("[.]class", "").replace('/', '.');
                    if (className.startsWith(packageName) && (regex == null || regex.matcher(className).matches()))
                        classes.add(className);
                }
            }
        }
        File dir = new File(path);
        if (!dir.exists()) {
            return classes;
        }

        File[] files = dir.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                assert !file.getName().contains(".");
                classes.addAll(findClasses(file.getAbsolutePath(), packageName + "." + file.getName(), regex));
            } else if (file.getName().endsWith(".class")) {
                String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
                if (regex == null || regex.matcher(className).matches())
                    classes.add(className);
            }
        }
        return classes;
    }

    public static <T> List<T> instances(Class<? extends T>[] classList) {
        List<T> tList = new LinkedList<T>();
        for(Class<? extends T> tClass : classList) {
            try {
                // Only try to instantiate real classes.
                if(! Modifier.isAbstract(tClass.getModifiers()) && ! Modifier.isInterface(tClass.getModifiers())) {
                    tList.add(tClass.newInstance());
                }
            } catch (Throwable t) {
                throw new RuntimeException(t.getMessage(), t);
            }

        }

        return tList;
    }

    public static Class[] findByPackage(String packageName, Class isAssignableFrom) {
        Class[] clazzes = getClassesInPackage(packageName, null);

        if(isAssignableFrom == null) {
            return clazzes;
        } else {
            List<Class> filteredList = new ArrayList<Class>();
            for(Class clazz : clazzes) {
                if(isAssignableFrom.isAssignableFrom(clazz))
                    filteredList.add(clazz);
            }

            return filteredList.toArray(new Class[0]);
        }
    }

    /**
     * Scans all classes accessible from the context class loader which belong to the given package and subpackages.
     * Adapted from http://snippets.dzone.com/posts/show/4831 and extended to support use of JAR files
     *
     * @param packageName The base package
     * @param regexFilter an optional class name pattern.
     * @return The classes
     */
    public static Class[] getClassesInPackage(String packageName, String regexFilter) {
        Pattern regex = null;
        if (regexFilter != null)
            regex = Pattern.compile(regexFilter);

        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            assert classLoader != null;
            String path = packageName.replace('.', '/');
            Enumeration<URL> resources = classLoader.getResources(path);
            List<String> dirs = new ArrayList<String>();
            while (resources.hasMoreElements()) {
                URL resource = resources.nextElement();
                dirs.add(resource.getFile());
            }
            TreeSet<String> classes = new TreeSet<String>();
            for (String directory : dirs) {
                classes.addAll(findClasses(directory, packageName, regex));
            }
            ArrayList<Class> classList = new ArrayList<Class>();
            for (String clazz : classes) {
                classList.add(Class.forName(clazz));
            }
                return classList.toArray(new Class[classes.size()]);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}