Move tools modules under spring-boot-tools
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
<?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.boot.maven.it</groupId>
|
||||
<artifactId>jar</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>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>some.random.Main</mainClass>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Not-Used>Foo</Not-Used>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.test;
|
||||
|
||||
public class SampleApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import java.io.*;
|
||||
import org.springframework.boot.maven.*;
|
||||
|
||||
Verify.verifyJar(
|
||||
new File( basedir, "target/jar-0.0.1.BUILD-SNAPSHOT.jar" ), "some.random.Main"
|
||||
);
|
||||
|
||||
@@ -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.boot.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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
def file = new File(basedir, "build.log")
|
||||
return file.text.contains("I haz been run")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<settings>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>it-repo</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>local.central</id>
|
||||
<url>@localRepositoryUrl@</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>local.central</id>
|
||||
<url>@localRepositoryUrl@</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</profile>
|
||||
</profiles>
|
||||
</settings>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?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.boot.maven.it</groupId>
|
||||
<artifactId>war</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>@project.groupId@</groupId>
|
||||
<artifactId>@project.artifactId@</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Not-Used>Foo</Not-Used>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>3.2.3.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.test;
|
||||
|
||||
public class SampleApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<html></html>
|
||||
@@ -0,0 +1,7 @@
|
||||
import java.io.*;
|
||||
import org.springframework.boot.maven.*;
|
||||
|
||||
Verify.verifyWar(
|
||||
new File( basedir, "target/war-0.0.1.BUILD-SNAPSHOT.war" )
|
||||
);
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.boot.maven;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.springframework.boot.loader.tools.Libraries;
|
||||
import org.springframework.boot.loader.tools.LibraryCallback;
|
||||
import org.springframework.boot.loader.tools.LibraryScope;
|
||||
|
||||
/**
|
||||
* {@link Libraries} backed by Maven {@link Artifact}s
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ArtifactsLibraries implements Libraries {
|
||||
|
||||
private static final Map<String, LibraryScope> SCOPES;
|
||||
static {
|
||||
Map<String, LibraryScope> scopes = new HashMap<String, LibraryScope>();
|
||||
scopes.put(Artifact.SCOPE_COMPILE, LibraryScope.COMPILE);
|
||||
scopes.put(Artifact.SCOPE_RUNTIME, LibraryScope.RUNTIME);
|
||||
scopes.put(Artifact.SCOPE_PROVIDED, LibraryScope.PROVIDED);
|
||||
SCOPES = Collections.unmodifiableMap(scopes);
|
||||
}
|
||||
|
||||
private final Set<Artifact> artifacts;
|
||||
|
||||
public ArtifactsLibraries(Set<Artifact> artifacts) {
|
||||
this.artifacts = artifacts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWithLibraries(LibraryCallback callback) throws IOException {
|
||||
for (Artifact artifact : this.artifacts) {
|
||||
LibraryScope scope = SCOPES.get(artifact.getScope());
|
||||
if (scope != null && artifact.getFile() != null) {
|
||||
callback.library(artifact.getFile(), scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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.boot.maven;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import org.apache.maven.plugins.shade.relocation.Relocator;
|
||||
import org.apache.maven.plugins.shade.resource.ResourceTransformer;
|
||||
|
||||
/**
|
||||
* Extension for the <a href="http://maven.apache.org/plugins/maven-shade-plugin/">Maven
|
||||
* shade plugin</a> to allow properties files (e.g. {@literal META-INF/spring.factories})
|
||||
* to be merged without losing any information.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class PropertiesMergingResourceTransformer implements ResourceTransformer {
|
||||
|
||||
// Set this in pom configuration with <resource>...</resource>
|
||||
private String resource;
|
||||
|
||||
private Properties data = new Properties();
|
||||
|
||||
/**
|
||||
* @return the data the properties being merged
|
||||
*/
|
||||
public Properties getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTransformResource(String resource) {
|
||||
if (this.resource != null && this.resource.equalsIgnoreCase(resource)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processResource(String resource, InputStream is,
|
||||
List<Relocator> relocators) throws IOException {
|
||||
Properties properties = new Properties();
|
||||
properties.load(is);
|
||||
is.close();
|
||||
for (Object key : properties.keySet()) {
|
||||
String name = (String) key;
|
||||
String value = properties.getProperty(name);
|
||||
String existing = this.data.getProperty(name);
|
||||
this.data
|
||||
.setProperty(name, existing == null ? value : existing + "," + value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTransformedResource() {
|
||||
return this.data.size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyOutputStream(JarOutputStream os) throws IOException {
|
||||
os.putNextEntry(new JarEntry(this.resource));
|
||||
this.data.store(os, "Merged by PropertiesMergingResourceTransformer");
|
||||
os.flush();
|
||||
this.data.clear();
|
||||
}
|
||||
|
||||
public String getResource() {
|
||||
return this.resource;
|
||||
}
|
||||
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.boot.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
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;
|
||||
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.springframework.boot.loader.tools.Libraries;
|
||||
import org.springframework.boot.loader.tools.Repackager;
|
||||
|
||||
/**
|
||||
* MOJO that can can be used to repackage existing JAR and WAR archives so that they can
|
||||
* be executed from the command line using {@literal java -jar}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Mojo(name = "repackage", defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true, threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME)
|
||||
public class RepackageMojo extends AbstractMojo {
|
||||
|
||||
/**
|
||||
* The Maven project.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project}", readonly = true, required = true)
|
||||
private MavenProject project;
|
||||
|
||||
/**
|
||||
* Maven project helper utils.
|
||||
*/
|
||||
@Component
|
||||
private MavenProjectHelper projectHelper;
|
||||
|
||||
/**
|
||||
* Directory containing the generated archive.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project.build.directory}", required = true)
|
||||
private File outputDirectory;
|
||||
|
||||
/**
|
||||
* Name of the generated archive.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project.build.finalName}", required = true)
|
||||
private String finalName;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* according to the finalName.
|
||||
*/
|
||||
@Parameter
|
||||
private String classifier;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
File source = this.project.getArtifact().getFile();
|
||||
File target = getTargetFile();
|
||||
Repackager repackager = new Repackager(source);
|
||||
repackager.setMainClass(this.mainClass);
|
||||
Libraries libraries = new ArtifactsLibraries(this.project.getArtifacts());
|
||||
try {
|
||||
repackager.repackage(target, libraries);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new MojoExecutionException(ex.getMessage(), ex);
|
||||
}
|
||||
if (!source.equals(target)) {
|
||||
getLog().info(
|
||||
"Attaching archive: " + target + ", with classifier: "
|
||||
+ this.classifier);
|
||||
this.projectHelper.attachArtifact(this.project, this.project.getPackaging(),
|
||||
this.classifier, target);
|
||||
}
|
||||
}
|
||||
|
||||
private File getTargetFile() {
|
||||
String classifier = (this.classifier == null ? "" : this.classifier.trim());
|
||||
if (classifier.length() > 0 && !classifier.startsWith("-")) {
|
||||
classifier = "-" + classifier;
|
||||
}
|
||||
return new File(this.outputDirectory, this.finalName + classifier + "."
|
||||
+ this.project.getPackaging());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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.boot.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
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.AbstractMojo;
|
||||
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;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.springframework.boot.loader.tools.MainClassFinder;
|
||||
|
||||
/**
|
||||
* 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 AbstractMojo {
|
||||
|
||||
/**
|
||||
* The Maven project.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project}", readonly = true, required = true)
|
||||
private MavenProject project;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Folders that should be added to the classpath.
|
||||
*/
|
||||
@Parameter
|
||||
private String[] folders;
|
||||
|
||||
/**
|
||||
* Directory containing the classes and resource files that should be packaged into
|
||||
* the archive.
|
||||
*/
|
||||
@Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
|
||||
private File classesDirectrory;
|
||||
|
||||
@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 final String getStartClass() throws MojoExecutionException {
|
||||
String mainClass = this.mainClass;
|
||||
if (mainClass == null) {
|
||||
try {
|
||||
mainClass = MainClassFinder.findMainClass(this.classesDirectrory);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new MojoExecutionException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
if (mainClass == null) {
|
||||
throw new MojoExecutionException("Unable to find a suitable main class, "
|
||||
+ "please add a 'mainClass' property");
|
||||
}
|
||||
return mainClass;
|
||||
}
|
||||
|
||||
private ClassLoader getClassLoader() throws MojoExecutionException {
|
||||
URL[] urls = getClassPathUrls();
|
||||
return new URLClassLoader(urls);
|
||||
}
|
||||
|
||||
private URL[] getClassPathUrls() throws MojoExecutionException {
|
||||
try {
|
||||
List<URL> urls = new ArrayList<URL>();
|
||||
addUserDefinedFolders(urls);
|
||||
addResources(urls);
|
||||
addProjectClasses(urls);
|
||||
addDependencies(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 : this.project.getResources()) {
|
||||
urls.add(new File(resource.getDirectory()).toURI().toURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addProjectClasses(List<URL> urls) throws MalformedURLException {
|
||||
urls.add(this.classesDirectrory.toURI().toURL());
|
||||
}
|
||||
|
||||
private void addDependencies(List<URL> urls) throws MalformedURLException {
|
||||
for (Artifact artifact : this.project.getArtifacts()) {
|
||||
if (artifact.getFile() != null) {
|
||||
if (!Artifact.SCOPE_TEST.equals(artifact.getScope())) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.boot.maven;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.maven.PropertiesMergingResourceTransformer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests for {@link PropertiesMergingResourceTransformer}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class PropertiesMergingResourceTransformerTests {
|
||||
|
||||
private PropertiesMergingResourceTransformer transformer = new PropertiesMergingResourceTransformer();
|
||||
|
||||
@Test
|
||||
public void testProcess() throws Exception {
|
||||
assertFalse(this.transformer.hasTransformedResource());
|
||||
this.transformer.processResource("foo",
|
||||
new ByteArrayInputStream("foo=bar".getBytes()), null);
|
||||
assertTrue(this.transformer.hasTransformedResource());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMerge() throws Exception {
|
||||
this.transformer.processResource("foo",
|
||||
new ByteArrayInputStream("foo=bar".getBytes()), null);
|
||||
this.transformer.processResource("bar",
|
||||
new ByteArrayInputStream("foo=spam".getBytes()), null);
|
||||
assertEquals("bar,spam", this.transformer.getData().getProperty("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutput() throws Exception {
|
||||
this.transformer.setResource("foo");
|
||||
this.transformer.processResource("foo",
|
||||
new ByteArrayInputStream("foo=bar".getBytes()), null);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
JarOutputStream os = new JarOutputStream(out);
|
||||
this.transformer.modifyOutputStream(os);
|
||||
os.flush();
|
||||
os.close();
|
||||
assertNotNull(out.toByteArray());
|
||||
assertTrue(out.toByteArray().length > 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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.boot.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Verification utility for use with maven-invoker-plugin verification scripts.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class Verify {
|
||||
|
||||
public static void verifyJar(File file) throws Exception {
|
||||
new JarArchiveVerification(file, "org.test.SampleApplication").verify();
|
||||
}
|
||||
|
||||
public static void verifyJar(File file, String main) throws Exception {
|
||||
new JarArchiveVerification(file, main).verify();
|
||||
}
|
||||
|
||||
public static void verifyWar(File file) throws Exception {
|
||||
new WarArchiveVerification(file).verify();
|
||||
}
|
||||
|
||||
private static abstract class AbstractArchiveVerification {
|
||||
|
||||
private File file;
|
||||
|
||||
public AbstractArchiveVerification(File file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public void verify() throws Exception {
|
||||
assertTrue("Archive missing", this.file.exists());
|
||||
assertTrue("Archive not a file", this.file.isFile());
|
||||
|
||||
ZipFile zipFile = new ZipFile(this.file);
|
||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
Map<String, ZipEntry> zipMap = new HashMap<String, ZipEntry>();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry zipEntry = entries.nextElement();
|
||||
zipMap.put(zipEntry.getName(), zipEntry);
|
||||
}
|
||||
verifyZipEntries(zipFile, zipMap);
|
||||
zipFile.close();
|
||||
}
|
||||
|
||||
protected void verifyZipEntries(ZipFile zipFile, Map<String, ZipEntry> entries)
|
||||
throws Exception {
|
||||
verifyManifest(zipFile, entries.get("META-INF/MANIFEST.MF"));
|
||||
}
|
||||
|
||||
private void verifyManifest(ZipFile zipFile, ZipEntry zipEntry) throws Exception {
|
||||
Manifest manifest = new Manifest(zipFile.getInputStream(zipEntry));
|
||||
verifyManifest(manifest);
|
||||
}
|
||||
|
||||
protected abstract void verifyManifest(Manifest manifest) throws Exception;
|
||||
|
||||
protected final void assertHasEntryNameStartingWith(
|
||||
Map<String, ZipEntry> entries, String value) {
|
||||
for (String name : entries.keySet()) {
|
||||
if (name.startsWith(value)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Expected entry starting with " + value);
|
||||
}
|
||||
}
|
||||
|
||||
private static class JarArchiveVerification extends AbstractArchiveVerification {
|
||||
|
||||
private String main;
|
||||
|
||||
public JarArchiveVerification(File file, String main) {
|
||||
super(file);
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void verifyZipEntries(ZipFile zipFile, Map<String, ZipEntry> entries)
|
||||
throws Exception {
|
||||
super.verifyZipEntries(zipFile, entries);
|
||||
assertHasEntryNameStartingWith(entries, "lib/spring-context");
|
||||
assertHasEntryNameStartingWith(entries, "lib/spring-core");
|
||||
assertHasEntryNameStartingWith(entries, "lib/javax.servlet-api-3.0.1.jar");
|
||||
assertTrue("Unpacked launcher classes", entries.containsKey("org/"
|
||||
+ "springframework/boot/loader/JarLauncher.class"));
|
||||
assertTrue("Own classes", entries.containsKey("org/"
|
||||
+ "test/SampleApplication.class"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void verifyManifest(Manifest manifest) throws Exception {
|
||||
assertEquals("org.springframework.boot.loader.JarLauncher", manifest
|
||||
.getMainAttributes().getValue("Main-Class"));
|
||||
assertEquals(this.main, manifest.getMainAttributes().getValue("Start-Class"));
|
||||
assertEquals("Foo", manifest.getMainAttributes().getValue("Not-Used"));
|
||||
}
|
||||
}
|
||||
|
||||
private static class WarArchiveVerification extends AbstractArchiveVerification {
|
||||
|
||||
public WarArchiveVerification(File file) {
|
||||
super(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void verifyZipEntries(ZipFile zipFile, Map<String, ZipEntry> entries)
|
||||
throws Exception {
|
||||
super.verifyZipEntries(zipFile, entries);
|
||||
assertHasEntryNameStartingWith(entries, "WEB-INF/lib/spring-context");
|
||||
assertHasEntryNameStartingWith(entries, "WEB-INF/lib/spring-core");
|
||||
assertHasEntryNameStartingWith(entries,
|
||||
"WEB-INF/lib-provided/javax.servlet-api-3.0.1.jar");
|
||||
assertTrue("Unpacked launcher classes", entries.containsKey("org/"
|
||||
+ "springframework/boot/loader/JarLauncher.class"));
|
||||
assertTrue("Own classes", entries.containsKey("WEB-INF/classes/org/"
|
||||
+ "test/SampleApplication.class"));
|
||||
assertTrue("Web content", entries.containsKey("index.html"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void verifyManifest(Manifest manifest) throws Exception {
|
||||
assertEquals("org.springframework.boot.loader.WarLauncher", manifest
|
||||
.getMainAttributes().getValue("Main-Class"));
|
||||
assertEquals("org.test.SampleApplication", manifest.getMainAttributes()
|
||||
.getValue("Start-Class"));
|
||||
assertEquals("Foo", manifest.getMainAttributes().getValue("Not-Used"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.boot.maven.sample;
|
||||
|
||||
/**
|
||||
* Sample class with a main method.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ClassWithMainMethod {
|
||||
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.boot.maven.sample;
|
||||
|
||||
/**
|
||||
* Sample class without a main method.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ClassWithoutMainMethod {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user