Fix detection of application home for paths containing spaces

Fixes gh-20531
This commit is contained in:
Andy Wilkinson 2020-03-17 12:41:26 +00:00
parent f251772e17
commit b51c7386aa
2 changed files with 85 additions and 3 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
@ -20,6 +20,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.security.CodeSource;
@ -116,12 +117,12 @@ public class ApplicationHome {
return false;
}
private File findSource(URL location) throws IOException {
private File findSource(URL location) throws IOException, URISyntaxException {
URLConnection connection = location.openConnection();
if (connection instanceof JarURLConnection) {
return getRootJarFile(((JarURLConnection) connection).getJarFile());
}
return new File(location.getPath());
return new File(location.toURI());
}
private File getRootJarFile(JarFile jarFile) {

View File

@ -0,0 +1,81 @@
/*
* Copyright 2012-2020 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
*
* https://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.system;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import net.bytebuddy.ByteBuddy;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.util.FileCopyUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ApplicationHome}.
*
* @author Andy Wilkinson
*/
public class ApplicationHomeTests {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Test
public void whenSourceClassIsProvidedThenApplicationHomeReflectsItsLocation() throws Exception {
File app = this.temporaryFolder.newFolder("app");
ApplicationHome applicationHome = createApplicationHome(app);
assertThat(applicationHome.getDir()).isEqualTo(app);
}
@Test
public void whenSourceClassIsProvidedWithSpaceInItsPathThenApplicationHomeReflectsItsLocation() throws Exception {
File app = this.temporaryFolder.newFolder("app location");
ApplicationHome applicationHome = createApplicationHome(app);
assertThat(applicationHome.getDir()).isEqualTo(app);
}
private ApplicationHome createApplicationHome(File location) throws Exception {
File examplePackage = new File(location, "com/example");
examplePackage.mkdirs();
FileCopyUtils.copy(
new ByteArrayInputStream(
new ByteBuddy().subclass(Object.class).name("com.example.Source").make().getBytes()),
new FileOutputStream(new File(examplePackage, "Source.class")));
try (URLClassLoader classLoader = new URLClassLoader(new URL[] { location.toURI().toURL() })) {
Class<?> sourceClass = classLoader.loadClass("com.example.Source");
// Separate thread to bypass stack-based unit test detection in
// ApplicationHome
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
return executor.submit(() -> new ApplicationHome(sourceClass)).get();
}
finally {
executor.shutdown();
}
}
}
}