Рефлексивно получить все пакеты в проекте? - PullRequest
2 голосов
/ 16 февраля 2012

Как я могу рефлексивно получить все пакеты в проекте?Я начал с Package.getPackages (), но он получил только все пакеты, связанные с текущим пакетом.Есть ли способ сделать это?

Ответы [ 4 ]

1 голос
/ 17 февраля 2012

@ Комментарий Филиппа Вендлера привел меня к методу выполнения того, что мне нужно.Я немного подправил метод, чтобы сделать его рекурсивным.

    /**
     * Recursively fetches a list of all the classes in a given
     * directory (and sub-directories) that have the @UnitTestable
     * annotation.
     * @param packageName The top level package to search.
     * @param loader The class loader to use. May be null; we'll
     * just grab the current threads.
     * @return The list of all @UnitTestable classes.
     */
    public List<Class<?>> getTestableClasses(String packageName, ClassLoader loader) {
        // State what package we are exploring
        System.out.println("Exploring package: " + packageName);
        // Create the list that will hold the testable classes
        List<Class<?>> ret = new ArrayList<Class<?>>();
        // Create the list of immediately accessible directories
        List<File> directories = new ArrayList<File>();
        // If we don't have a class loader, get one.
        if (loader == null)
            loader = Thread.currentThread().getContextClassLoader();
        // Convert the package path to file path
        String path = packageName.replace('.', '/');
        // Try to get all of nested directories.
        try {
            // Get all of the resources for the given path
            Enumeration<URL> res = loader.getResources(path);
            // While we have directories to look at, recursively
            // get all their classes.
            while (res.hasMoreElements()) {
                // Get the file path the the directory
                String dirPath = URLDecoder.decode(res.nextElement()
                        .getPath(), "UTF-8");
                // Make a file handler for easy managing
                File dir = new File(dirPath);
                // Check every file in the directory, if it's a
                // directory, recursively add its viable files
                for (File file : dir.listFiles()) {
                    if (file.isDirectory()) 
                        ret.addAll(getTestableClasses(packageName + '.' + file.getName(), loader));
                }
            }
        } catch (IOException e) {
            // We failed to get any nested directories. State
            // so and continue; this directory may still have
            // some UnitTestable classes.
            System.out.println("Failed to load resources for [" + packageName + ']');
        }
        // We need access to our directory, so we can pull
        // all the classes.
        URL tmp = loader.getResource(path);
        System.out.println(tmp);
        if (tmp == null)
            return ret;
        File currDir = new File(tmp.getPath());
        // Now we iterate through all of the classes we find
        for (String classFile : currDir.list()) {
            // Ensure that we only find class files; can't load gif's!
            if (classFile.endsWith(".class")) {
                // Attempt to load the class or state the issue
                try {
                    // Try loading the class
                    Class<?> add = Class.forName(packageName + '.' +
                            classFile.substring(0, classFile.length() - 6));
                    // If the class has the correct annotation, add it
                    if (add.isAnnotationPresent(UnitTestable.class))
                        ret.add(add);
                    else 
                        System.out.println(add.getName() + " is not a UnitTestable class");
                } catch (NoClassDefFoundError e) {
                    // The class loader could not load the class
                    System.out.println("We have found class [" + classFile + "], and couldn't load it.");
                } catch (ClassNotFoundException e) {
                    // We couldn't even find the damn class
                    System.out.println("We could not find class [" + classFile + ']');
                }
            }
        }
        return ret;
    }
0 голосов
/ 05 декабря 2016

При таком подходе печатаются только все пакеты (сначала нужно указать хотя бы корневое имя "packageName").

Получено сверху.

package devTools;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

public class DevToolUtil {

    /**
     * Method prints all packages (at least a root "packageName" has to be given first).
     *
     * @see /4808351/refleksivno-poluchit-vse-pakety-v-proekte
     * @since 2016-12-05
     * @param packageName
     * @param loader
     * @return List of classes.
     */
    public List<Class<?>> getTestableClasses(final String packageName, ClassLoader loader) {
        System.out.println("Exploring package: " + packageName);

        final List<Class<?>> ret = new ArrayList<Class<?>>();

        if (loader == null) {
            loader = Thread.currentThread().getContextClassLoader();
        }

        final String path = packageName.replace('.', '/');

        try {
            final Enumeration<URL> res = loader.getResources(path);

            while (res.hasMoreElements()) {
                final String dirPath = URLDecoder.decode(res.nextElement().getPath(), "UTF-8");
                final File dir = new File(dirPath);

                if (dir.listFiles() != null) {
                    for (final File file : dir.listFiles()) {
                        if (file.isDirectory()) {
                            final String packageNameAndFile = packageName + '.' + file.getName();
                            ret.addAll(getTestableClasses(packageNameAndFile, loader));
                        }
                    }
                }
            }
        } catch (final IOException e) {
            System.out.println("Failed to load resources for [" + packageName + ']');
        }

        return ret;
    }

    public static void main(final String[] args) {
        new DevToolUtil().getTestableClasses("at", null);
    }
}
0 голосов
/ 17 февраля 2012

Может быть не по теме (потому что это не совсем с точки зрения java "отражения") ... Однако как насчет следующего решения:

Пакеты Java можно рассматривать как папки (или каталоги в Linux \ UNIX). Предполагая, что у вас есть корневой пакет и его абсолютный путь известен, вы можете рекурсивно распечатать все подпапки с файлами * .java или * .class, используя в качестве основы следующий пакет:

@echo off
rem List all the subfolders under current dir

FOR /R "." %%G in (.) DO (
 Pushd %%G
 Echo now in %%G
 Popd )
Echo "back home" 

Вы можете обернуть этот пакет в Java или, если вы работаете в Linux \ Unix, переписать его в каком-нибудь сценарии оболочки.

Удачи!

Aviad.

0 голосов
/ 16 февраля 2012

Это возможно, но сложно и дорого, так как вам нужно пройтись по классной дорожке самостоятельно.Вот как это делает TestNG, вы, вероятно, можете извлечь для себя важную часть:

https://github.com/cbeust/testng/blob/master/src/main/java/org/testng/internal/PackageUtils.java

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...