Attempts to list all the classes in the specified package as determined by the context class loader...
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLDecoder; import java.security.CodeSource; import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class FileUtils { static int BUFFER_SIZE = 10*1024; /** * 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<Class<?>> getClassesInSamePackage(Class<?>... classes) throws ClassNotFoundException { ArrayList<Class<?>> result = new ArrayList<Class<?>>(); if(classes == null || classes.length == 0) return result; // This will hold a list of directories matching the pckgname. There may be more than one if // a package is split over multiple jars/paths ArrayList<File> directories = new ArrayList<File>(); HashMap<File,String> packageNames = null; String pckgname = null; try { ClassLoader cld = Thread.currentThread().getContextClassLoader(); if (cld == null) { throw new ClassNotFoundException("Can't get class loader."); } for(Class<?> clazz: classes) { // TODO: this would not work in a non OSGi environment String syspath = getBundlePath(clazz); if(syspath.endsWith("/")) { syspath = syspath.substring(0, syspath.length()-1); } else if(syspath.endsWith(".jar")) { getClassesInSamePackageFromJar(result, classes, syspath); continue; } pckgname = clazz.getPackage().getName(); String path = pckgname.replace('.', '/'); // Ask for all resources for the path Enumeration<URL> resources = cld.getResources(path); File directory = null; while (resources.hasMoreElements()) { String path2 = resources.nextElement().getPath(); if (!path2.contains(syspath)) { // needed to get it working on Eclipse 3.5 if(syspath.indexOf("/bin")<1) { syspath = syspath + "/bin"; } directory = new File(URLDecoder.decode(syspath+path2, "UTF-8")); } else directory = new File(URLDecoder.decode(path2, "UTF-8")); directories.add(directory); } if (packageNames == null) packageNames = new HashMap<File, String>(); 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 every directory identified capture all the .class files for (File directory : directories) { if (directory.exists()) { // Get the list of the files contained in the package String[] files = directory.list(); for (String file : files) { System.out.println(file); // we are only interested in .class files if (file.endsWith(".class")) { try { // removes the .class extension result.add(Class.forName(packageNames.get(directory) + '.' + file.substring(0, file.length() - 6))); } catch (Throwable e) { // ignore exception and continue } } } } 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 <code>classes</code>. * * @param result * @param classes * @param jarPath */ private static void getClassesInSamePackageFromJar(List<Class<?>> result, Class<?>[] classes, String jarPath) { JarFile jarFile = null; try { jarFile = new JarFile(jarPath); //ClassLoader cld = Thread.currentThread().getContextClassLoader(); Enumeration<JarEntry> en = jarFile.entries(); while(en.hasMoreElements()) { JarEntry entry = en.nextElement(); String entryName = entry.getName(); for(Class<?> clazz: classes) { String packageName = clazz.getPackage().getName().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) { result.addAll(Arrays.asList(classes)); } finally { try { if(jarFile != null) jarFile.close(); } catch (Exception e) { } } } /** * Returns the location of the * * @param clazz * @return */ public static String getBundlePath(Class<?> clazz) { ProtectionDomain pd = clazz.getProtectionDomain(); if (pd == null) return null; CodeSource cs = pd.getCodeSource(); if (cs == null) return null; URL url = cs.getLocation(); if (url == null) return null; String result = url.getFile(); return result; } }