From e6a3ca5da6c58e8e6beb72624a1dfc1c41b121cf Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 21 Jun 2017 12:44:25 -0700 Subject: [PATCH] Address deprecation warning that's generated by Gradle 4.x In Gradle 4.x, SourceSetOutput now has multiple classes directories and getClassesDir() has been deprecated. This commit introduces the use of reflection to use getClassesDirs() when it's available rather than getClassesDir(). Closes gh-9559 --- .../boot/gradle/run/FindMainClassTask.java | 27 ++++++++++--- .../boot/loader/tools/MainClassFinder.java | 39 +++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/run/FindMainClassTask.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/run/FindMainClassTask.java index c3d2470a92b..ce35c01c415 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/run/FindMainClassTask.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/run/FindMainClassTask.java @@ -16,11 +16,16 @@ package org.springframework.boot.gradle.run; +import java.io.File; import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collection; import org.gradle.api.DefaultTask; import org.gradle.api.Project; import org.gradle.api.Task; +import org.gradle.api.file.FileCollection; import org.gradle.api.plugins.ApplicationPluginConvention; import org.gradle.api.plugins.ExtraPropertiesExtension; import org.gradle.api.tasks.Input; @@ -30,6 +35,7 @@ import org.gradle.api.tasks.TaskAction; import org.springframework.boot.gradle.SpringBootPluginExtension; import org.springframework.boot.loader.tools.MainClassFinder; +import org.springframework.util.ReflectionUtils; /** * Task to find and set the 'mainClassName' convention when it's missing by searching the @@ -103,13 +109,13 @@ public class FindMainClassTask extends DefaultTask { if (mainClass == null) { // Search if (this.mainClassSourceSetOutput != null) { - project.getLogger().debug("Looking for main in: " - + this.mainClassSourceSetOutput.getClassesDir()); + Collection classesDirs = getClassesDirs( + this.mainClassSourceSetOutput); + getProject().getLogger().debug("Looking for main in: " + classesDirs); try { - mainClass = MainClassFinder.findSingleMainClass( - this.mainClassSourceSetOutput.getClassesDir(), + mainClass = MainClassFinder.findSingleMainClass(classesDirs, SPRING_BOOT_APPLICATION_CLASS_NAME); - project.getLogger().info("Computed main class: " + mainClass); + getProject().getLogger().info("Computed main class: " + mainClass); } catch (IOException ex) { throw new IllegalStateException("Cannot find main class", ex); @@ -132,6 +138,17 @@ public class FindMainClassTask extends DefaultTask { return mainClass; } + private Collection getClassesDirs(SourceSetOutput sourceSetOutput) { + Method getClassesDirs = ReflectionUtils.findMethod(SourceSetOutput.class, + "getClassesDirs"); + if (getClassesDirs == null) { + return Arrays.asList(sourceSetOutput.getClassesDir()); + } + FileCollection classesDirs = (FileCollection) ReflectionUtils + .invokeMethod(getClassesDirs, sourceSetOutput); + return classesDirs.getFiles(); + } + private JavaExec findRunTask(Project project) { Task runTask = project.getTasks().findByName("run"); if (runTask instanceof JavaExec) { diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/MainClassFinder.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/MainClassFinder.java index f46257618f8..429caa3df8d 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/MainClassFinder.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/MainClassFinder.java @@ -25,6 +25,7 @@ import java.io.InputStream; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Deque; @@ -117,6 +118,44 @@ public abstract class MainClassFinder { return callback.getMainClassName(); } + /** + * Find a single main class from the given {@code rootFolders}. A main class annotated + * with an annotation with the given {@code annotationName} will be preferred over a + * main class with no such annotation. + * @param rootFolders the root folders to search + * @param annotationName the name of the annotation that may be present on the main + * class + * @return the main class or {@code null} + * @throws IOException if a root folder cannot be read + * @since 1.5.5 + */ + public static String findSingleMainClass(Collection rootFolders, + String annotationName) throws IOException { + SingleMainClassCallback callback = new SingleMainClassCallback(annotationName); + doWithMainClasses(rootFolders, callback); + return callback.getMainClassName(); + } + + /** + * Perform the given callback operation on all main classes from the given root + * folder. + * @param the result type + * @param rootFolders the root folders + * @param callback the callback + * @return the first callback result or {@code null} + * @throws IOException in case of I/O errors + */ + static T doWithMainClasses(Collection rootFolders, + MainClassCallback callback) throws IOException { + for (File rootFolder : rootFolders) { + T result = doWithMainClasses(rootFolder, callback); + if (result != null) { + return result; + } + } + return null; + } + /** * Perform the given callback operation on all main classes from the given root * folder.