0

I want take all mehod with @Test in all JAR file with many class. i have my main in src/main/java/it/anas/testsuiteloader/controller.java and jar file in src/main/java/test/* <---test is a package

my code is:

             //TAKE ALL JAR FILE
             List<JarFile> jarList = Files.walk(Paths.get("src/main/java/test"))
            .filter(f -> f.toString().endsWith(".jar"))
            .map(Path::toFile).map(f -> {
                try {
                    return new JarFile(f);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            })
            .collect(Collectors.toList());

     //in all jar, in all class in all method

     for (JarFile j : jarList) {
         for (Enumeration<JarEntry> entries = j.entries(); entries.hasMoreElements(); ) {
            JarEntry entry = entries.nextElement();
            String file = entry.getName();

            if (file.endsWith(".class")) {
                String classname = file.replaceAll("/", ".")
                        .substring(0, file.lastIndexOf("."));


                try {
                    Class<?> currentClass = Class.forName(classname); <----ERROR!!!!
                    List<String> testMethods = new ArrayList<>();
                    for (int i = 0; i < currentClass.getMethods().length; i++) {
                        Method method = currentClass.getMethods()[i];
                        Annotation ann = method.getAnnotation(Test.class);
                        if (ann != null) {
                            testMethods.add(method.getName());
                        }
                    }//fine for metodi
                    if (testMethods.size() >1) {
                        testClassObjList.put(j.toString(),classname,testMethods);
                        System.out.format("%s %s %s",j.toString(),classname,testMethods);
                    }
                } catch (Throwable e) {System.out.println("WARNING: failed to instantiate " + classname + " from " + file); }

            }
        }

It take correct class name:

String classname = file.replaceAll("/", ".")
                        .substring(0, file.lastIndexOf("."));  //<----- IS OK i view here class name

But here i have error:

Class<?> currentClass = Class.forName(classname);  //<-----ERROR no class found! 

Some TIPS??? How i search class in JAR file?? thanks Regards

Catanzaro
  • 1,312
  • 2
  • 13
  • 24

1 Answers1

0

You open a jar file (jar is an archive in zip format) and iterate over the entries in the archive. Your problem is that you never loaded your jar to the JVM, so Class.forName will fail.

You need to load your jar file dynamically. Here is my code for finding annotations in one class for dynamically loaded jar, inspired by How to load JAR files dynamically at Runtime?

var url = new File("YOUR_JAR.jar").toURI().toURL();
var child = new URLClassLoader(
        new URL[] {url},
        this.getClass().getClassLoader()
);
var classToLoad = Class.forName("YOUR_CLASS_FULLY_QUALIFIED_NAME", true, child);
var methods = classToLoad.getMethods();
for (var method: methods) {
    Annotation ann = method.getAnnotation(Test.class);
    if (ann != null) {
        System.out.println("method: " + method.getName());
    }
}

You can easily extend that to process multiple classes and multiple jars.

Lesiak
  • 22,088
  • 2
  • 41
  • 65