简体   繁体   中英

Reflections in custom java gradle plugin

I have a gradle project with multiple modules, each built to it's own .jar file. I want to use reflections in a custom java gradle plugin, to generate a report on annotated classes/methods.

/build.gradle

apply plugin: com.my.plugins.MyPlugin

/buildSrc/build.gradle

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.reflections:reflections:0.9.11'
    compile 'javax.annotation:javax.annotation-api:1.3.2'
}

/buildSrc/src/main/java/com/my/plugins/MyPlugin.java

@NonNullApi
public class MyPlugin implements Plugin<Project> {
    @Override
    public void apply(Project project) {
        MyTask myTask = project.getTasks().create("mytask", MyTask.class);
        Task javaCompileTask = project.getTasks().getByName("compileJava");
        myTask.dependsOn(javaCompileTask);
    }
}

/buildSrc/src/main/java/com/my/plugins/MyTask.java

public class MyTask extends DefaultTask {

    @TaskAction
    public void perform() throws MalformedURLException, ClassNotFoundException {

        List<URL> listOfURL = new ArrayList<>();
        Set<File> runtimeFiles = getProject().getConfigurations().findByName("runtime").getFiles();
        for (File file : runtimeFiles) {
            // TODO: Exclude files from gradle cache folder
            if (file.getPath().contains("build\\libs")) {
                listOfURL.add(file.toURI().toURL());
            }
        }

        URL[] urls = listOfURL.toArray(new URL[0]);
        System.out.println("\nURLs:");
        for (URL u : urls) {
            System.out.println("  " + u.toString());
        }

        ClassLoader classLoader = new URLClassLoader(urls, null);
        classLoader.loadClass("com.my.services.sample.MyClass");
        System.out.println("\nClassLoader OK!\n");

        Configuration config = new ConfigurationBuilder()
            .setUrls(ClasspathHelper.forClassLoader(classLoader))
            .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("com.my.services")))
            .addClassLoader(classLoader)
            .setScanners(new SubTypesScanner(),
                    new TypeAnnotationsScanner(),
                    new MethodAnnotationsScanner());

        Reflections reflections = new Reflections(config);

        System.out.println("\nPermitAll Classes\n");
        for (Class c : reflections.getTypesAnnotatedWith(PermitAll.class)) {
            System.out.println(c.getName());
        }

        System.out.println("\nPermitAll Methods\n");
        for (Method m : reflections.getMethodsAnnotatedWith(PermitAll.class)) {
            System.out.println(m.getName());
        }

    }
}

When I run gradlew mytask , I see the list of all my .jar files under build\\libs in the list of URLs.

Although the classLoader can successfully load (for example) MyClass, the new Reflections() line generates numerous "could not get type for name" errors, for example:

could not get type for name com.my.services.sample.MyClass from any class loader

Then, the list of PermitAll Classes generates correctly, but the list of PermitAll Methods fails with an exception, for example:

Execution failed for task ':mytask'.

> org/dom4j/DocumentException

I have already used the following as guides but am unable to make any further progress:

https://discuss.gradle.org/t/gradle-plugin-with-reflections/22690

Reflections could not get class type

You should use the following to create the classloader

URL[] urls = project.sourceSets.main.runtimeClasspath.files.collect {
    it.toURI().toURL()
} as URL[]
ClassLoader classloader = new URLClassLoader(urls, null) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM