Skip to content

Commit 9dc858c

Browse files
committed
Add missing properties to RepackageTask and improve test coverage
Closes gh-4978
1 parent 36133d9 commit 9dc858c

File tree

6 files changed

+311
-9
lines changed

6 files changed

+311
-9
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Copyright 2012-2015 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 java.io.BufferedReader;
20+
import java.io.File;
21+
import java.io.FileReader;
22+
import java.io.IOException;
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
import java.util.regex.Pattern;
26+
27+
import org.gradle.tooling.ProjectConnection;
28+
import org.junit.BeforeClass;
29+
import org.junit.Test;
30+
31+
import static org.hamcrest.Matchers.is;
32+
import static org.junit.Assert.assertThat;
33+
34+
/**
35+
* Integration tests for creating a fully executable jar with Gradle.
36+
*
37+
* @author Andy Wilkinson
38+
*/
39+
public class FullyExecutableJarTests {
40+
41+
private static final String BOOT_VERSION = Versions.getBootVersion();
42+
43+
private static ProjectConnection project;
44+
45+
@BeforeClass
46+
public static void createProject() throws IOException {
47+
project = new ProjectCreator().createProject("executable-jar");
48+
}
49+
50+
@Test
51+
public void jarIsNotExecutableByDefault() throws IOException {
52+
project.newBuild().forTasks("clean", "build")
53+
.withArguments("-PbootVersion=" + BOOT_VERSION).run();
54+
File buildLibs = new File("target/executable-jar/build/libs");
55+
File executableJar = new File(buildLibs, "executable-jar.jar");
56+
assertThat(isFullyExecutable(executableJar), is(false));
57+
}
58+
59+
@Test
60+
public void madeExecutableViaExtension() throws IOException {
61+
project.newBuild().forTasks("clean", "build").withArguments(
62+
"-PbootVersion=" + BOOT_VERSION, "-PextensionExecutable=true").run();
63+
File buildLibs = new File("target/executable-jar/build/libs");
64+
File executableJar = new File(buildLibs, "executable-jar.jar");
65+
assertThat(isFullyExecutable(executableJar), is(true));
66+
}
67+
68+
@Test
69+
public void madeExecutableViaTask() throws IOException {
70+
project.newBuild().forTasks("clean", "build")
71+
.withArguments("-PbootVersion=" + BOOT_VERSION, "-PtaskExecutable=true")
72+
.run();
73+
File buildLibs = new File("target/executable-jar/build/libs");
74+
File executableJar = new File(buildLibs, "executable-jar.jar");
75+
assertThat(isFullyExecutable(executableJar), is(true));
76+
}
77+
78+
@Test
79+
public void taskTakesPrecedenceForMakingJarExecutable() throws IOException {
80+
project.newBuild().forTasks("clean", "build")
81+
.withArguments("-PbootVersion=" + BOOT_VERSION,
82+
"-PextensionExecutable=false", "-PtaskExecutable=true")
83+
.run();
84+
File buildLibs = new File("target/executable-jar/build/libs");
85+
File executableJar = new File(buildLibs, "executable-jar.jar");
86+
assertThat(isFullyExecutable(executableJar), is(true));
87+
}
88+
89+
@Test
90+
public void scriptPropertiesFromTask() throws IOException {
91+
project.newBuild().forTasks("clean", "build")
92+
.withArguments("-PbootVersion=" + BOOT_VERSION, "-PtaskProperties=true")
93+
.run();
94+
File buildLibs = new File("target/executable-jar/build/libs");
95+
File executableJar = new File(buildLibs, "executable-jar.jar");
96+
assertThat(isFullyExecutable(executableJar), is(true));
97+
assertThat(containsLine("# Provides:.*__task__", executableJar), is(true));
98+
}
99+
100+
@Test
101+
public void scriptPropertiesFromExtension() throws IOException {
102+
project.newBuild().forTasks("clean", "build").withArguments(
103+
"-PbootVersion=" + BOOT_VERSION, "-PextensionProperties=true").run();
104+
File buildLibs = new File("target/executable-jar/build/libs");
105+
File executableJar = new File(buildLibs, "executable-jar.jar");
106+
assertThat(isFullyExecutable(executableJar), is(true));
107+
assertThat(containsLine("# Provides:.*__extension__", executableJar), is(true));
108+
}
109+
110+
@Test
111+
public void taskTakesPrecedenceForScriptProperties() throws IOException {
112+
project.newBuild().forTasks("clean", "build")
113+
.withArguments("-PbootVersion=" + BOOT_VERSION,
114+
"-PextensionProperties=true", "-PtaskProperties=true")
115+
.run();
116+
File buildLibs = new File("target/executable-jar/build/libs");
117+
File executableJar = new File(buildLibs, "executable-jar.jar");
118+
assertThat(isFullyExecutable(executableJar), is(true));
119+
assertThat(containsLine("# Provides:.*__task__", executableJar), is(true));
120+
}
121+
122+
@Test
123+
public void customScriptFromTask() throws IOException {
124+
project.newBuild().forTasks("clean", "build")
125+
.withArguments("-PbootVersion=" + BOOT_VERSION, "-PtaskScript=true")
126+
.run();
127+
File buildLibs = new File("target/executable-jar/build/libs");
128+
File executableJar = new File(buildLibs, "executable-jar.jar");
129+
assertThat(containsLine("Custom task script", executableJar), is(true));
130+
}
131+
132+
@Test
133+
public void customScriptFromExtension() throws IOException {
134+
project.newBuild().forTasks("clean", "build")
135+
.withArguments("-PbootVersion=" + BOOT_VERSION, "-PextensionScript=true")
136+
.run();
137+
File buildLibs = new File("target/executable-jar/build/libs");
138+
File executableJar = new File(buildLibs, "executable-jar.jar");
139+
assertThat(containsLine("Custom extension script", executableJar), is(true));
140+
}
141+
142+
@Test
143+
public void taskTakesPrecedenceForCustomScript() throws IOException {
144+
project.newBuild().forTasks("clean", "build")
145+
.withArguments("-PbootVersion=" + BOOT_VERSION, "-PextensionScript=true",
146+
"-PtaskScript=true")
147+
.run();
148+
File buildLibs = new File("target/executable-jar/build/libs");
149+
File executableJar = new File(buildLibs, "executable-jar.jar");
150+
assertThat(containsLine("Custom task script", executableJar), is(true));
151+
}
152+
153+
private boolean isFullyExecutable(File file) throws IOException {
154+
return containsLine("#!/bin/bash", file);
155+
}
156+
157+
private boolean containsLine(String toMatch, File file) throws IOException {
158+
Pattern pattern = Pattern.compile(toMatch);
159+
for (String line : readLines(file)) {
160+
if (pattern.matcher(line).matches()) {
161+
return true;
162+
}
163+
}
164+
return false;
165+
}
166+
167+
private List<String> readLines(File file) throws IOException {
168+
BufferedReader reader = new BufferedReader(new FileReader(file));
169+
String line;
170+
List<String> lines = new ArrayList<String>();
171+
try {
172+
while ((line = reader.readLine()) != null && lines.size() < 50) {
173+
lines.add(line);
174+
}
175+
}
176+
finally {
177+
reader.close();
178+
}
179+
return lines;
180+
}
181+
182+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
buildscript {
2+
repositories {
3+
mavenLocal()
4+
}
5+
dependencies {
6+
classpath "org.springframework.boot:spring-boot-gradle-plugin:${project.bootVersion}"
7+
}
8+
}
9+
10+
repositories {
11+
mavenLocal()
12+
mavenCentral()
13+
}
14+
15+
apply plugin: 'spring-boot'
16+
apply plugin: 'java'
17+
18+
dependencies {
19+
compile 'org.springframework.boot:spring-boot-starter-freemarker'
20+
compile 'org.springframework.boot:spring-boot-starter-web'
21+
compile 'org.springframework.boot:spring-boot-devtools'
22+
compile files("foo.jar")
23+
}
24+
25+
springBoot {
26+
mainClass = 'foo.bar.Baz'
27+
}
28+
29+
if (project.properties['taskExecutable']) {
30+
bootRepackage.executable = Boolean.valueOf(project.taskExecutable)
31+
}
32+
33+
if (project.properties['extensionExecutable']) {
34+
springBoot.executable = Boolean.valueOf(project.extensionExecutable)
35+
}
36+
37+
if (project.properties['taskProperties']) {
38+
bootRepackage.executable = true
39+
bootRepackage.embeddedLaunchScriptProperties = ['initInfoProvides': '__task__']
40+
}
41+
42+
if (project.properties['extensionProperties']) {
43+
bootRepackage.executable = true
44+
springBoot.embeddedLaunchScriptProperties = ['initInfoProvides': '__extension__']
45+
}
46+
47+
if (project.properties['taskScript']) {
48+
bootRepackage.embeddedLaunchScript = file('task.script')
49+
}
50+
51+
if (project.properties['extensionScript']) {
52+
springBoot.embeddedLaunchScript = file('extension.script')
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Custom extension script
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Custom task script

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2015 the original author or authors.
2+
* Copyright 2012-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -48,6 +48,8 @@ class ProjectLibraries implements Libraries {
4848

4949
private final SpringBootPluginExtension extension;
5050

51+
private final boolean excludeDevtools;
52+
5153
private String providedConfigurationName = "providedRuntime";
5254

5355
private String customConfigurationName = null;
@@ -56,10 +58,13 @@ class ProjectLibraries implements Libraries {
5658
* Create a new {@link ProjectLibraries} instance of the specified {@link Project}.
5759
* @param project the gradle project
5860
* @param extension the extension
61+
* @param excludeDevTools whether Spring Boot Devtools should be excluded
5962
*/
60-
ProjectLibraries(Project project, SpringBootPluginExtension extension) {
63+
ProjectLibraries(Project project, SpringBootPluginExtension extension,
64+
boolean excludeDevTools) {
6165
this.project = project;
6266
this.extension = extension;
67+
this.excludeDevtools = excludeDevTools;
6368
}
6469

6570
/**
@@ -165,7 +170,7 @@ private void libraries(Set<GradleLibrary> libraries, LibraryCallback callback)
165170
}
166171

167172
private boolean isExcluded(GradleLibrary library) {
168-
if (this.extension.isExcludeDevtools() && isDevToolsJar(library)) {
173+
if (this.excludeDevtools && isDevToolsJar(library)) {
169174
return true;
170175
}
171176
return false;

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

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2015 the original author or authors.
2+
* Copyright 2012-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
import java.io.File;
2020
import java.io.IOException;
2121
import java.util.HashSet;
22+
import java.util.Map;
2223
import java.util.Set;
2324
import java.util.concurrent.TimeUnit;
2425

@@ -57,6 +58,14 @@ public class RepackageTask extends DefaultTask {
5758

5859
private File outputFile;
5960

61+
private Boolean excludeDevtools;
62+
63+
private Boolean executable;
64+
65+
private File embeddedLaunchScript;
66+
67+
private Map<String, String> embeddedLaunchScriptProperties;
68+
6069
public void setCustomConfiguration(String customConfiguration) {
6170
this.customConfiguration = customConfiguration;
6271
}
@@ -89,6 +98,39 @@ void setOutputFile(File file) {
8998
this.outputFile = file;
9099
}
91100

101+
public Boolean getExcludeDevtools() {
102+
return this.excludeDevtools;
103+
}
104+
105+
public void setExcludeDevtools(Boolean excludeDevtools) {
106+
this.excludeDevtools = excludeDevtools;
107+
}
108+
109+
public Boolean getExecutable() {
110+
return this.executable;
111+
}
112+
113+
public void setExecutable(Boolean executable) {
114+
this.executable = executable;
115+
}
116+
117+
public File getEmbeddedLaunchScript() {
118+
return this.embeddedLaunchScript;
119+
}
120+
121+
public void setEmbeddedLaunchScript(File embeddedLaunchScript) {
122+
this.embeddedLaunchScript = embeddedLaunchScript;
123+
}
124+
125+
public Map<String, String> getEmbeddedLaunchScriptProperties() {
126+
return this.embeddedLaunchScriptProperties;
127+
}
128+
129+
public void setEmbeddedLaunchScriptProperties(
130+
Map<String, String> embeddedLaunchScriptProperties) {
131+
this.embeddedLaunchScriptProperties = embeddedLaunchScriptProperties;
132+
}
133+
92134
@TaskAction
93135
public void repackage() {
94136
Project project = getProject();
@@ -102,7 +144,9 @@ public ProjectLibraries getLibraries() {
102144
Project project = getProject();
103145
SpringBootPluginExtension extension = project.getExtensions()
104146
.getByType(SpringBootPluginExtension.class);
105-
ProjectLibraries libraries = new ProjectLibraries(project, extension);
147+
ProjectLibraries libraries = new ProjectLibraries(project, extension,
148+
(this.excludeDevtools != null && this.excludeDevtools)
149+
|| extension.isExcludeDevtools());
106150
if (extension.getProvidedConfiguration() != null) {
107151
libraries.setProvidedConfigurationName(extension.getProvidedConfiguration());
108152
}
@@ -223,14 +267,30 @@ else if (this.extension.getMainClass() != null) {
223267
}
224268

225269
private LaunchScript getLaunchScript() throws IOException {
226-
if (this.extension.isExecutable()
227-
|| this.extension.getEmbeddedLaunchScript() != null) {
228-
return new DefaultLaunchScript(this.extension.getEmbeddedLaunchScript(),
229-
this.extension.getEmbeddedLaunchScriptProperties());
270+
if (isExecutable() || getEmbeddedLaunchScript() != null) {
271+
return new DefaultLaunchScript(getEmbeddedLaunchScript(),
272+
getEmbeddedLaunchScriptProperties());
230273
}
231274
return null;
232275
}
233276

277+
private boolean isExecutable() {
278+
return RepackageTask.this.executable != null ? RepackageTask.this.executable
279+
: this.extension.isExecutable();
280+
}
281+
282+
private File getEmbeddedLaunchScript() {
283+
return RepackageTask.this.embeddedLaunchScript != null
284+
? RepackageTask.this.embeddedLaunchScript
285+
: this.extension.getEmbeddedLaunchScript();
286+
}
287+
288+
private Map<String, String> getEmbeddedLaunchScriptProperties() {
289+
return RepackageTask.this.embeddedLaunchScriptProperties != null
290+
? RepackageTask.this.embeddedLaunchScriptProperties
291+
: this.extension.getEmbeddedLaunchScriptProperties();
292+
}
293+
234294
}
235295

236296
/**

0 commit comments

Comments
 (0)