List Classes with Generated Jar

Asked

Viewed 85 times

0

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

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 running in the IDE it works correctly, when I run the JAR and run outside the IDE, it error by not locating any Class, someone can help me as I do to search inside the already generated jar?

1 answer

0

This implementation is based on the lookup of directories/.class files that simply don’t exist when you generate the jar. Put some prints in the code that you will notice the search being performed in non-existent directories(jar).

By the way, this implementation was posted on ONLY and also in the 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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.