Skip to content

Commit 9cd1a4b

Browse files
rupert-madden-abbottwilkinsona
authored andcommitted
Fix handling of static resource jars with spaces in their paths
See gh-11991
1 parent 647c6c4 commit 9cd1a4b

File tree

2 files changed

+85
-25
lines changed

2 files changed

+85
-25
lines changed

spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactory.java

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.net.URL;
2323
import java.net.URLClassLoader;
2424
import java.net.URLConnection;
25+
import java.net.URLDecoder;
2526
import java.security.CodeSource;
2627
import java.util.ArrayList;
2728
import java.util.Arrays;
@@ -96,56 +97,64 @@ protected List<URL> getUrlsOfJarsWithMetaInfResources() {
9697
List<URL> staticResourceUrls = new ArrayList<URL>();
9798
if (classLoader instanceof URLClassLoader) {
9899
for (URL url : ((URLClassLoader) classLoader).getURLs()) {
99-
try {
100-
if ("file".equals(url.getProtocol())) {
101-
File file = new File(url.getFile());
102-
if (file.isDirectory()
103-
&& new File(file, "META-INF/resources").isDirectory()) {
104-
staticResourceUrls.add(url);
105-
}
106-
else if (isResourcesJar(file)) {
107-
staticResourceUrls.add(url);
108-
}
109-
}
110-
else {
111-
URLConnection connection = url.openConnection();
112-
if (connection instanceof JarURLConnection) {
113-
if (isResourcesJar((JarURLConnection) connection)) {
114-
staticResourceUrls.add(url);
115-
}
116-
}
117-
}
118-
}
119-
catch (IOException ex) {
120-
throw new IllegalStateException(ex);
100+
if (isStaticResource(url)) {
101+
staticResourceUrls.add(url);
121102
}
122103
}
123104
}
124105
return staticResourceUrls;
125106
}
126107

108+
protected boolean isStaticResource(URL url) {
109+
try {
110+
if ("file".equals(url.getProtocol())) {
111+
File file = new File(URLDecoder.decode(url.getFile(), "UTF-8"));
112+
if (file.isDirectory()
113+
&& new File(file, "META-INF/resources").isDirectory()) {
114+
return true;
115+
}
116+
else if (isResourcesJar(file)) {
117+
return true;
118+
}
119+
}
120+
else {
121+
URLConnection connection = url.openConnection();
122+
if (connection instanceof JarURLConnection) {
123+
if (isResourcesJar((JarURLConnection) connection)) {
124+
return true;
125+
}
126+
}
127+
}
128+
}
129+
catch (IOException ex) {
130+
throw new IllegalStateException(ex);
131+
}
132+
return false;
133+
}
134+
127135
private boolean isResourcesJar(JarURLConnection connection) {
128136
try {
129137
return isResourcesJar(connection.getJarFile());
130138
}
131139
catch (IOException ex) {
140+
logger.warn("Unable to open jar to determine if it contains static resources", ex);
132141
return false;
133142
}
134143
}
135144

136145
private boolean isResourcesJar(File file) {
137146
try {
138-
return isResourcesJar(new JarFile(file));
147+
return file.getName().endsWith(".jar") && isResourcesJar(new JarFile(file));
139148
}
140149
catch (IOException ex) {
150+
logger.warn("Unable to open jar to determine if it contains static resources", ex);
141151
return false;
142152
}
143153
}
144154

145155
private boolean isResourcesJar(JarFile jar) throws IOException {
146156
try {
147-
return jar.getName().endsWith(".jar")
148-
&& (jar.getJarEntry("META-INF/resources") != null);
157+
return jar.getJarEntry("META-INF/resources") != null;
149158
}
150159
finally {
151160
jar.close();

spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.io.File;
2020
import java.io.FileInputStream;
21+
import java.io.FileOutputStream;
2122
import java.io.FileWriter;
2223
import java.io.FilenameFilter;
2324
import java.io.IOException;
@@ -49,6 +50,8 @@
4950
import java.util.concurrent.TimeUnit;
5051
import java.util.concurrent.atomic.AtomicBoolean;
5152
import java.util.concurrent.atomic.AtomicReference;
53+
import java.util.jar.JarEntry;
54+
import java.util.jar.JarOutputStream;
5255
import java.util.zip.GZIPInputStream;
5356

5457
import javax.net.ssl.SSLContext;
@@ -1035,6 +1038,54 @@ public void explodedWarFileDocumentRootWhenRunningFromPackagedWar() throws Excep
10351038
assertThat(documentRoot).isNull();
10361039
}
10371040

1041+
@Test
1042+
public void includeJarWithStaticResources() throws Exception {
1043+
AbstractEmbeddedServletContainerFactory factory = getFactory();
1044+
File jarFile = this.temporaryFolder.newFile("test.jar");
1045+
JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(jarFile));
1046+
JarEntry jarEntry = new JarEntry("META-INF/resources");
1047+
jarOutputStream.putNextEntry(jarEntry);
1048+
jarOutputStream.closeEntry();
1049+
jarOutputStream.close();
1050+
String path = "file:" + jarFile.getAbsolutePath();
1051+
1052+
boolean isStaticResource = factory.isStaticResource(new URL(path));
1053+
1054+
assertThat(isStaticResource).isTrue();
1055+
}
1056+
1057+
@Test
1058+
public void includeJarWithStaticResourcesWithUrlEncodedSpaces() throws Exception {
1059+
AbstractEmbeddedServletContainerFactory factory = getFactory();
1060+
this.temporaryFolder.newFolder("test parent");
1061+
File jarFile = this.temporaryFolder.newFile("test parent/test.jar");
1062+
JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(jarFile));
1063+
JarEntry jarEntry = new JarEntry("META-INF/resources");
1064+
jarOutputStream.putNextEntry(jarEntry);
1065+
jarOutputStream.closeEntry();
1066+
jarOutputStream.close();
1067+
String path = "file:" + jarFile.getAbsolutePath().replaceAll(" ", "%20");
1068+
1069+
boolean isStaticResource = factory.isStaticResource(new URL(path));
1070+
1071+
assertThat(isStaticResource).isTrue();
1072+
}
1073+
1074+
@Test
1075+
public void excludeJarWithoutStaticResources() throws Exception {
1076+
AbstractEmbeddedServletContainerFactory factory = getFactory();
1077+
File jarFile = this.temporaryFolder.newFile("test.jar");
1078+
JarOutputStream jarOutputStream = new JarOutputStream(
1079+
new FileOutputStream(jarFile));
1080+
jarOutputStream.closeEntry();
1081+
jarOutputStream.close();
1082+
String path = "file:" + jarFile.getAbsolutePath();
1083+
1084+
boolean isStaticResource = factory.isStaticResource(new URL(path));
1085+
1086+
assertThat(isStaticResource).isFalse();
1087+
}
1088+
10381089
protected abstract void addConnector(int port,
10391090
AbstractEmbeddedServletContainerFactory factory);
10401091

0 commit comments

Comments
 (0)