Commit 2433f721 authored by Dave Syer's avatar Dave Syer

Add 'classifier' property to Gradle plugin

The default behaviour doesn't change with this commit, but now
the user has the option to specify a 'classifier' property
either in springBoot { classifier = 'exec' } (i.e. globally
for all repackage tasks) or in each repackage task, e.g.
bootRepackage { classifier = 'exec' }. In that case the original
archive is not overwritten but copied into <file>-<classifier>.jar
(or .war etc.) and then enhanced.

Fixes gh-1113, fixes gh-141 also I believe.
parent edffabee
/*
* Copyright 2012-2014 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.gradle;
import static org.junit.Assert.assertNotNull;
import java.util.jar.JarFile;
import org.gradle.tooling.ProjectConnection;
import org.junit.Test;
import org.springframework.boot.dependency.tools.ManagedDependencies;
/**
* Tests for using the Gradle plugin's support for installing artifacts
*
* @author Dave Syer
*/
public class ClassifierTests {
private ProjectConnection project;
private static final String BOOT_VERSION = ManagedDependencies.get().find(
"spring-boot").getVersion();
@Test
public void classifierInBootTask() throws Exception {
project = new ProjectCreator().createProject("classifier");
project.newBuild().forTasks("build").withArguments(
"-PbootVersion=" + BOOT_VERSION, "--stacktrace").run();
checkFilesExist("classifier");
}
@Test
public void classifierInBootExtension() throws Exception {
project = new ProjectCreator().createProject("classifier-extension");
project.newBuild().forTasks("build").withArguments(
"-PbootVersion=" + BOOT_VERSION, "--stacktrace", "--info").run();
}
private void checkFilesExist(String name) throws Exception {
JarFile jar = new JarFile("target/" + name + "/build/libs/" + name + ".jar");
assertNotNull(jar.getManifest());
jar.close();
jar = new JarFile("target/" + name + "/build/libs/" + name + "-exec.jar");
assertNotNull(jar.getManifest());
jar.close();
}
}
buildscript {
repositories {
mavenLocal()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.bootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'spring-boot'
jar {
baseName = 'classifier-extension'
}
springBoot {
classifier = 'exec'
mainClass = 'demo.Application'
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile "org.springframework:spring-core"
}
buildscript {
repositories {
mavenLocal()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.bootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'spring-boot'
jar {
baseName = 'classifier'
}
bootRepackage {
classifier = 'exec'
mainClass = 'demo.Application'
}
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile "org.springframework:spring-core"
}
......@@ -58,12 +58,20 @@ public class SpringBootPluginExtension {
}
/**
* The main class that should be run. If not specified the value from the
* MANIFEST will be used, or if no manifest entry is the archive will be
* The main class that should be run. Instead of setting this explicitly you can use the
* 'mainClassName' of the project or the 'main' of the 'run' task. If not specified the
* value from the MANIFEST will be used, or if no manifest entry is the archive will be
* searched for a suitable class.
*/
String mainClass
/**
* The classifier (file name part before the extension). Instead of setting this explicitly
* you can use the 'classifier' property of the 'bootRepackage' task. If not specified the archive
* will be replaced instead of renamed.
*/
String classifier
/**
* The name of the ivy configuration name to treat as 'provided' (when packaging
* those dependencies in a separate path). If not specified 'providedRuntime' will
......
......@@ -16,11 +16,17 @@
package org.springframework.boot.gradle.repackage;
import java.io.File;
import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.plugins.BasePlugin;
import org.gradle.api.tasks.bundling.Jar;
import org.springframework.boot.gradle.PluginFeatures;
import org.springframework.boot.gradle.SpringBootPluginExtension;
import org.springframework.util.StringUtils;
/**
* {@link PluginFeatures} to add repackage support.
......@@ -47,9 +53,19 @@ public class RepackagePluginFeatures implements PluginFeatures {
task.dependsOn(project.getConfigurations()
.getByName(Dependency.ARCHIVES_CONFIGURATION).getAllArtifacts()
.getBuildDependencies());
registerOutput(project, task);
ensureTaskRunsOnAssembly(project, task);
}
private void registerOutput(Project project, final RepackageTask task) {
project.afterEvaluate(new Action<Project>() {
@Override
public void execute(Project project) {
project.getTasks().withType(Jar.class, new OutputAction(task));
}
});
}
private void ensureTaskRunsOnAssembly(Project project, Task task) {
project.getTasks().getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(task);
}
......@@ -62,4 +78,51 @@ public class RepackagePluginFeatures implements PluginFeatures {
.set("BootRepackage", RepackageTask.class);
}
private class OutputAction implements Action<Jar> {
private RepackageTask task;
public OutputAction(RepackageTask task) {
this.task = task;
}
@Override
public void execute(Jar archive) {
if ("".equals(archive.getClassifier())) {
setClassifier(task, archive);
File file = archive.getArchivePath();
String classifier = task.getClassifier();
if (classifier != null) {
String withClassifer = file.getName();
withClassifer = StringUtils.stripFilenameExtension(withClassifer)
+ "-" + classifier + "."
+ StringUtils.getFilenameExtension(withClassifer);
File out = new File(file.getParentFile(), withClassifer);
file = out;
task.getOutputs().file(file);
task.setOutputFile(file);
}
}
}
private void setClassifier(RepackageTask task, Jar archive) {
Project project = task.getProject();
String classifier = null;
SpringBootPluginExtension extension = project.getExtensions().getByType(
SpringBootPluginExtension.class);
if (task.getClassifier() != null) {
classifier = task.getClassifier();
}
else if (extension.getClassifier() != null) {
classifier = extension.getClassifier();
}
if (classifier != null) {
project.getLogger().info("Setting classifier: " + classifier);
task.setClassifier(classifier);
}
}
}
}
......@@ -27,6 +27,7 @@ import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.bundling.Jar;
import org.springframework.boot.gradle.SpringBootPluginExtension;
import org.springframework.boot.loader.tools.Repackager;
import org.springframework.util.FileCopyUtils;
/**
* Repackage task.
......@@ -44,6 +45,10 @@ public class RepackageTask extends DefaultTask {
private String mainClass;
private String classifier;
private File outputFile;
public void setCustomConfiguration(String customConfiguration) {
this.customConfiguration = customConfiguration;
}
......@@ -60,6 +65,14 @@ public class RepackageTask extends DefaultTask {
return mainClass;
}
public String getClassifier() {
return classifier;
}
public void setClassifier(String classifier) {
this.classifier = classifier;
}
@TaskAction
public void repackage() {
Project project = getProject();
......@@ -102,13 +115,24 @@ public class RepackageTask extends DefaultTask {
File file = archive.getArchivePath();
if (file.exists()) {
Repackager repackager = new LoggingRepackager(file);
File out = RepackageTask.this.outputFile;
if (out != null) {
try {
FileCopyUtils.copy(file, out);
}
catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
file = out;
}
RepackageTask.this.outputFile = file;
setMainClass(repackager);
if (this.extension.convertLayout() != null) {
repackager.setLayout(this.extension.convertLayout());
}
repackager.setBackupSource(this.extension.isBackupSource());
try {
repackager.repackage(this.libraries);
repackager.repackage(file, this.libraries);
}
catch (IOException ex) {
throw new IllegalStateException(ex.getMessage(), ex);
......@@ -121,10 +145,13 @@ public class RepackageTask extends DefaultTask {
String mainClass = (String) getProject().property("mainClassName");
if (RepackageTask.this.mainClass != null) {
mainClass = RepackageTask.this.mainClass;
} else if (this.extension.getMainClass() != null) {
}
else if (this.extension.getMainClass() != null) {
mainClass = this.extension.getMainClass();
} else if (getProject().getTasks().getByName("run").hasProperty("main")) {
mainClass = (String) getProject().getTasks().getByName("run").property("main");
}
else if (getProject().getTasks().getByName("run").hasProperty("main")) {
mainClass = (String) getProject().getTasks().getByName("run")
.property("main");
}
getLogger().info("Setting mainClass: " + mainClass);
repackager.setMainClass(mainClass);
......@@ -154,4 +181,9 @@ public class RepackageTask extends DefaultTask {
}
};
}
void setOutputFile(File file) {
this.outputFile = file;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment