Consider jar's Class-Path attribute when getting changeable URLs
To overcome command length limits on Windows, IntelliJ IDEA may launch an application with a single jar on the classpath that contains that application's actual classpath in the Class-Path attribute of its manifest. This would prevent DevTools restarts from working as it only considered the single jar's URL when identifying changeable URLs and ignored the URLs added to the classpath via the jar's manifest. This commit updates ChangeableUrls when it is created from a URLClassLoader to consider the Class-Path manifest attribute of any jars in the class loader's URLs. This allows the full classpath to be considered when identifying URLs that are changeable and that need to be monitored for restart triggering. Closes gh-5127
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2016 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.
|
||||
@@ -17,13 +17,21 @@
|
||||
package org.springframework.boot.devtools.restart;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
@@ -31,6 +39,7 @@ import static org.junit.Assert.assertThat;
|
||||
* Tests for {@link ChangeableUrls}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class ChangeableUrlsTests {
|
||||
|
||||
@@ -64,6 +73,16 @@ public class ChangeableUrlsTests {
|
||||
assertThat(urls.size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void urlsFromJarClassPathAreConsidered() throws Exception {
|
||||
URL projectCore = makeUrl("project-core");
|
||||
URL projectWeb = makeUrl("project-web");
|
||||
ChangeableUrls urls = ChangeableUrls.fromUrlClassLoader(new URLClassLoader(
|
||||
new URL[] { makeJarFileWithUrlsInManifestClassPath(projectCore,
|
||||
projectWeb) }));
|
||||
assertThat(urls.toList(), contains(projectCore, projectWeb));
|
||||
}
|
||||
|
||||
private URL makeUrl(String name) throws IOException {
|
||||
File file = this.temporaryFolder.newFolder();
|
||||
file = new File(file, name);
|
||||
@@ -73,4 +92,15 @@ public class ChangeableUrlsTests {
|
||||
return file.toURI().toURL();
|
||||
}
|
||||
|
||||
private URL makeJarFileWithUrlsInManifestClassPath(URL... urls) throws Exception {
|
||||
File classpathJar = this.temporaryFolder.newFile("classpath.jar");
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(),
|
||||
"1.0");
|
||||
manifest.getMainAttributes().putValue(Attributes.Name.CLASS_PATH.toString(),
|
||||
StringUtils.arrayToDelimitedString(urls, " "));
|
||||
new JarOutputStream(new FileOutputStream(classpathJar), manifest).close();
|
||||
return classpathJar.toURI().toURL();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user