Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find classes implementing an interface in Jar

I want to find whether the classes inside the jar has implemented a particular interface or not. I have implemented below code, but it iterates over all the classes inside jar file and finds on each class whether it has implemented this particular interface or not.

    public static synchronized boolean findClassesInJar(final Class<?> baseInterface, final String jarName){
        final List<String> classesTobeReturned = new ArrayList<String>();
        if (!StringUtils.isBlank(jarName)) {
            //jarName is relative location of jar wrt. 
            final String jarFullPath = File.separator + jarName;
            final ClassLoader classLoader = this.getClassLoader();
            JarInputStream jarFile = null;
            URLClassLoader ucl = null;
            final URL url = new URL("jar:file:" + jarFullPath + "!/");
            ucl = new URLClassLoader(new URL[] { url }, classLoader);
            jarFile = new JarInputStream(new FileInputStream(jarFullPath));
            JarEntry jarEntry;
            while (true) {
                jarEntry = jarFile.getNextJarEntry();
                if (jarEntry == null)
                    break;
                if (jarEntry.getName().endsWith(".class")) {
                    String classname = jarEntry.getName().replaceAll("/", "\\.");
                    classname = classname.substring(0, classname.length() - 6);
                    if (!classname.contains("$")) {
                        try {
                            final Class<?> myLoadedClass = Class.forName(classname, true, ucl);
                            if (baseInterface.isAssignableFrom(myLoadedClass)) {
                                return true;
                            }
                        } catch (final ClassNotFoundException e) {

                        } 
                    }
                }
            }
        return false;
    }

Is there any simple way to do this ? Because If have a jar with 100 class files and 100th class has implemented this interface, through the above code I need to iterate all the 100 class files and find whether it has implemented the interface or not. Is there any efficient way of doing it ?

like image 933
Lolly Avatar asked May 14 '13 14:05

Lolly


2 Answers

The Reflections library can do that:

Reflections reflections = new Reflections(
    ClasspathHelper.forPackage("your.root.package"), new SubTypesScanner());
Set<Class<? extends YourInterface>> implementingTypes =
     reflections.getSubTypesOf(YourInterface.class);
like image 132
Sean Patrick Floyd Avatar answered Oct 19 '22 20:10

Sean Patrick Floyd


Spring has some helper code for this in ClassPathScanningCandidateComponentProvider but it basically does what you did.

You might also want to look at Freud which is a comfortable toolkit to write static analysis tests like making sure that all classes in a certain package or which implement a certain interface also implement equals() and hashCode()

The nice thing about Freud is that it can analyze Java source and class files (i.e. source code and compiled byte code), it can look into properties or text files, it can read CSS and Spring configurations (so it can make sure that all important methods of a DAO bean have @Transactional).

like image 21
Aaron Digulla Avatar answered Oct 19 '22 21:10

Aaron Digulla