Skip to content

Commit 8e7a6ce

Browse files
committed
Polish "Make dev tools' home directory configurable"
See gh-17924
1 parent b9dbfad commit 8e7a6ce

File tree

3 files changed

+83
-41
lines changed

3 files changed

+83
-41
lines changed

spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessor.java

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@
2323
import java.util.Collections;
2424
import java.util.HashSet;
2525
import java.util.List;
26+
import java.util.Map;
27+
import java.util.Properties;
2628
import java.util.Set;
2729
import java.util.function.Function;
30+
import java.util.function.Supplier;
2831

2932
import org.springframework.boot.SpringApplication;
3033
import org.springframework.boot.devtools.system.DevToolsEnablementDeducer;
@@ -59,6 +62,10 @@ public class DevToolsHomePropertiesPostProcessor implements EnvironmentPostProce
5962

6063
private static final Set<PropertySourceLoader> PROPERTY_SOURCE_LOADERS;
6164

65+
private final Properties systemProperties;
66+
67+
private final Map<String, String> environmentVariables;
68+
6269
static {
6370
Set<PropertySourceLoader> propertySourceLoaders = new HashSet<>();
6471
propertySourceLoaders.add(new PropertiesPropertySourceLoader());
@@ -68,6 +75,15 @@ public class DevToolsHomePropertiesPostProcessor implements EnvironmentPostProce
6875
PROPERTY_SOURCE_LOADERS = Collections.unmodifiableSet(propertySourceLoaders);
6976
}
7077

78+
public DevToolsHomePropertiesPostProcessor() {
79+
this(System.getenv(), System.getProperties());
80+
}
81+
82+
DevToolsHomePropertiesPostProcessor(Map<String, String> environmentVariables, Properties systemProperties) {
83+
this.environmentVariables = environmentVariables;
84+
this.systemProperties = systemProperties;
85+
}
86+
7187
@Override
7288
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
7389
if (DevToolsEnablementDeducer.shouldEnable(Thread.currentThread())) {
@@ -93,7 +109,7 @@ private String getPropertySourceName(File file) {
93109

94110
private void addPropertySource(List<PropertySource<?>> propertySources, String fileName,
95111
Function<File, String> propertySourceNamer) {
96-
File home = getProjectRootFolder();
112+
File home = getHomeDirectory();
97113
File file = (home != null) ? new File(home, fileName) : null;
98114
FileSystemResource resource = (file != null) ? new FileSystemResource(file) : null;
99115
if (resource != null && resource.exists() && resource.isFile()) {
@@ -121,21 +137,19 @@ private boolean canLoadFileExtension(PropertySourceLoader loader, String name) {
121137
.anyMatch((fileExtension) -> StringUtils.endsWithIgnoreCase(name, fileExtension));
122138
}
123139

124-
protected File getProjectRootFolder() {
125-
String rootFolder = System.getenv("PROJECT_ROOT_FOLDER");
126-
if (rootFolder == null) {
127-
rootFolder = System.getProperty("PROJECT_ROOT_FOLDER");
128-
}
129-
if (StringUtils.hasLength(rootFolder)) {
130-
return new File(rootFolder);
131-
}
132-
return getHomeDirectory();
140+
protected File getHomeDirectory() {
141+
return getHomeDirectory(() -> this.environmentVariables.get("SPRING_DEVTOOLS_HOME"),
142+
() -> this.systemProperties.getProperty("spring.devtools.home"),
143+
() -> this.systemProperties.getProperty("user.home"));
133144
}
134145

135-
protected File getHomeDirectory() {
136-
String home = System.getProperty("user.home");
137-
if (StringUtils.hasLength(home)) {
138-
return new File(home);
146+
@SafeVarargs
147+
private final File getHomeDirectory(Supplier<String>... pathSuppliers) {
148+
for (Supplier<String> pathSupplier : pathSuppliers) {
149+
String path = pathSupplier.get();
150+
if (StringUtils.hasText(path)) {
151+
return new File(path);
152+
}
139153
}
140154
return null;
141155
}

spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/env/DevToolsHomePropertiesPostProcessorTests.java

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import java.io.IOException;
2222
import java.io.OutputStream;
2323
import java.nio.file.Files;
24+
import java.util.Collections;
25+
import java.util.Map;
2426
import java.util.Properties;
2527

2628
import org.junit.jupiter.api.BeforeEach;
@@ -47,12 +49,12 @@ class DevToolsHomePropertiesPostProcessorTests {
4749

4850
private File home;
4951

50-
private File rootDir;
52+
private File customHome;
5153

5254
@BeforeEach
53-
void setup(@TempDir File tempDir, @TempDir File rootDir) {
54-
this.home = tempDir;
55-
this.rootDir = rootDir;
55+
void setup(@TempDir File tempDir) {
56+
this.home = new File(tempDir, "default-home");
57+
this.customHome = new File(tempDir, "custom-home");
5658
this.configDir = this.home + "/.config/spring-boot/";
5759
new File(this.configDir).mkdirs();
5860
}
@@ -67,17 +69,25 @@ void loadsPropertiesFromHomeDirectoryUsingProperties() throws Exception {
6769
}
6870

6971
@Test
70-
void loadsRootFolderProperties() throws Exception {
71-
System.setProperty("PROJECT_ROOT_FOLDER", this.rootDir.getAbsolutePath());
72+
void loadsPropertiesFromCustomHomeDirectorySetUsingSystemProperty() throws Exception {
7273
Properties properties = new Properties();
7374
properties.put("uvw", "xyz");
74-
OutputStream out = new FileOutputStream(
75-
new File(this.rootDir, ".config/spring-boot/spring-boot-devtools.properties"));
76-
properties.store(out, null);
77-
out.close();
78-
ConfigurableEnvironment environment = new MockEnvironment();
79-
MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor();
80-
runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null));
75+
writeFile(properties, this.customHome, ".config/spring-boot/spring-boot-devtools.properties");
76+
Properties systemProperties = new Properties();
77+
systemProperties.setProperty("spring.devtools.home", this.customHome.getAbsolutePath());
78+
ConfigurableEnvironment environment = getPostProcessedEnvironment(systemProperties);
79+
assertThat(environment.getProperty("uvw")).isEqualTo("xyz");
80+
}
81+
82+
@Test
83+
void loadsPropertiesFromCustomHomeDirectorySetUsingEnvironmentVariable() throws Exception {
84+
Properties properties = new Properties();
85+
properties.put("uvw", "xyz");
86+
writeFile(properties, this.customHome, ".config/spring-boot/spring-boot-devtools.properties");
87+
Properties systemProperties = new Properties();
88+
systemProperties.setProperty("spring.devtools.home", this.customHome.getAbsolutePath());
89+
ConfigurableEnvironment environment = getPostProcessedEnvironment(
90+
Collections.singletonMap("SPRING_DEVTOOLS_HOME", this.customHome.getAbsolutePath()));
8191
assertThat(environment.getProperty("uvw")).isEqualTo("xyz");
8292
}
8393

@@ -169,15 +179,39 @@ void ignoresMissingHomeProperties() throws Exception {
169179
assertThat(environment.getProperty("abc")).isNull();
170180
}
171181

172-
private void writeFile(Properties properties, String s) throws IOException {
173-
OutputStream out = new FileOutputStream(new File(this.home, s));
174-
properties.store(out, null);
175-
out.close();
182+
private void writeFile(Properties properties, String path) throws IOException {
183+
writeFile(properties, this.home, path);
184+
}
185+
186+
private void writeFile(Properties properties, File home, String path) throws IOException {
187+
File file = new File(home, path);
188+
file.getParentFile().mkdirs();
189+
try (OutputStream out = new FileOutputStream(file)) {
190+
properties.store(out, null);
191+
}
176192
}
177193

178194
private ConfigurableEnvironment getPostProcessedEnvironment() throws Exception {
195+
return getPostProcessedEnvironment(null, null);
196+
}
197+
198+
private ConfigurableEnvironment getPostProcessedEnvironment(Properties systemProperties) throws Exception {
199+
return getPostProcessedEnvironment(null, systemProperties);
200+
}
201+
202+
private ConfigurableEnvironment getPostProcessedEnvironment(Map<String, String> env) throws Exception {
203+
return getPostProcessedEnvironment(env, null);
204+
}
205+
206+
private ConfigurableEnvironment getPostProcessedEnvironment(Map<String, String> env, Properties systemProperties)
207+
throws Exception {
208+
if (systemProperties == null) {
209+
systemProperties = new Properties();
210+
systemProperties.setProperty("user.home", this.home.getAbsolutePath());
211+
}
179212
ConfigurableEnvironment environment = new MockEnvironment();
180-
MockDevToolHomePropertiesPostProcessor postProcessor = new MockDevToolHomePropertiesPostProcessor();
213+
DevToolsHomePropertiesPostProcessor postProcessor = new DevToolsHomePropertiesPostProcessor(
214+
(env != null) ? env : Collections.emptyMap(), systemProperties);
181215
runPostProcessor(() -> postProcessor.postProcessEnvironment(environment, null));
182216
return environment;
183217
}
@@ -188,13 +222,4 @@ protected void runPostProcessor(Runnable runnable) throws Exception {
188222
thread.join();
189223
}
190224

191-
private class MockDevToolHomePropertiesPostProcessor extends DevToolsHomePropertiesPostProcessor {
192-
193-
@Override
194-
protected File getHomeDirectory() {
195-
return DevToolsHomePropertiesPostProcessorTests.this.home;
196-
}
197-
198-
}
199-
200225
}

spring-boot-project/spring-boot-docs/src/docs/asciidoc/using/devtools.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,9 @@ For example, to configure restart to always use a <<using#using.devtools.restart
285285
trigger-file: ".reloadtrigger"
286286
----
287287

288+
By default, `$HOME` is the user's home directory.
289+
To customize this location, set the `SPRING_DEVTOOLS_HOME` environment variable or the `spring.devtools.home` system property.
290+
288291
NOTE: If devtools configuration files are not found in `$HOME/.config/spring-boot`, the root of the `$HOME` directory is searched for the presence of a `.spring-boot-devtools.properties` file.
289292
This allows you to share the devtools global configuration with applications that are on an older version of Spring Boot that does not support the `$HOME/.config/spring-boot` location.
290293

0 commit comments

Comments
 (0)