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.
This commit is contained in:
Dave Syer 2014-06-18 16:02:26 +01:00
parent edffabeee4
commit 2433f721bc
6 changed files with 233 additions and 7 deletions

View File

@ -0,0 +1,63 @@
/*
* 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();
}
}

View File

@ -0,0 +1,30 @@
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"
}

View File

@ -0,0 +1,30 @@
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"
}

View File

@ -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

View File

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

View File

@ -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;
}
@ -55,11 +60,19 @@ public class RepackageTask extends DefaultTask {
public void setMainClass(String mainClass) {
this.mainClass = mainClass;
}
public String getMainClass() {
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;
}
}