diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/NamedMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/NamedMvcEndpoint.java
index 87e9a59188..f92fb0eecf 100644
--- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/NamedMvcEndpoint.java
+++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/NamedMvcEndpoint.java
@@ -17,7 +17,7 @@
package org.springframework.boot.actuate.endpoint.mvc;
/**
- * A {@link MvcEndpoint} that also includes a logical name. Unlike {@link #getPath()
+ * An {@link MvcEndpoint} that also includes a logical name. Unlike {@link #getPath()
* endpoints paths}, it should not be possible for a user to change the endpoint name.
* Names provide a consistent way to reference an endpoint, for example they may be used
* as the {@literal 'rel'} attribute in a HAL response.
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqExceptionTranslator.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqExceptionTranslator.java
index d1f9de3913..778f83df54 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqExceptionTranslator.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqExceptionTranslator.java
@@ -30,7 +30,7 @@ import org.springframework.jdbc.support.SQLExceptionTranslator;
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
/**
- * Transforms {@link java.sql.SQLException} into a Spring-specific @{link
+ * Transforms {@link java.sql.SQLException} into a Spring-specific {@link
* DataAccessException}.
*
* @author Lukas Eder
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java
index 6126f61966..e157173a7f 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java
@@ -174,6 +174,20 @@ public class SecurityProperties implements SecurityPrerequisite {
NONE, DOMAIN, ALL
}
+ public enum ContentSecurityPolicyMode {
+
+ /**
+ * Use the 'Content-Security-Policy' header.
+ */
+ DEFAULT,
+
+ /**
+ * Use the 'Content-Security-Policy-Report-Only' header.
+ */
+ REPORT_ONLY
+
+ }
+
/**
* Enable cross site scripting (XSS) protection.
*/
@@ -194,6 +208,16 @@ public class SecurityProperties implements SecurityPrerequisite {
*/
private boolean contentType = true;
+ /**
+ * Value for content security policy header.
+ */
+ private String contentSecurityPolicy;
+
+ /**
+ * Security policy mode.
+ */
+ private ContentSecurityPolicyMode contentSecurityPolicyMode = ContentSecurityPolicyMode.DEFAULT;
+
/**
* HTTP Strict Transport Security (HSTS) mode (none, domain, all).
*/
@@ -231,6 +255,23 @@ public class SecurityProperties implements SecurityPrerequisite {
this.contentType = contentType;
}
+ public String getContentSecurityPolicy() {
+ return this.contentSecurityPolicy;
+ }
+
+ public void setContentSecurityPolicy(String contentSecurityPolicy) {
+ this.contentSecurityPolicy = contentSecurityPolicy;
+ }
+
+ public ContentSecurityPolicyMode getContentSecurityPolicyMode() {
+ return this.contentSecurityPolicyMode;
+ }
+
+ public void setContentSecurityPolicyMode(
+ ContentSecurityPolicyMode contentSecurityPolicyMode) {
+ this.contentSecurityPolicyMode = contentSecurityPolicyMode;
+ }
+
public HSTS getHsts() {
return this.hsts;
}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfiguration.java
index 22747e1ad7..0197ca2ee7 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfiguration.java
@@ -29,6 +29,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.security.SecurityProperties.Headers;
+import org.springframework.boot.autoconfigure.security.SecurityProperties.Headers.ContentSecurityPolicyMode;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -108,6 +109,16 @@ public class SpringBootWebSecurityConfiguration {
if (!headers.isContentType()) {
configurer.contentTypeOptions().disable();
}
+ if (StringUtils.hasText(headers.getContentSecurityPolicy())) {
+ String policyDirectives = headers.getContentSecurityPolicy();
+ ContentSecurityPolicyMode mode = headers.getContentSecurityPolicyMode();
+ if (mode == ContentSecurityPolicyMode.DEFAULT) {
+ configurer.contentSecurityPolicy(policyDirectives);
+ }
+ else {
+ configurer.contentSecurityPolicy(policyDirectives).reportOnly();
+ }
+ }
if (!headers.isXss()) {
configurer.xssProtection().disable();
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnCloudPlatformTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnCloudPlatformTests.java
index f2de5088d2..9d9aa5a5a0 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnCloudPlatformTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnCloudPlatformTests.java
@@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.condition;
+import org.junit.After;
import org.junit.Test;
import org.springframework.boot.cloud.CloudPlatform;
@@ -33,6 +34,13 @@ public class ConditionalOnCloudPlatformTests {
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+ @After
+ public void cleanUp() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
@Test
public void outcomeWhenCloudfoundryPlatformNotPresentShouldNotMatch()
throws Exception {
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java
index 82d6956546..e20cbb74d9 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java
@@ -213,7 +213,9 @@ public class SpringBootWebSecurityConfigurationTests {
.andExpect(MockMvcResultMatchers.header().string("Cache-Control",
is(notNullValue())))
.andExpect(MockMvcResultMatchers.header().string("X-Frame-Options",
- is(notNullValue())));
+ is(notNullValue())))
+ .andExpect(MockMvcResultMatchers.header()
+ .doesNotExist("Content-Security-Policy"));
}
@Test
@@ -239,6 +241,39 @@ public class SpringBootWebSecurityConfigurationTests {
MockMvcResultMatchers.header().doesNotExist("X-Frame-Options"));
}
+ @Test
+ public void contentSecurityPolicyConfiguration() throws Exception {
+ this.context = SpringApplication.run(VanillaWebConfiguration.class,
+ "--security.headers.content-security-policy=default-src 'self';");
+ MockMvc mockMvc = MockMvcBuilders
+ .webAppContextSetup((WebApplicationContext) this.context)
+ .addFilters((FilterChainProxy) this.context
+ .getBean("springSecurityFilterChain", Filter.class))
+ .build();
+ mockMvc.perform(MockMvcRequestBuilders.get("/"))
+ .andExpect(MockMvcResultMatchers.header()
+ .string("Content-Security-Policy", is("default-src 'self';")))
+ .andExpect(MockMvcResultMatchers.header()
+ .doesNotExist("Content-Security-Policy-Report-Only"));
+ }
+
+ @Test
+ public void contentSecurityPolicyReportOnlyConfiguration() throws Exception {
+ this.context = SpringApplication.run(VanillaWebConfiguration.class,
+ "--security.headers.content-security-policy=default-src 'self';",
+ "--security.headers.content-security-policy-mode=report-only");
+ MockMvc mockMvc = MockMvcBuilders
+ .webAppContextSetup((WebApplicationContext) this.context)
+ .addFilters((FilterChainProxy) this.context
+ .getBean("springSecurityFilterChain", Filter.class))
+ .build();
+ mockMvc.perform(MockMvcRequestBuilders.get("/"))
+ .andExpect(MockMvcResultMatchers.header().string(
+ "Content-Security-Policy-Report-Only", is("default-src 'self';")))
+ .andExpect(MockMvcResultMatchers.header()
+ .doesNotExist("Content-Security-Policy"));
+ }
+
@Configuration
@Import(TestWebConfiguration.class)
@Order(Ordered.LOWEST_PRECEDENCE)
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java
index 9b17db8c2f..478772ba3a 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfigurationTests.java
@@ -577,7 +577,7 @@ public class WebMvcAutoConfigurationTests {
}
@Test
- public void welcomePageMappingDoesNotHandleRequestThatDoNotAcceptTextHtml()
+ public void welcomePageMappingDoesNotHandleRequestsThatDoNotAcceptTextHtml()
throws Exception {
load("spring.resources.static-locations:classpath:/welcome-page/");
assertThat(this.context.getBeansOfType(WelcomePageHandlerMapping.class))
diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml
index 55a54e9790..7f7b004284 100644
--- a/spring-boot-dependencies/pom.xml
+++ b/spring-boot-dependencies/pom.xml
@@ -87,7 +87,7 @@
2.4.7
2.3.13
2.3.3
- 2.21
+ 2.23
4.1.2
4.5.2
4.4.5
@@ -136,6 +136,7 @@
4.1.4
3.0.3.RELEASE
2.53.1
+ 2.23.2
2.2.2
3.1.0
1.1.1
@@ -1818,7 +1819,7 @@
org.seleniumhq.selenium
htmlunit-driver
- ${htmlunit.version}
+ ${selenium-htmlunit.version}
org.seleniumhq.selenium
diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java
index 8cd7d81229..817d173359 100644
--- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java
+++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/RestartApplicationListener.java
@@ -45,15 +45,14 @@ public class RestartApplicationListener
onApplicationStartingEvent((ApplicationStartingEvent) event);
}
if (event instanceof ApplicationPreparedEvent) {
- Restarter.getInstance()
- .prepare(((ApplicationPreparedEvent) event).getApplicationContext());
+ onApplicationPreparedEvent((ApplicationPreparedEvent) event);
}
if (event instanceof ApplicationReadyEvent
|| event instanceof ApplicationFailedEvent) {
Restarter.getInstance().finish();
- if (event instanceof ApplicationFailedEvent) {
- Restarter.getInstance().prepare(null);
- }
+ }
+ if (event instanceof ApplicationFailedEvent) {
+ onApplicationFailedEvent((ApplicationFailedEvent) event);
}
}
@@ -72,6 +71,14 @@ public class RestartApplicationListener
}
}
+ private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
+ Restarter.getInstance().prepare(event.getApplicationContext());
+ }
+
+ private void onApplicationFailedEvent(ApplicationFailedEvent event) {
+ Restarter.getInstance().remove(event.getApplicationContext());
+ }
+
@Override
public int getOrder() {
return this.order;
diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/Restarter.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/Restarter.java
index 1c94bc5506..681026c032 100644
--- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/Restarter.java
+++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/Restarter.java
@@ -31,6 +31,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.locks.Lock;
@@ -116,7 +117,7 @@ public class Restarter {
private boolean finished = false;
- private volatile ConfigurableApplicationContext rootContext;
+ private final List rootContexts = new CopyOnWriteArrayList();
/**
* Internal constructor to create a new {@link Restarter} instance.
@@ -314,9 +315,9 @@ public class Restarter {
this.logger.debug("Stopping application");
this.stopLock.lock();
try {
- if (this.rootContext != null) {
- this.rootContext.close();
- this.rootContext = null;
+ for (ConfigurableApplicationContext context : this.rootContexts) {
+ context.close();
+ this.rootContexts.remove(context);
}
cleanupCaches();
if (this.forceReferenceCleanup) {
@@ -418,7 +419,13 @@ public class Restarter {
if (applicationContext != null && applicationContext.getParent() != null) {
return;
}
- this.rootContext = applicationContext;
+ this.rootContexts.add(applicationContext);
+ }
+
+ void remove(ConfigurableApplicationContext applicationContext) {
+ if (applicationContext != null) {
+ this.rootContexts.remove(applicationContext);
+ }
}
private LeakSafeThread getLeakSafeThread() {
diff --git a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/restart/RestartApplicationListenerTests.java b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/restart/RestartApplicationListenerTests.java
index 31acad0f0e..34848adbc2 100644
--- a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/restart/RestartApplicationListenerTests.java
+++ b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/restart/RestartApplicationListenerTests.java
@@ -16,6 +16,8 @@
package org.springframework.boot.devtools.restart;
+import java.util.List;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -64,8 +66,8 @@ public class RestartApplicationListenerTests {
assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "args"))
.isEqualTo(ARGS);
assertThat(Restarter.getInstance().isFinished()).isTrue();
- assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "rootContext"))
- .isNotNull();
+ assertThat((List>) ReflectionTestUtils.getField(Restarter.getInstance(),
+ "rootContexts")).isNotEmpty();
}
@Test
@@ -74,8 +76,8 @@ public class RestartApplicationListenerTests {
assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "args"))
.isEqualTo(ARGS);
assertThat(Restarter.getInstance().isFinished()).isTrue();
- assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "rootContext"))
- .isNull();
+ assertThat((List>) ReflectionTestUtils.getField(Restarter.getInstance(),
+ "rootContexts")).isEmpty();
}
@Test
diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
index 3c8b477037..f295f097b7 100644
--- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
+++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
@@ -430,6 +430,8 @@ content into your application; rather pick only the properties that you need.
security.filter-order=0 # Security filter chain order.
security.filter-dispatcher-types=ASYNC, FORWARD, INCLUDE, REQUEST # Security filter chain dispatcher types.
security.headers.cache=true # Enable cache control HTTP headers.
+ security.headers.content-security-policy= # Value for content security policy header.
+ security.headers.content-security-policy-mode=default # Content security policy mode (default, report-only).
security.headers.content-type=true # Enable "X-Content-Type-Options" header.
security.headers.frame=true # Enable "X-Frame-Options" header.
security.headers.hsts= # HTTP Strict Transport Security (HSTS) mode (none, domain, all).
diff --git a/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc b/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
index 321bdb9e61..c8dd9ba81f 100644
--- a/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
+++ b/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
@@ -811,7 +811,7 @@ If you are using Jolokia but you don't want Spring Boot to configure it, simply
== Loggers
Spring Boot Actuator includes the ability to view and configure the log levels of your
application at runtime. You can view either the entire list or an individual logger's
-configuration which is made up of both the explictily configured logging level as well as
+configuration which is made up of both the explicitly configured logging level as well as
the effective logging level given to it by the logging framework. These levels can be:
* `TRACE`
@@ -823,7 +823,7 @@ the effective logging level given to it by the logging framework. These levels
* `OFF`
* `null`
-with `null` indicating that there is no explict configuration.
+with `null` indicating that there is no explicit configuration.
diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
index 98b31f93cb..776ed4b367 100644
--- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
+++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
@@ -3883,7 +3883,7 @@ abstraction expects. No further customization is applied on it.
EhCache 2.x is used if a file named `ehcache.xml` can be found at the root of the
classpath. If EhCache 2.x, the `EhCacheCacheManager` provided by the
`spring-boot-starter-cache` '`Starter`' and such file is present it is used to bootstrap
-the cache manager. An alternate configuration file can be provide a well using:
+the cache manager. An alternate configuration file can be provided as well using:
[source,properties,indent=0]
----
diff --git a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc
index 608f83a09b..00b0b781ef 100644
--- a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc
+++ b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc
@@ -769,7 +769,7 @@ dependencies out-of-the-box so you may want to have a look to the
{propdeps-plugin}[`propdeps-plugin`] in the meantime.
TIP: repackaged archives do not contain devtools by default. If you want to use
-<>, you'll need to enable the
+<>, you'll need to disable the
`excludeDevtools` build property to include it. The property is supported with both the
Maven and Gradle plugins.
diff --git a/spring-boot-samples/spring-boot-sample-test-nomockito/pom.xml b/spring-boot-samples/spring-boot-sample-test-nomockito/pom.xml
index 2bda0f5137..bc99def749 100644
--- a/spring-boot-samples/spring-boot-sample-test-nomockito/pom.xml
+++ b/spring-boot-samples/spring-boot-sample-test-nomockito/pom.xml
@@ -42,6 +42,7 @@
org.assertj
assertj-core
+ test
diff --git a/spring-boot-samples/spring-boot-sample-test-nomockito/src/test/java/sample/testnomockito/SampleTestNoMockitoApplicationTest.java b/spring-boot-samples/spring-boot-sample-test-nomockito/src/test/java/sample/testnomockito/SampleTestNoMockitoApplicationTest.java
index 589bb0c4f1..70e89a1f24 100644
--- a/spring-boot-samples/spring-boot-sample-test-nomockito/src/test/java/sample/testnomockito/SampleTestNoMockitoApplicationTest.java
+++ b/spring-boot-samples/spring-boot-sample-test-nomockito/src/test/java/sample/testnomockito/SampleTestNoMockitoApplicationTest.java
@@ -10,7 +10,7 @@ import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
- * Tests that {code ResetMocksTestExecutionListener} and
+ * Tests that {@code ResetMocksTestExecutionListener} and
* {@code MockitoTestExecutionListener} gracefully degrade when Mockito is not on the
* classpath.
*
diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/web/htmlunit/webdriver/LocalHostWebConnectionHtmlUnitDriverTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/web/htmlunit/webdriver/LocalHostWebConnectionHtmlUnitDriverTests.java
index 66ed6e53bb..b618de2ce9 100644
--- a/spring-boot-test/src/test/java/org/springframework/boot/test/web/htmlunit/webdriver/LocalHostWebConnectionHtmlUnitDriverTests.java
+++ b/spring-boot-test/src/test/java/org/springframework/boot/test/web/htmlunit/webdriver/LocalHostWebConnectionHtmlUnitDriverTests.java
@@ -81,7 +81,9 @@ public class LocalHostWebConnectionHtmlUnitDriverTests {
throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Environment must not be null");
- new LocalHostWebConnectionHtmlUnitDriver(null, mock(Capabilities.class));
+ Capabilities capabilities = mock(Capabilities.class);
+ given(capabilities.getBrowserName()).willReturn("chrome");
+ new LocalHostWebConnectionHtmlUnitDriver(null, capabilities);
}
@Test
diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java
index 6cc20a4e44..ef6f62f8b3 100644
--- a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java
+++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java
@@ -52,7 +52,7 @@ public class RunProcess {
/**
* Creates new {@link RunProcess} instance for the specified command.
- * @param command the program to execute and it's arguments
+ * @param command the program to execute and its arguments
*/
public RunProcess(String... command) {
this(null, command);
@@ -63,7 +63,7 @@ public class RunProcess {
* command.
* @param workingDirectory the working directory of the child process or {@code null}
* to run in the working directory of the current Java process
- * @param command the program to execute and it's arguments
+ * @param command the program to execute and its arguments
*/
public RunProcess(File workingDirectory, String... command) {
this.workingDirectory = workingDirectory;
diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java
index 5f6b8fb63e..6efca10a31 100644
--- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java
+++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java
@@ -65,7 +65,7 @@ public class ExplodedArchive implements Archive {
* Create a new {@link ExplodedArchive} instance.
* @param root the root folder
* @param recursive if recursive searching should be used to locate the manifest.
- * Defaults to {@code true}, folders with a large tree might want to set this to {code
+ * Defaults to {@code true}, folders with a large tree might want to set this to {@code
* false}.
*/
public ExplodedArchive(File root, boolean recursive) {
diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
index b22b1b7e57..dc08eff497 100644
--- a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
+++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
@@ -89,7 +89,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
/**
* Current working directory to use for the application. If not specified, basedir
- * will be used NOTE: the use of working directory means that processes will be
+ * will be used. NOTE: the use of working directory means that processes will be
* started by forking a new JVM.
* @since 1.5
*/
diff --git a/spring-boot/src/main/java/org/springframework/boot/web/support/ErrorPageFilter.java b/spring-boot/src/main/java/org/springframework/boot/web/support/ErrorPageFilter.java
index 484bc42d08..19a612ec75 100644
--- a/spring-boot/src/main/java/org/springframework/boot/web/support/ErrorPageFilter.java
+++ b/spring-boot/src/main/java/org/springframework/boot/web/support/ErrorPageFilter.java
@@ -185,7 +185,14 @@ public class ErrorPageFilter implements Filter, ErrorPageRegistry {
request.getRequestDispatcher(path).forward(request, response);
}
- private String getDescription(HttpServletRequest request) {
+ /**
+ * Return the description for the given request. By default this method will return a
+ * description based on the request {@code servletPath} and {@code pathInfo}.
+ * @param request the source request
+ * @return the description
+ * @since 1.5.0
+ */
+ protected String getDescription(HttpServletRequest request) {
return "[" + request.getServletPath()
+ (request.getPathInfo() == null ? "" : request.getPathInfo()) + "]";
}