Rework Repacakger timeout code

Pull up common timeout code into Repackager and remove the need for
custom subclasses.

See gh-7263
This commit is contained in:
Phillip Webb
2016-11-21 14:58:42 -08:00
parent dada7423b0
commit f5b03c81f3
3 changed files with 62 additions and 50 deletions

View File

@@ -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'");
}
}

View File

@@ -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<MainClassTimeoutWarningListener> mainClassTimeoutListeners = new ArrayList<MainClassTimeoutWarningListener>();
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.
*/

View File

@@ -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");
}
}
}