List Jar Classes Generated

0

I have a class that searches and lists the classes inside my jar, it being:

public static Class[] getClasses(String packageName) throws ClassNotFoundException, IOException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    assert classLoader != null;
    String path = packageName.replace('.', '/');
    Enumeration<URL> resources = classLoader.getResources(path);
    List<File> dirs = new ArrayList<File>();
    while (resources.hasMoreElements()) {
        URL resource = resources.nextElement();
        dirs.add(new File(resource.getFile()));
    }
    ArrayList<Class> classes = new ArrayList<Class>();
    for (File directory : dirs) {
        classes.addAll(findClasses(directory, packageName));
    }
    return classes.toArray(new Class[classes.size()]);
}

/**
 * Recursive method used to find all classes in a given directory and subdirs.
 *
 * @param directory   The base directory
 * @param packageName The package name for classes found inside the base directory
 * @return The classes
 * @throws ClassNotFoundException
 */
private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
    List<Class> classes = new ArrayList<Class>();
    if (!directory.exists()) {
        return classes;
    }
    File[] files = directory.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            assert !file.getName().contains(".");
            classes.addAll(findClasses(file, packageName + "." + file.getName()));
        } else if (file.getName().endsWith(".class")) {
            Class teste = Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6));
            if (teste.isAnnotationPresent(Table.class)){
                classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
            }
        }
    }
    return classes;
}

When I run the IDE, it works correctly, when I generate the JAR and run out of the IDE, it does not find any Class, can anyone help me with how do I search inside the jar already generated?

    
asked by anonymous 09.02.2018 / 13:16

1 answer

0

This implementation is based on directory / file.class lookup which simply does not exist when you generate the jar. Put some prints in the code you will notice the search being done in nonexistent (jar) directories.

By the way, this implementation has been posted to SO and also to DZone , both contain comments indicating that they do not work in an" executable-jar. "

One option is to use Reflections .

Example:

pom.xml

<dependencies>
    <dependency>
        <groupId>org.reflections</groupId>
        <artifactId>reflections</artifactId>
        <version>0.9.11</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>
                                    com.mypackage.scanner.ClassScanner
                                </mainClass>
                            </manifest>
                        </archive>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

ClassScanner:

public class ClassScanner {

    public static void main( String[] args ) {              
        Reflections reflections = new Reflections("com.mypackage.scanner", new SubTypesScanner(false));
        Set<Class<? extends Object>> classes = reflections.getSubTypesOf(Object.class);
        for(Class<? extends Object> cls : classes) {
           System.out.println(cls.getName());
        }
    }
}

Generating jar with Maven:

mvn clean package

For testing I added a class called "User" inside the same package.

Execution:

java -jar scanner-0.0.1-SNAPSHOT-jar-with-dependencies.jar

// output
com.mypackage.scanner.ClassScanner
com.mypackage.scanner.User
    
09.02.2018 / 21:49