Skip to content

Commit 35b7a16

Browse files
committed
Merge branch '1.5.x'
2 parents 52b40ee + 3cc0055 commit 35b7a16

File tree

7 files changed

+143
-16
lines changed

7 files changed

+143
-16
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ private void configureDocumentRoot(WebAppContext handler) {
287287

288288
private Resource createResource(URL url) throws IOException {
289289
if ("file".equals(url.getProtocol())) {
290-
File file = new File(url.getFile());
290+
File file = new File(getDecodedFile(url));
291291
if (file.isFile()) {
292292
return Resource.newResource("jar:" + url + "!/META-INF/resources");
293293
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ public void lifecycleEvent(LifecycleEvent event) {
682682

683683
private void addResourceJars(List<URL> resourceJarUrls) {
684684
for (URL url : resourceJarUrls) {
685-
String file = url.getFile();
685+
String file = getDecodedFile(url);
686686
if (file.endsWith(".jar") || file.endsWith(".jar!/")) {
687687
String jar = url.toString();
688688
if (!jar.startsWith("jar:")) {

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ private ResourceManager getDocumentRootResourceManager() {
367367
: new LoaderHidingResourceManager(rootResourceManager));
368368
for (URL url : metaInfResourceUrls) {
369369
if ("file".equals(url.getProtocol())) {
370-
File file = new File(url.getFile());
370+
File file = new File(getDecodedFile(url));
371371
if (file.isFile()) {
372372
try {
373373
resourceJarUrls.add(new URL("jar:" + url + "!/"));

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactory.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
package org.springframework.boot.web.servlet.server;
1818

1919
import java.io.File;
20+
import java.io.UnsupportedEncodingException;
2021
import java.net.URL;
22+
import java.net.URLDecoder;
2123
import java.nio.charset.Charset;
2224
import java.util.ArrayList;
2325
import java.util.Arrays;
@@ -280,6 +282,16 @@ protected final List<URL> getUrlsOfJarsWithMetaInfResources() {
280282
return this.staticResourceJars.getUrls();
281283
}
282284

285+
protected final String getDecodedFile(URL url) {
286+
try {
287+
return URLDecoder.decode(url.getFile(), "UTF-8");
288+
}
289+
catch (UnsupportedEncodingException ex) {
290+
throw new IllegalStateException(
291+
"Failed to decode '" + url.getFile() + "' using UTF-8");
292+
}
293+
}
294+
283295
protected final File getValidSessionStoreDir() {
284296
return getValidSessionStoreDir(true);
285297
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/server/StaticResourceJars.java

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@
1818

1919
import java.io.File;
2020
import java.io.IOException;
21+
import java.io.UnsupportedEncodingException;
2122
import java.lang.management.ManagementFactory;
2223
import java.net.JarURLConnection;
2324
import java.net.MalformedURLException;
2425
import java.net.URL;
2526
import java.net.URLClassLoader;
2627
import java.net.URLConnection;
28+
import java.net.URLDecoder;
2729
import java.util.ArrayList;
2830
import java.util.List;
2931
import java.util.jar.JarFile;
32+
import java.util.stream.Stream;
3033

3134
/**
3235
* Logic to extract URLs of static resource jars (those containing
@@ -37,21 +40,25 @@
3740
*/
3841
class StaticResourceJars {
3942

40-
public final List<URL> getUrls() {
43+
List<URL> getUrls() {
4144
ClassLoader classLoader = getClass().getClassLoader();
42-
List<URL> urls = new ArrayList<>();
4345
if (classLoader instanceof URLClassLoader) {
44-
for (URL url : ((URLClassLoader) classLoader).getURLs()) {
45-
addUrl(urls, url);
46-
}
46+
return getUrlsFrom(((URLClassLoader) classLoader).getURLs());
4747
}
4848
else {
49-
for (String entry : ManagementFactory.getRuntimeMXBean().getClassPath()
50-
.split(File.pathSeparator)) {
51-
addUrl(urls, toUrl(entry));
52-
}
49+
return getUrlsFrom(Stream
50+
.of(ManagementFactory.getRuntimeMXBean().getClassPath()
51+
.split(File.pathSeparator))
52+
.map(this::toUrl).toArray(URL[]::new));
53+
}
54+
}
55+
56+
List<URL> getUrlsFrom(URL... urls) {
57+
List<URL> resourceJarUrls = new ArrayList<>();
58+
for (URL url : urls) {
59+
addUrl(resourceJarUrls, url);
5360
}
54-
return urls;
61+
return resourceJarUrls;
5562
}
5663

5764
private URL toUrl(String classPathEntry) {
@@ -67,7 +74,7 @@ private URL toUrl(String classPathEntry) {
6774
private void addUrl(List<URL> urls, URL url) {
6875
try {
6976
if ("file".equals(url.getProtocol())) {
70-
addUrlFile(urls, url, new File(url.getFile()));
77+
addUrlFile(urls, url, new File(getDecodedFile(url)));
7178
}
7279
else {
7380
addUrlConnection(urls, url, url.openConnection());
@@ -78,6 +85,16 @@ private void addUrl(List<URL> urls, URL url) {
7885
}
7986
}
8087

88+
private String getDecodedFile(URL url) {
89+
try {
90+
return URLDecoder.decode(url.getFile(), "UTF-8");
91+
}
92+
catch (UnsupportedEncodingException ex) {
93+
throw new IllegalStateException(
94+
"Failed to decode '" + url.getFile() + "' using UTF-8");
95+
}
96+
}
97+
8198
private void addUrlFile(List<URL> urls, URL url, File file) {
8299
if ((file.isDirectory() && new File(file, "META-INF/resources").isDirectory())
83100
|| isResourcesJar(file)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2012-2018 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.web.servlet.server;
18+
19+
import java.io.File;
20+
import java.io.FileOutputStream;
21+
import java.io.IOException;
22+
import java.net.URL;
23+
import java.util.List;
24+
import java.util.function.Consumer;
25+
import java.util.jar.JarEntry;
26+
import java.util.jar.JarOutputStream;
27+
28+
import org.junit.Rule;
29+
import org.junit.Test;
30+
import org.junit.rules.TemporaryFolder;
31+
32+
import static org.assertj.core.api.Assertions.assertThat;
33+
34+
/**
35+
* Tests for {@link StaticResourceJars}.
36+
*
37+
* @author Rupert Madden-Abbott
38+
* @author Andy Wilkinson
39+
*/
40+
public class StaticResourceJarsTests {
41+
42+
@Rule
43+
public final TemporaryFolder temporaryFolder = new TemporaryFolder();
44+
45+
@Test
46+
public void includeJarWithStaticResources() throws Exception {
47+
File jarFile = createResourcesJar("test-resources.jar");
48+
List<URL> staticResourceJarUrls = new StaticResourceJars()
49+
.getUrlsFrom(jarFile.toURI().toURL());
50+
assertThat(staticResourceJarUrls).hasSize(1);
51+
}
52+
53+
@Test
54+
public void includeJarWithStaticResourcesWithUrlEncodedSpaces() throws Exception {
55+
File jarFile = createResourcesJar("test resources.jar");
56+
List<URL> staticResourceJarUrls = new StaticResourceJars()
57+
.getUrlsFrom(jarFile.toURI().toURL());
58+
assertThat(staticResourceJarUrls).hasSize(1);
59+
}
60+
61+
@Test
62+
public void excludeJarWithoutStaticResources() throws Exception {
63+
File jarFile = createJar("dependency.jar");
64+
List<URL> staticResourceJarUrls = new StaticResourceJars()
65+
.getUrlsFrom(jarFile.toURI().toURL());
66+
assertThat(staticResourceJarUrls).hasSize(0);
67+
}
68+
69+
private File createResourcesJar(String name) throws IOException {
70+
return createJar(name, (output) -> {
71+
JarEntry jarEntry = new JarEntry("META-INF/resources");
72+
try {
73+
output.putNextEntry(jarEntry);
74+
output.closeEntry();
75+
}
76+
catch (IOException ex) {
77+
throw new RuntimeException(ex);
78+
}
79+
});
80+
}
81+
82+
private File createJar(String name) throws IOException {
83+
return createJar(name, null);
84+
}
85+
86+
private File createJar(String name, Consumer<JarOutputStream> customizer)
87+
throws IOException {
88+
File jarFile = this.temporaryFolder.newFile(name);
89+
JarOutputStream jarOutputStream = new JarOutputStream(
90+
new FileOutputStream(jarFile));
91+
if (customizer != null) {
92+
customizer.accept(jarOutputStream);
93+
}
94+
jarOutputStream.close();
95+
return jarFile;
96+
}
97+
98+
}

spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/src/test/java/org/springframework/boot/context/embedded/IdeApplicationLauncher.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2017 the original author or authors.
2+
* Copyright 2012-2018 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.
@@ -40,7 +40,7 @@
4040
*/
4141
class IdeApplicationLauncher extends AbstractApplicationLauncher {
4242

43-
private final File exploded = new File("target/ide");
43+
private final File exploded = new File("target/ide application");
4444

4545
IdeApplicationLauncher(ApplicationBuilder applicationBuilder) {
4646
super(applicationBuilder);

0 commit comments

Comments
 (0)