diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/repackage/RepackageTask.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/repackage/RepackageTask.java index 92d99dbf35..98d17ccb88 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/repackage/RepackageTask.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/repackage/RepackageTask.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeUnit; import org.gradle.api.Action; import org.gradle.api.DefaultTask; @@ -35,6 +34,7 @@ import org.springframework.boot.gradle.SpringBootPluginExtension; import org.springframework.boot.loader.tools.DefaultLaunchScript; import org.springframework.boot.loader.tools.LaunchScript; import org.springframework.boot.loader.tools.Repackager; +import org.springframework.boot.loader.tools.Repackager.MainClassTimeoutWarningListener; import org.springframework.util.FileCopyUtils; /** @@ -46,8 +46,6 @@ import org.springframework.util.FileCopyUtils; */ public class RepackageTask extends DefaultTask { - private static final long FIND_WARNING_TIMEOUT = TimeUnit.SECONDS.toMillis(10); - private String customConfiguration; private Object withJarTask; @@ -215,7 +213,9 @@ public class RepackageTask extends DefaultTask { copy(file, outputFile); file = outputFile; } - Repackager repackager = new LoggingRepackager(file); + Repackager repackager = new Repackager(file); + repackager.addMainClassTimeoutWarningListener( + new LoggingMainClassTimeoutWarningListener()); setMainClass(repackager); if (this.extension.convertLayout() != null) { repackager.setLayout(this.extension.convertLayout()); @@ -305,26 +305,13 @@ public class RepackageTask extends DefaultTask { /** * {@link Repackager} that also logs when searching takes too long. */ - private class LoggingRepackager extends Repackager { - - LoggingRepackager(File source) { - super(source); - } + private class LoggingMainClassTimeoutWarningListener + implements MainClassTimeoutWarningListener { @Override - protected String findMainMethod(java.util.jar.JarFile source) throws IOException { - long startTime = System.currentTimeMillis(); - try { - return super.findMainMethod(source); - } - finally { - long duration = System.currentTimeMillis() - startTime; - if (duration > FIND_WARNING_TIMEOUT) { - getLogger().warn("Searching for the main-class is taking " - + "some time, consider using setting " - + "'springBoot.mainClass'"); - } - } + public void handleTimeoutWarning(long duration, String mainMethod) { + getLogger().warn("Searching for the main-class is taking " + + "some time, consider using setting " + "'springBoot.mainClass'"); } } diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java index c25129844b..ed56ebe5fc 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.Manifest; @@ -53,6 +54,10 @@ public class Repackager { private static final byte[] ZIP_FILE_HEADER = new byte[] { 'P', 'K', 3, 4 }; + private static final long FIND_WARNING_TIMEOUT = TimeUnit.SECONDS.toMillis(10); + + private List mainClassTimeoutListeners = new ArrayList(); + private String mainClass; private boolean backupSource = true; @@ -69,6 +74,16 @@ public class Repackager { this.layout = Layouts.forFile(source); } + /** + * Add a listener that will be triggered to dispaly a warning if searching for the + * main class takes too long. + * @param listener the listener to add + */ + public void addMainClassTimeoutWarningListener( + MainClassTimeoutWarningListener listener) { + this.mainClassTimeoutListeners.add(listener); + } + /** * Sets the main class that should be run. If not specified the value from the * MANIFEST will be used, or if no manifest entry is found the archive will be @@ -281,7 +296,7 @@ public class Repackager { startClass = manifest.getMainAttributes().getValue(MAIN_CLASS_ATTRIBUTE); } if (startClass == null) { - startClass = findMainMethod(source); + startClass = findMainMethodWithTimeoutWarning(source); } String launcherClassName = this.layout.getLauncherClassName(); if (launcherClassName != null) { @@ -306,6 +321,18 @@ public class Repackager { return manifest; } + private String findMainMethodWithTimeoutWarning(JarFile source) throws IOException { + long startTime = System.currentTimeMillis(); + String mainMethod = findMainMethod(source); + long duration = System.currentTimeMillis() - startTime; + if (duration > FIND_WARNING_TIMEOUT) { + for (MainClassTimeoutWarningListener listener : this.mainClassTimeoutListeners) { + listener.handleTimeoutWarning(duration, mainMethod); + } + } + return mainMethod; + } + protected String findMainMethod(JarFile source) throws IOException { return MainClassFinder.findSingleMainClass(source, this.layout.getClassesLocation()); @@ -324,6 +351,21 @@ public class Repackager { } } + /** + * Callback interface used to present a warning when finding the main class takes too + * long. + */ + public interface MainClassTimeoutWarningListener { + + /** + * Handle a timeout warning. + * @param duration the amount of time it took to find the main method + * @param mainMethod the main method that was actually found + */ + void handleTimeoutWarning(long duration, String mainMethod); + + } + /** * An {@code EntryTransformer} that renames entries by applying a prefix. */ diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java index 309eb72db3..4c7092d17a 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RepackageMojo.java @@ -22,14 +22,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.jar.JarFile; import org.apache.maven.artifact.Artifact; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; @@ -46,6 +43,7 @@ import org.springframework.boot.loader.tools.Layout; import org.springframework.boot.loader.tools.Layouts; import org.springframework.boot.loader.tools.Libraries; import org.springframework.boot.loader.tools.Repackager; +import org.springframework.boot.loader.tools.Repackager.MainClassTimeoutWarningListener; /** * Repackages existing JAR and WAR archives so that they can be executed from the command @@ -59,8 +57,6 @@ import org.springframework.boot.loader.tools.Repackager; @Mojo(name = "repackage", defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true, threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME) public class RepackageMojo extends AbstractDependencyFilterMojo { - private static final long FIND_WARNING_TIMEOUT = TimeUnit.SECONDS.toMillis(10); - /** * The Maven project. * @since 1.0 @@ -224,7 +220,9 @@ public class RepackageMojo extends AbstractDependencyFilterMojo { } private Repackager getRepackager(File source) { - Repackager repackager = new LoggingRepackager(source, getLog()); + Repackager repackager = new Repackager(source); + repackager.addMainClassTimeoutWarningListener( + new LoggingMainClassTimeoutWarningListener()); repackager.setMainClass(this.mainClass); if (this.layout != null) { getLog().info("Layout: " + this.layout); @@ -356,30 +354,15 @@ public class RepackageMojo extends AbstractDependencyFilterMojo { } - private static class LoggingRepackager extends Repackager { - - private final Log log; - - LoggingRepackager(File source, Log log) { - super(source); - this.log = log; - } + private class LoggingMainClassTimeoutWarningListener + implements MainClassTimeoutWarningListener { @Override - protected String findMainMethod(JarFile source) throws IOException { - long startTime = System.currentTimeMillis(); - try { - return super.findMainMethod(source); - } - finally { - long duration = System.currentTimeMillis() - startTime; - if (duration > FIND_WARNING_TIMEOUT) { - this.log.warn("Searching for the main-class is taking some time, " - + "consider using the mainClass configuration " - + "parameter"); - } - } + public void handleTimeoutWarning(long duration, String mainMethod) { + getLog().warn("Searching for the main-class is taking some time, " + + "consider using the mainClass configuration " + "parameter"); } } + }