Skip to content

Commit 2433f72

Browse files
author
Dave Syer
committed
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.
1 parent edffabe commit 2433f72

File tree

6 files changed

+233
-7
lines changed

6 files changed

+233
-7
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2012-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.gradle;
18+
19+
import static org.junit.Assert.assertNotNull;
20+
21+
import java.util.jar.JarFile;
22+
23+
import org.gradle.tooling.ProjectConnection;
24+
import org.junit.Test;
25+
import org.springframework.boot.dependency.tools.ManagedDependencies;
26+
27+
/**
28+
* Tests for using the Gradle plugin's support for installing artifacts
29+
*
30+
* @author Dave Syer
31+
*/
32+
public class ClassifierTests {
33+
34+
private ProjectConnection project;
35+
36+
private static final String BOOT_VERSION = ManagedDependencies.get().find(
37+
"spring-boot").getVersion();
38+
39+
@Test
40+
public void classifierInBootTask() throws Exception {
41+
project = new ProjectCreator().createProject("classifier");
42+
project.newBuild().forTasks("build").withArguments(
43+
"-PbootVersion=" + BOOT_VERSION, "--stacktrace").run();
44+
checkFilesExist("classifier");
45+
}
46+
47+
@Test
48+
public void classifierInBootExtension() throws Exception {
49+
project = new ProjectCreator().createProject("classifier-extension");
50+
project.newBuild().forTasks("build").withArguments(
51+
"-PbootVersion=" + BOOT_VERSION, "--stacktrace", "--info").run();
52+
}
53+
54+
private void checkFilesExist(String name) throws Exception {
55+
JarFile jar = new JarFile("target/" + name + "/build/libs/" + name + ".jar");
56+
assertNotNull(jar.getManifest());
57+
jar.close();
58+
jar = new JarFile("target/" + name + "/build/libs/" + name + "-exec.jar");
59+
assertNotNull(jar.getManifest());
60+
jar.close();
61+
}
62+
63+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
buildscript {
2+
repositories {
3+
mavenLocal()
4+
}
5+
dependencies {
6+
classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.bootVersion}")
7+
}
8+
}
9+
10+
apply plugin: 'java'
11+
apply plugin: 'maven'
12+
apply plugin: 'spring-boot'
13+
14+
jar {
15+
baseName = 'classifier-extension'
16+
}
17+
18+
springBoot {
19+
classifier = 'exec'
20+
mainClass = 'demo.Application'
21+
}
22+
23+
repositories {
24+
mavenLocal()
25+
mavenCentral()
26+
}
27+
28+
dependencies {
29+
compile "org.springframework:spring-core"
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
buildscript {
2+
repositories {
3+
mavenLocal()
4+
}
5+
dependencies {
6+
classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.bootVersion}")
7+
}
8+
}
9+
10+
apply plugin: 'java'
11+
apply plugin: 'maven'
12+
apply plugin: 'spring-boot'
13+
14+
jar {
15+
baseName = 'classifier'
16+
}
17+
18+
bootRepackage {
19+
classifier = 'exec'
20+
mainClass = 'demo.Application'
21+
}
22+
23+
repositories {
24+
mavenLocal()
25+
mavenCentral()
26+
}
27+
28+
dependencies {
29+
compile "org.springframework:spring-core"
30+
}

spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/SpringBootPluginExtension.groovy

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,20 @@ public class SpringBootPluginExtension {
5858
}
5959

6060
/**
61-
* The main class that should be run. If not specified the value from the
62-
* MANIFEST will be used, or if no manifest entry is the archive will be
61+
* The main class that should be run. Instead of setting this explicitly you can use the
62+
* 'mainClassName' of the project or the 'main' of the 'run' task. If not specified the
63+
* value from the MANIFEST will be used, or if no manifest entry is the archive will be
6364
* searched for a suitable class.
6465
*/
6566
String mainClass
6667

68+
/**
69+
* The classifier (file name part before the extension). Instead of setting this explicitly
70+
* you can use the 'classifier' property of the 'bootRepackage' task. If not specified the archive
71+
* will be replaced instead of renamed.
72+
*/
73+
String classifier
74+
6775
/**
6876
* The name of the ivy configuration name to treat as 'provided' (when packaging
6977
* those dependencies in a separate path). If not specified 'providedRuntime' will

spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/repackage/RepackagePluginFeatures.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,17 @@
1616

1717
package org.springframework.boot.gradle.repackage;
1818

19+
import java.io.File;
20+
21+
import org.gradle.api.Action;
1922
import org.gradle.api.Project;
2023
import org.gradle.api.Task;
2124
import org.gradle.api.artifacts.Dependency;
2225
import org.gradle.api.plugins.BasePlugin;
26+
import org.gradle.api.tasks.bundling.Jar;
2327
import org.springframework.boot.gradle.PluginFeatures;
28+
import org.springframework.boot.gradle.SpringBootPluginExtension;
29+
import org.springframework.util.StringUtils;
2430

2531
/**
2632
* {@link PluginFeatures} to add repackage support.
@@ -47,9 +53,19 @@ private void addRepackageTask(Project project) {
4753
task.dependsOn(project.getConfigurations()
4854
.getByName(Dependency.ARCHIVES_CONFIGURATION).getAllArtifacts()
4955
.getBuildDependencies());
56+
registerOutput(project, task);
5057
ensureTaskRunsOnAssembly(project, task);
5158
}
5259

60+
private void registerOutput(Project project, final RepackageTask task) {
61+
project.afterEvaluate(new Action<Project>() {
62+
@Override
63+
public void execute(Project project) {
64+
project.getTasks().withType(Jar.class, new OutputAction(task));
65+
}
66+
});
67+
}
68+
5369
private void ensureTaskRunsOnAssembly(Project project, Task task) {
5470
project.getTasks().getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(task);
5571
}
@@ -62,4 +78,51 @@ private void registerRepackageTaskProperty(Project project) {
6278
.set("BootRepackage", RepackageTask.class);
6379
}
6480

81+
private class OutputAction implements Action<Jar> {
82+
83+
private RepackageTask task;
84+
85+
public OutputAction(RepackageTask task) {
86+
this.task = task;
87+
}
88+
89+
@Override
90+
public void execute(Jar archive) {
91+
if ("".equals(archive.getClassifier())) {
92+
setClassifier(task, archive);
93+
File file = archive.getArchivePath();
94+
String classifier = task.getClassifier();
95+
if (classifier != null) {
96+
String withClassifer = file.getName();
97+
withClassifer = StringUtils.stripFilenameExtension(withClassifer)
98+
+ "-" + classifier + "."
99+
+ StringUtils.getFilenameExtension(withClassifer);
100+
File out = new File(file.getParentFile(), withClassifer);
101+
file = out;
102+
task.getOutputs().file(file);
103+
task.setOutputFile(file);
104+
}
105+
}
106+
107+
}
108+
109+
private void setClassifier(RepackageTask task, Jar archive) {
110+
Project project = task.getProject();
111+
String classifier = null;
112+
SpringBootPluginExtension extension = project.getExtensions().getByType(
113+
SpringBootPluginExtension.class);
114+
if (task.getClassifier() != null) {
115+
classifier = task.getClassifier();
116+
}
117+
else if (extension.getClassifier() != null) {
118+
classifier = extension.getClassifier();
119+
}
120+
if (classifier != null) {
121+
project.getLogger().info("Setting classifier: " + classifier);
122+
task.setClassifier(classifier);
123+
}
124+
}
125+
126+
}
127+
65128
}

spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/repackage/RepackageTask.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.gradle.api.tasks.bundling.Jar;
2828
import org.springframework.boot.gradle.SpringBootPluginExtension;
2929
import org.springframework.boot.loader.tools.Repackager;
30+
import org.springframework.util.FileCopyUtils;
3031

3132
/**
3233
* Repackage task.
@@ -44,6 +45,10 @@ public class RepackageTask extends DefaultTask {
4445

4546
private String mainClass;
4647

48+
private String classifier;
49+
50+
private File outputFile;
51+
4752
public void setCustomConfiguration(String customConfiguration) {
4853
this.customConfiguration = customConfiguration;
4954
}
@@ -55,11 +60,19 @@ public void setWithJarTask(Object withJarTask) {
5560
public void setMainClass(String mainClass) {
5661
this.mainClass = mainClass;
5762
}
58-
63+
5964
public String getMainClass() {
6065
return mainClass;
6166
}
6267

68+
public String getClassifier() {
69+
return classifier;
70+
}
71+
72+
public void setClassifier(String classifier) {
73+
this.classifier = classifier;
74+
}
75+
6376
@TaskAction
6477
public void repackage() {
6578
Project project = getProject();
@@ -102,13 +115,24 @@ public void execute(Jar archive) {
102115
File file = archive.getArchivePath();
103116
if (file.exists()) {
104117
Repackager repackager = new LoggingRepackager(file);
118+
File out = RepackageTask.this.outputFile;
119+
if (out != null) {
120+
try {
121+
FileCopyUtils.copy(file, out);
122+
}
123+
catch (IOException e) {
124+
throw new IllegalStateException(e.getMessage(), e);
125+
}
126+
file = out;
127+
}
128+
RepackageTask.this.outputFile = file;
105129
setMainClass(repackager);
106130
if (this.extension.convertLayout() != null) {
107131
repackager.setLayout(this.extension.convertLayout());
108132
}
109133
repackager.setBackupSource(this.extension.isBackupSource());
110134
try {
111-
repackager.repackage(this.libraries);
135+
repackager.repackage(file, this.libraries);
112136
}
113137
catch (IOException ex) {
114138
throw new IllegalStateException(ex.getMessage(), ex);
@@ -121,10 +145,13 @@ private void setMainClass(Repackager repackager) {
121145
String mainClass = (String) getProject().property("mainClassName");
122146
if (RepackageTask.this.mainClass != null) {
123147
mainClass = RepackageTask.this.mainClass;
124-
} else if (this.extension.getMainClass() != null) {
148+
}
149+
else if (this.extension.getMainClass() != null) {
125150
mainClass = this.extension.getMainClass();
126-
} else if (getProject().getTasks().getByName("run").hasProperty("main")) {
127-
mainClass = (String) getProject().getTasks().getByName("run").property("main");
151+
}
152+
else if (getProject().getTasks().getByName("run").hasProperty("main")) {
153+
mainClass = (String) getProject().getTasks().getByName("run")
154+
.property("main");
128155
}
129156
getLogger().info("Setting mainClass: " + mainClass);
130157
repackager.setMainClass(mainClass);
@@ -154,4 +181,9 @@ protected String findMainMethod(java.util.jar.JarFile source) throws IOException
154181
}
155182
};
156183
}
184+
185+
void setOutputFile(File file) {
186+
this.outputFile = file;
187+
}
188+
157189
}

0 commit comments

Comments
 (0)