mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Add 'run' goal to spring-package-maven-plugin
Add a 'run' goal that allows maven to run a bootstrap packaged application in-place. Similar to the maven-exec-plugin but also adds src/main/resources to the classpath, allowing 'instant refresh' for web developers. Issue: #53592789
This commit is contained in:
parent
7dd186aa40
commit
1bec676ca1
@ -14,6 +14,11 @@
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- Compile -->
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-launcher</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-archiver</artifactId>
|
||||
@ -82,13 +87,6 @@
|
||||
<artifactId>maven-plugin-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-launcher</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
@ -12,7 +12,6 @@
|
||||
<groupId>@project.groupId@</groupId>
|
||||
<artifactId>@project.artifactId@</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
27
spring-package-maven-plugin/src/it/run/pom.xml
Normal file
27
spring-package-maven-plugin/src/it/run/pom.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.zero.maven.it</groupId>
|
||||
<artifactId>run</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>@project.groupId@</groupId>
|
||||
<artifactId>@project.artifactId@</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id></id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,9 @@
|
||||
package org.test;
|
||||
|
||||
public class SampleApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("I haz been run");
|
||||
}
|
||||
|
||||
}
|
3
spring-package-maven-plugin/src/it/run/verify.groovy
Normal file
3
spring-package-maven-plugin/src/it/run/verify.groovy
Normal file
@ -0,0 +1,3 @@
|
||||
def file = new File(basedir, "build.log")
|
||||
return file.text.contains("I haz been run")
|
||||
|
@ -12,7 +12,6 @@
|
||||
<groupId>@project.groupId@</groupId>
|
||||
<artifactId>@project.artifactId@</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.maven.packaging;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.archiver.MavenArchiveConfiguration;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
|
||||
/**
|
||||
* Abstract base class for MOJOs that work with executable archives.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class AbstractExecutableArchiveMojo extends AbstractMojo {
|
||||
|
||||
protected static final String MAIN_CLASS_ATTRIBUTE = "Main-Class";
|
||||
|
||||
private static final Map<String, ArchiveHelper> ARCHIVE_HELPERS;
|
||||
static {
|
||||
Map<String, ArchiveHelper> helpers = new HashMap<String, ArchiveHelper>();
|
||||
helpers.put("jar", new ExecutableJarHelper());
|
||||
helpers.put("war", new ExecutableWarHelper());
|
||||
ARCHIVE_HELPERS = Collections.unmodifiableMap(helpers);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Maven project.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project}", readonly = true, required = true)
|
||||
private MavenProject project;
|
||||
|
||||
/**
|
||||
* Directory containing the classes and resource files that should be packaged into
|
||||
* the archive.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
|
||||
private File classesDirectrory;
|
||||
|
||||
/**
|
||||
* The name of the main class. If not specified the first compiled class found that
|
||||
* contains a 'main' method will be used.
|
||||
*/
|
||||
@Parameter
|
||||
private String mainClass;
|
||||
|
||||
/**
|
||||
* The archive configuration to use. See <a
|
||||
* href="http://maven.apache.org/shared/maven-archiver/index.html">Maven Archiver
|
||||
* Reference</a>.
|
||||
*/
|
||||
@Parameter
|
||||
private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
|
||||
|
||||
protected final ArchiveHelper getArchiveHelper() throws MojoExecutionException {
|
||||
ArchiveHelper helper = ARCHIVE_HELPERS.get(getType());
|
||||
if (helper == null) {
|
||||
throw new MojoExecutionException("Unsupported packaging type: " + getType());
|
||||
}
|
||||
return helper;
|
||||
}
|
||||
|
||||
protected final String getStartClass() throws MojoExecutionException {
|
||||
String mainClass = this.mainClass;
|
||||
if (mainClass == null) {
|
||||
mainClass = this.archive.getManifestEntries().get(MAIN_CLASS_ATTRIBUTE);
|
||||
}
|
||||
if (mainClass == null) {
|
||||
mainClass = MainClassFinder.findMainClass(this.classesDirectrory);
|
||||
}
|
||||
if (mainClass == null) {
|
||||
throw new MojoExecutionException("Unable to find a suitable main class, "
|
||||
+ "please add a 'mainClass' property");
|
||||
}
|
||||
return mainClass;
|
||||
}
|
||||
|
||||
protected final MavenProject getProject() {
|
||||
return this.project;
|
||||
}
|
||||
|
||||
protected final String getType() {
|
||||
return this.project.getPackaging();
|
||||
}
|
||||
|
||||
protected final String getExtension() {
|
||||
return getProject().getPackaging();
|
||||
}
|
||||
|
||||
protected final MavenArchiveConfiguration getArchiveConfiguration() {
|
||||
return this.archive;
|
||||
}
|
||||
|
||||
protected final File getClassesDirectory() {
|
||||
return this.classesDirectrory;
|
||||
}
|
||||
}
|
@ -21,17 +21,12 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.maven.archiver.MavenArchiveConfiguration;
|
||||
import org.apache.maven.archiver.MavenArchiver;
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.execution.MavenSession;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.Component;
|
||||
@ -39,7 +34,6 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.project.MavenProjectHelper;
|
||||
import org.codehaus.plexus.archiver.Archiver;
|
||||
import org.codehaus.plexus.archiver.jar.JarArchiver;
|
||||
@ -63,20 +57,10 @@ import org.sonatype.aether.util.artifact.DefaultArtifact;
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Mojo(name = "package", defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true, threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME)
|
||||
public class ExecutableArchiveMojo extends AbstractMojo {
|
||||
|
||||
private static final String MAIN_CLASS_ATTRIBUTE = "Main-Class";
|
||||
public class ExecutableArchiveMojo extends AbstractExecutableArchiveMojo {
|
||||
|
||||
private static final String START_CLASS_ATTRIBUTE = "Start-Class";
|
||||
|
||||
private static final Map<String, ArchiveHelper> ARCHIVE_HELPERS;
|
||||
static {
|
||||
Map<String, ArchiveHelper> helpers = new HashMap<String, ArchiveHelper>();
|
||||
helpers.put("jar", new ExecutableJarHelper());
|
||||
helpers.put("war", new ExecutableWarHelper());
|
||||
ARCHIVE_HELPERS = Collections.unmodifiableMap(helpers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Archiver used to create a JAR file.
|
||||
*/
|
||||
@ -95,12 +79,6 @@ public class ExecutableArchiveMojo extends AbstractMojo {
|
||||
@Component
|
||||
private RepositorySystem repositorySystem;
|
||||
|
||||
/**
|
||||
* The Maven project.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project}", readonly = true, required = true)
|
||||
private MavenProject project;
|
||||
|
||||
/**
|
||||
* The Maven session.
|
||||
*/
|
||||
@ -119,13 +97,6 @@ public class ExecutableArchiveMojo extends AbstractMojo {
|
||||
@Parameter(defaultValue = "${project.build.finalName}", required = true)
|
||||
private String finalName;
|
||||
|
||||
/**
|
||||
* The name of the main class. If not specified the first compiled class found that
|
||||
* contains a 'main' method will be used.
|
||||
*/
|
||||
@Parameter
|
||||
private String mainClass;
|
||||
|
||||
/**
|
||||
* Classifier to add to the artifact generated. If given, the artifact will be
|
||||
* attached. If this is not given, it will merely be written to the output directory
|
||||
@ -134,21 +105,6 @@ public class ExecutableArchiveMojo extends AbstractMojo {
|
||||
@Parameter
|
||||
private String classifier;
|
||||
|
||||
/**
|
||||
* Directory containing the classes and resource files that should be packaged into
|
||||
* the archive.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
|
||||
private File classesDirectrory;
|
||||
|
||||
/**
|
||||
* The archive configuration to use. See <a
|
||||
* href="http://maven.apache.org/shared/maven-archiver/index.html">Maven Archiver
|
||||
* Reference</a>.
|
||||
*/
|
||||
@Parameter
|
||||
private MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
|
||||
|
||||
/**
|
||||
* Whether creating the archive should be forced.
|
||||
*/
|
||||
@ -165,25 +121,17 @@ public class ExecutableArchiveMojo extends AbstractMojo {
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
File archiveFile = createArchive();
|
||||
if (this.classifier == null || this.classifier.isEmpty()) {
|
||||
this.project.getArtifact().setFile(archiveFile);
|
||||
getProject().getArtifact().setFile(archiveFile);
|
||||
}
|
||||
else {
|
||||
getLog().info(
|
||||
"Attaching archive: " + archiveFile + ", with classifier: "
|
||||
+ this.classifier);
|
||||
this.projectHelper.attachArtifact(this.project, getType(), this.classifier,
|
||||
this.projectHelper.attachArtifact(getProject(), getType(), this.classifier,
|
||||
archiveFile);
|
||||
}
|
||||
}
|
||||
|
||||
private ArchiveHelper getArchiveHelper() throws MojoExecutionException {
|
||||
ArchiveHelper helper = ARCHIVE_HELPERS.get(getType());
|
||||
if (helper == null) {
|
||||
throw new MojoExecutionException("Unsupported packaging type: " + getType());
|
||||
}
|
||||
return helper;
|
||||
}
|
||||
|
||||
private File createArchive() throws MojoExecutionException {
|
||||
File archiveFile = getTargetFile();
|
||||
MavenArchiver archiver = new MavenArchiver();
|
||||
@ -195,11 +143,12 @@ public class ExecutableArchiveMojo extends AbstractMojo {
|
||||
|
||||
try {
|
||||
getLog().info("Modifying archive: " + archiveFile);
|
||||
copyContent(archiver, this.project.getArtifact().getFile());
|
||||
copyContent(archiver, getProject().getArtifact().getFile());
|
||||
addLibs(archiver);
|
||||
ZipFile zipFile = addLauncherClasses(archiver);
|
||||
try {
|
||||
archiver.createArchive(this.session, this.project, this.archive);
|
||||
archiver.createArchive(this.session, getProject(),
|
||||
getArchiveConfiguration());
|
||||
return archiveFile;
|
||||
}
|
||||
finally {
|
||||
@ -211,14 +160,6 @@ public class ExecutableArchiveMojo extends AbstractMojo {
|
||||
}
|
||||
}
|
||||
|
||||
private String getType() {
|
||||
return this.project.getPackaging();
|
||||
}
|
||||
|
||||
private String getExtension() {
|
||||
return this.project.getPackaging();
|
||||
}
|
||||
|
||||
private void copyContent(MavenArchiver archiver, File file) throws IOException {
|
||||
|
||||
FileInputStream input = new FileInputStream(file);
|
||||
@ -232,7 +173,6 @@ public class ExecutableArchiveMojo extends AbstractMojo {
|
||||
Enumeration<? extends ZipEntry> entries = zipFile.getEntries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
// TODO: maybe merge manifest instead of skipping it?
|
||||
if (!entry.isDirectory()
|
||||
&& !entry.getName().toUpperCase().equals("/META-INF/MANIFEST.MF")) {
|
||||
ZipResource zipResource = new ZipResource(zipFile, entry);
|
||||
@ -252,28 +192,20 @@ public class ExecutableArchiveMojo extends AbstractMojo {
|
||||
}
|
||||
|
||||
private void customizeArchiveConfiguration() throws MojoExecutionException {
|
||||
this.archive.setForced(this.forceCreation);
|
||||
String mainClass = this.mainClass;
|
||||
if (mainClass == null) {
|
||||
mainClass = this.archive.getManifestEntries().get(MAIN_CLASS_ATTRIBUTE);
|
||||
}
|
||||
if (mainClass == null) {
|
||||
mainClass = MainClassFinder.findMainClass(this.classesDirectrory);
|
||||
}
|
||||
if (mainClass == null) {
|
||||
throw new MojoExecutionException("Unable to find a suitable main class, "
|
||||
+ "please add a 'mainClass' property");
|
||||
}
|
||||
this.archive.getManifestEntries().put(MAIN_CLASS_ATTRIBUTE,
|
||||
getArchiveConfiguration().setForced(this.forceCreation);
|
||||
String startClass = getStartClass();
|
||||
getArchiveConfiguration().getManifestEntries().put(MAIN_CLASS_ATTRIBUTE,
|
||||
getArchiveHelper().getLauncherClass());
|
||||
this.archive.getManifestEntries().put(START_CLASS_ATTRIBUTE, mainClass);
|
||||
getArchiveConfiguration().getManifestEntries().put(START_CLASS_ATTRIBUTE,
|
||||
startClass);
|
||||
}
|
||||
|
||||
private void addLibs(MavenArchiver archiver) throws MojoExecutionException {
|
||||
getLog().info("Adding dependencies");
|
||||
for (Artifact artifact : this.project.getArtifacts()) {
|
||||
ArchiveHelper archiveHelper = getArchiveHelper();
|
||||
for (Artifact artifact : getProject().getArtifacts()) {
|
||||
if (artifact.getFile() != null) {
|
||||
String dir = getArchiveHelper().getArtifactDestination(artifact);
|
||||
String dir = archiveHelper.getArtifactDestination(artifact);
|
||||
if (dir != null) {
|
||||
getLog().debug("Adding dependency: " + artifact);
|
||||
archiver.getArchiver().addFile(artifact.getFile(),
|
||||
@ -288,8 +220,8 @@ public class ExecutableArchiveMojo extends AbstractMojo {
|
||||
getLog().info("Adding launcher classes");
|
||||
try {
|
||||
List<RemoteRepository> repositories = new ArrayList<RemoteRepository>();
|
||||
repositories.addAll(this.project.getRemotePluginRepositories());
|
||||
repositories.addAll(this.project.getRemoteProjectRepositories());
|
||||
repositories.addAll(getProject().getRemotePluginRepositories());
|
||||
repositories.addAll(getProject().getRemoteProjectRepositories());
|
||||
|
||||
String version = getClass().getPackage().getImplementationVersion();
|
||||
DefaultArtifact artifact = new DefaultArtifact(
|
||||
|
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.maven.packaging;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.model.Resource;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
|
||||
/**
|
||||
* MOJO that can be used to run a executable archive application directly from Maven.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Mojo(name = "run", requiresProject = true, defaultPhase = LifecyclePhase.VALIDATE, requiresDependencyResolution = ResolutionScope.TEST)
|
||||
public class RunMojo extends AbstractExecutableArchiveMojo {
|
||||
|
||||
/**
|
||||
* Add maven resources to the classpath directly, this allows live in-place editing or
|
||||
* resources. Since resources will be added directly, and via the target/classes
|
||||
* folder they will appear twice if ClassLoader.getResources() is called. In practice
|
||||
* however most applications call ClassLoader.getResource() which will always return
|
||||
* the first resource.
|
||||
*/
|
||||
@Parameter(property = "run.addResources", defaultValue = "true")
|
||||
private boolean addResources;
|
||||
|
||||
/**
|
||||
* Arguments that should be passed to the application.
|
||||
*/
|
||||
@Parameter(property = "run.arguments")
|
||||
private String[] arguments;
|
||||
|
||||
/**
|
||||
* Folders that should be added to the classpath.
|
||||
*/
|
||||
@Parameter
|
||||
private String[] folders;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
final String startClassName = getStartClass();
|
||||
IsolatedThreadGroup threadGroup = new IsolatedThreadGroup(startClassName);
|
||||
Thread launchThread = new Thread(threadGroup, new LaunchRunner(startClassName,
|
||||
this.arguments), startClassName + ".main()");
|
||||
launchThread.setContextClassLoader(getClassLoader());
|
||||
launchThread.start();
|
||||
join(threadGroup);
|
||||
threadGroup.rethrowUncaughtException();
|
||||
}
|
||||
|
||||
private ClassLoader getClassLoader() throws MojoExecutionException {
|
||||
URL[] urls = getClassPathUrls();
|
||||
return new URLClassLoader(urls);
|
||||
}
|
||||
|
||||
private URL[] getClassPathUrls() throws MojoExecutionException {
|
||||
ArchiveHelper archiveHelper = getArchiveHelper();
|
||||
try {
|
||||
List<URL> urls = new ArrayList<URL>();
|
||||
addUserDefinedFolders(urls);
|
||||
addResources(urls);
|
||||
addProjectClasses(urls);
|
||||
addDependencies(archiveHelper, urls);
|
||||
return urls.toArray(new URL[urls.size()]);
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
throw new MojoExecutionException("Unable to build classpath", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void addUserDefinedFolders(List<URL> urls) throws MalformedURLException {
|
||||
if (this.folders != null) {
|
||||
for (String folder : this.folders) {
|
||||
urls.add(new File(folder).toURI().toURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addResources(List<URL> urls) throws MalformedURLException {
|
||||
if (this.addResources) {
|
||||
for (Resource resource : getProject().getResources()) {
|
||||
urls.add(new File(resource.getDirectory()).toURI().toURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addProjectClasses(List<URL> urls) throws MalformedURLException {
|
||||
urls.add(getClassesDirectory().toURI().toURL());
|
||||
}
|
||||
|
||||
private void addDependencies(ArchiveHelper archiveHelper, List<URL> urls)
|
||||
throws MalformedURLException {
|
||||
for (Artifact artifact : getProject().getArtifacts()) {
|
||||
if (artifact.getFile() != null) {
|
||||
if (archiveHelper.getArtifactDestination(artifact) != null) {
|
||||
urls.add(artifact.getFile().toURI().toURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void join(ThreadGroup threadGroup) {
|
||||
boolean hasNonDaemonThreads;
|
||||
do {
|
||||
hasNonDaemonThreads = false;
|
||||
Thread[] threads = new Thread[threadGroup.activeCount()];
|
||||
threadGroup.enumerate(threads);
|
||||
for (Thread thread : threads) {
|
||||
if (thread != null && !thread.isDaemon()) {
|
||||
try {
|
||||
hasNonDaemonThreads = true;
|
||||
thread.join();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (hasNonDaemonThreads);
|
||||
}
|
||||
|
||||
/**
|
||||
* Isolated {@link ThreadGroup} to capture uncaught exceptions.
|
||||
*/
|
||||
class IsolatedThreadGroup extends ThreadGroup {
|
||||
|
||||
private Throwable exception;
|
||||
|
||||
public IsolatedThreadGroup(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable ex) {
|
||||
if (!(ex instanceof ThreadDeath)) {
|
||||
synchronized (this) {
|
||||
this.exception = (this.exception == null ? ex : this.exception);
|
||||
}
|
||||
getLog().warn(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void rethrowUncaughtException() throws MojoExecutionException {
|
||||
if (this.exception != null) {
|
||||
throw new MojoExecutionException("An exception occured while running. "
|
||||
+ this.exception.getMessage(), this.exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runner used to launch the application.
|
||||
*/
|
||||
class LaunchRunner implements Runnable {
|
||||
|
||||
private String startClassName;
|
||||
private String[] args;
|
||||
|
||||
public LaunchRunner(String startClassName, String... args) {
|
||||
this.startClassName = startClassName;
|
||||
this.args = (args != null ? args : new String[] {});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Thread thread = Thread.currentThread();
|
||||
ClassLoader classLoader = thread.getContextClassLoader();
|
||||
try {
|
||||
Class<?> startClass = classLoader.loadClass(this.startClassName);
|
||||
Method mainMethod = startClass.getMethod("main",
|
||||
new Class[] { String[].class });
|
||||
if (!mainMethod.isAccessible()) {
|
||||
mainMethod.setAccessible(true);
|
||||
}
|
||||
mainMethod.invoke(null, new Object[] { this.args });
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
Exception wrappedEx = new Exception(
|
||||
"The specified mainClass doesn't contain a "
|
||||
+ "main method with appropriate signature.", ex);
|
||||
thread.getThreadGroup().uncaughtException(thread, wrappedEx);
|
||||
}
|
||||
catch (Exception e) {
|
||||
thread.getThreadGroup().uncaughtException(thread, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -204,17 +204,6 @@
|
||||
<version>2.3</version>
|
||||
</plugin>
|
||||
|
||||
<!-- Allow exec plugin to launch the application -->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<configuration>
|
||||
<includePluginDependencies>true</includePluginDependencies>
|
||||
<mainClass>${start-class}</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Support the generally useful versions command -->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
@ -222,19 +211,27 @@
|
||||
<version>2.0</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.springframework.zero</groupId>
|
||||
<artifactId>spring-package-maven-plugin</artifactId>
|
||||
<version>${spring.zero.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>package</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Support our own packaging plugin -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.zero</groupId>
|
||||
<artifactId>spring-package-maven-plugin</artifactId>
|
||||
<version>${spring.zero.version}</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>package</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- Support shade packaging -->
|
||||
<plugin>
|
||||
|
Loading…
Reference in New Issue
Block a user