Commit cb7c0b50 authored by Phillip Webb's avatar Phillip Webb

Merge branch '1.5.x'

parents 4edab86b dcbfb51a
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
package org.springframework.boot.actuate.endpoint.mvc; 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. * 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 * Names provide a consistent way to reference an endpoint, for example they may be used
* as the {@literal 'rel'} attribute in a HAL response. * as the {@literal 'rel'} attribute in a HAL response.
......
...@@ -30,7 +30,7 @@ import org.springframework.jdbc.support.SQLExceptionTranslator; ...@@ -30,7 +30,7 @@ import org.springframework.jdbc.support.SQLExceptionTranslator;
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator; 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}. * DataAccessException}.
* *
* @author Lukas Eder * @author Lukas Eder
......
...@@ -174,6 +174,20 @@ public class SecurityProperties implements SecurityPrerequisite { ...@@ -174,6 +174,20 @@ public class SecurityProperties implements SecurityPrerequisite {
NONE, DOMAIN, ALL 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. * Enable cross site scripting (XSS) protection.
*/ */
...@@ -194,6 +208,16 @@ public class SecurityProperties implements SecurityPrerequisite { ...@@ -194,6 +208,16 @@ public class SecurityProperties implements SecurityPrerequisite {
*/ */
private boolean contentType = true; 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). * HTTP Strict Transport Security (HSTS) mode (none, domain, all).
*/ */
...@@ -231,6 +255,23 @@ public class SecurityProperties implements SecurityPrerequisite { ...@@ -231,6 +255,23 @@ public class SecurityProperties implements SecurityPrerequisite {
this.contentType = contentType; 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() { public HSTS getHsts() {
return this.hsts; return this.hsts;
} }
......
...@@ -29,6 +29,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean ...@@ -29,6 +29,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.security.SecurityProperties.Headers; 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.ErrorController;
import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
...@@ -108,6 +109,16 @@ public class SpringBootWebSecurityConfiguration { ...@@ -108,6 +109,16 @@ public class SpringBootWebSecurityConfiguration {
if (!headers.isContentType()) { if (!headers.isContentType()) {
configurer.contentTypeOptions().disable(); 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()) { if (!headers.isXss()) {
configurer.xssProtection().disable(); configurer.xssProtection().disable();
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.condition; package org.springframework.boot.autoconfigure.condition;
import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.cloud.CloudPlatform;
...@@ -33,6 +34,13 @@ public class ConditionalOnCloudPlatformTests { ...@@ -33,6 +34,13 @@ public class ConditionalOnCloudPlatformTests {
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@After
public void cleanUp() {
if (this.context != null) {
this.context.close();
}
}
@Test @Test
public void outcomeWhenCloudfoundryPlatformNotPresentShouldNotMatch() public void outcomeWhenCloudfoundryPlatformNotPresentShouldNotMatch()
throws Exception { throws Exception {
......
...@@ -213,7 +213,9 @@ public class SpringBootWebSecurityConfigurationTests { ...@@ -213,7 +213,9 @@ public class SpringBootWebSecurityConfigurationTests {
.andExpect(MockMvcResultMatchers.header().string("Cache-Control", .andExpect(MockMvcResultMatchers.header().string("Cache-Control",
is(notNullValue()))) is(notNullValue())))
.andExpect(MockMvcResultMatchers.header().string("X-Frame-Options", .andExpect(MockMvcResultMatchers.header().string("X-Frame-Options",
is(notNullValue()))); is(notNullValue())))
.andExpect(MockMvcResultMatchers.header()
.doesNotExist("Content-Security-Policy"));
} }
@Test @Test
...@@ -239,6 +241,39 @@ public class SpringBootWebSecurityConfigurationTests { ...@@ -239,6 +241,39 @@ public class SpringBootWebSecurityConfigurationTests {
MockMvcResultMatchers.header().doesNotExist("X-Frame-Options")); 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 @Configuration
@Import(TestWebConfiguration.class) @Import(TestWebConfiguration.class)
@Order(Ordered.LOWEST_PRECEDENCE) @Order(Ordered.LOWEST_PRECEDENCE)
......
...@@ -577,7 +577,7 @@ public class WebMvcAutoConfigurationTests { ...@@ -577,7 +577,7 @@ public class WebMvcAutoConfigurationTests {
} }
@Test @Test
public void welcomePageMappingDoesNotHandleRequestThatDoNotAcceptTextHtml() public void welcomePageMappingDoesNotHandleRequestsThatDoNotAcceptTextHtml()
throws Exception { throws Exception {
load("spring.resources.static-locations:classpath:/welcome-page/"); load("spring.resources.static-locations:classpath:/welcome-page/");
assertThat(this.context.getBeansOfType(WelcomePageHandlerMapping.class)) assertThat(this.context.getBeansOfType(WelcomePageHandlerMapping.class))
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
<hikaricp.version>2.4.7</hikaricp.version> <hikaricp.version>2.4.7</hikaricp.version>
<hikaricp-java6.version>2.3.13</hikaricp-java6.version> <hikaricp-java6.version>2.3.13</hikaricp-java6.version>
<hsqldb.version>2.3.3</hsqldb.version> <hsqldb.version>2.3.3</hsqldb.version>
<htmlunit.version>2.21</htmlunit.version> <htmlunit.version>2.23</htmlunit.version>
<httpasyncclient.version>4.1.2</httpasyncclient.version> <httpasyncclient.version>4.1.2</httpasyncclient.version>
<httpclient.version>4.5.2</httpclient.version> <httpclient.version>4.5.2</httpclient.version>
<httpcore.version>4.4.5</httpcore.version> <httpcore.version>4.4.5</httpcore.version>
...@@ -136,6 +136,7 @@ ...@@ -136,6 +136,7 @@
<querydsl.version>4.1.4</querydsl.version> <querydsl.version>4.1.4</querydsl.version>
<reactor.version>3.0.3.RELEASE</reactor.version> <reactor.version>3.0.3.RELEASE</reactor.version>
<selenium.version>2.53.1</selenium.version> <selenium.version>2.53.1</selenium.version>
<selenium-htmlunit.version>2.23.2</selenium-htmlunit.version>
<sendgrid.version>2.2.2</sendgrid.version> <sendgrid.version>2.2.2</sendgrid.version>
<servlet-api.version>3.1.0</servlet-api.version> <servlet-api.version>3.1.0</servlet-api.version>
<simple-json.version>1.1.1</simple-json.version> <simple-json.version>1.1.1</simple-json.version>
...@@ -1818,7 +1819,7 @@ ...@@ -1818,7 +1819,7 @@
<dependency> <dependency>
<groupId>org.seleniumhq.selenium</groupId> <groupId>org.seleniumhq.selenium</groupId>
<artifactId>htmlunit-driver</artifactId> <artifactId>htmlunit-driver</artifactId>
<version>${htmlunit.version}</version> <version>${selenium-htmlunit.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.seleniumhq.selenium</groupId> <groupId>org.seleniumhq.selenium</groupId>
......
...@@ -45,15 +45,14 @@ public class RestartApplicationListener ...@@ -45,15 +45,14 @@ public class RestartApplicationListener
onApplicationStartingEvent((ApplicationStartingEvent) event); onApplicationStartingEvent((ApplicationStartingEvent) event);
} }
if (event instanceof ApplicationPreparedEvent) { if (event instanceof ApplicationPreparedEvent) {
Restarter.getInstance() onApplicationPreparedEvent((ApplicationPreparedEvent) event);
.prepare(((ApplicationPreparedEvent) event).getApplicationContext());
} }
if (event instanceof ApplicationReadyEvent if (event instanceof ApplicationReadyEvent
|| event instanceof ApplicationFailedEvent) { || event instanceof ApplicationFailedEvent) {
Restarter.getInstance().finish(); 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 ...@@ -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 @Override
public int getOrder() { public int getOrder() {
return this.order; return this.order;
......
...@@ -31,6 +31,7 @@ import java.util.Map; ...@@ -31,6 +31,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.BlockingDeque; import java.util.concurrent.BlockingDeque;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
...@@ -116,7 +117,7 @@ public class Restarter { ...@@ -116,7 +117,7 @@ public class Restarter {
private boolean finished = false; private boolean finished = false;
private volatile ConfigurableApplicationContext rootContext; private final List<ConfigurableApplicationContext> rootContexts = new CopyOnWriteArrayList<ConfigurableApplicationContext>();
/** /**
* Internal constructor to create a new {@link Restarter} instance. * Internal constructor to create a new {@link Restarter} instance.
...@@ -314,9 +315,9 @@ public class Restarter { ...@@ -314,9 +315,9 @@ public class Restarter {
this.logger.debug("Stopping application"); this.logger.debug("Stopping application");
this.stopLock.lock(); this.stopLock.lock();
try { try {
if (this.rootContext != null) { for (ConfigurableApplicationContext context : this.rootContexts) {
this.rootContext.close(); context.close();
this.rootContext = null; this.rootContexts.remove(context);
} }
cleanupCaches(); cleanupCaches();
if (this.forceReferenceCleanup) { if (this.forceReferenceCleanup) {
...@@ -418,7 +419,13 @@ public class Restarter { ...@@ -418,7 +419,13 @@ public class Restarter {
if (applicationContext != null && applicationContext.getParent() != null) { if (applicationContext != null && applicationContext.getParent() != null) {
return; return;
} }
this.rootContext = applicationContext; this.rootContexts.add(applicationContext);
}
void remove(ConfigurableApplicationContext applicationContext) {
if (applicationContext != null) {
this.rootContexts.remove(applicationContext);
}
} }
private LeakSafeThread getLeakSafeThread() { private LeakSafeThread getLeakSafeThread() {
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
package org.springframework.boot.devtools.restart; package org.springframework.boot.devtools.restart;
import java.util.List;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -64,8 +66,8 @@ public class RestartApplicationListenerTests { ...@@ -64,8 +66,8 @@ public class RestartApplicationListenerTests {
assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "args")) assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "args"))
.isEqualTo(ARGS); .isEqualTo(ARGS);
assertThat(Restarter.getInstance().isFinished()).isTrue(); assertThat(Restarter.getInstance().isFinished()).isTrue();
assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "rootContext")) assertThat((List<?>) ReflectionTestUtils.getField(Restarter.getInstance(),
.isNotNull(); "rootContexts")).isNotEmpty();
} }
@Test @Test
...@@ -74,8 +76,8 @@ public class RestartApplicationListenerTests { ...@@ -74,8 +76,8 @@ public class RestartApplicationListenerTests {
assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "args")) assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "args"))
.isEqualTo(ARGS); .isEqualTo(ARGS);
assertThat(Restarter.getInstance().isFinished()).isTrue(); assertThat(Restarter.getInstance().isFinished()).isTrue();
assertThat(ReflectionTestUtils.getField(Restarter.getInstance(), "rootContext")) assertThat((List<?>) ReflectionTestUtils.getField(Restarter.getInstance(),
.isNull(); "rootContexts")).isEmpty();
} }
@Test @Test
......
...@@ -430,6 +430,8 @@ content into your application; rather pick only the properties that you need. ...@@ -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-order=0 # Security filter chain order.
security.filter-dispatcher-types=ASYNC, FORWARD, INCLUDE, REQUEST # Security filter chain dispatcher types. security.filter-dispatcher-types=ASYNC, FORWARD, INCLUDE, REQUEST # Security filter chain dispatcher types.
security.headers.cache=true # Enable cache control HTTP headers. 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.content-type=true # Enable "X-Content-Type-Options" header.
security.headers.frame=true # Enable "X-Frame-Options" header. security.headers.frame=true # Enable "X-Frame-Options" header.
security.headers.hsts= # HTTP Strict Transport Security (HSTS) mode (none, domain, all). security.headers.hsts= # HTTP Strict Transport Security (HSTS) mode (none, domain, all).
......
...@@ -811,7 +811,7 @@ If you are using Jolokia but you don't want Spring Boot to configure it, simply ...@@ -811,7 +811,7 @@ If you are using Jolokia but you don't want Spring Boot to configure it, simply
== Loggers == Loggers
Spring Boot Actuator includes the ability to view and configure the log levels of your 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 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: the effective logging level given to it by the logging framework. These levels can be:
* `TRACE` * `TRACE`
...@@ -823,7 +823,7 @@ the effective logging level given to it by the logging framework. These levels ...@@ -823,7 +823,7 @@ the effective logging level given to it by the logging framework. These levels
* `OFF` * `OFF`
* `null` * `null`
with `null` indicating that there is no explict configuration. with `null` indicating that there is no explicit configuration.
......
...@@ -3883,7 +3883,7 @@ abstraction expects. No further customization is applied on it. ...@@ -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 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 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 `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] [source,properties,indent=0]
---- ----
......
...@@ -769,7 +769,7 @@ dependencies out-of-the-box so you may want to have a look to the ...@@ -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. {propdeps-plugin}[`propdeps-plugin`] in the meantime.
TIP: repackaged archives do not contain devtools by default. If you want to use TIP: repackaged archives do not contain devtools by default. If you want to use
<<using-boot-devtools-remote,certain remote devtools feature>>, you'll need to enable the <<using-boot-devtools-remote,certain remote devtools feature>>, you'll need to disable the
`excludeDevtools` build property to include it. The property is supported with both the `excludeDevtools` build property to include it. The property is supported with both the
Maven and Gradle plugins. Maven and Gradle plugins.
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
<dependency> <dependency>
<groupId>org.assertj</groupId> <groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId> <artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
......
...@@ -10,7 +10,7 @@ import org.springframework.test.context.junit4.SpringRunner; ...@@ -10,7 +10,7 @@ import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat; 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 * {@code MockitoTestExecutionListener} gracefully degrade when Mockito is not on the
* classpath. * classpath.
* *
......
...@@ -81,7 +81,9 @@ public class LocalHostWebConnectionHtmlUnitDriverTests { ...@@ -81,7 +81,9 @@ public class LocalHostWebConnectionHtmlUnitDriverTests {
throws Exception { throws Exception {
this.thrown.expect(IllegalArgumentException.class); this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Environment must not be null"); 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 @Test
......
...@@ -52,7 +52,7 @@ public class RunProcess { ...@@ -52,7 +52,7 @@ public class RunProcess {
/** /**
* Creates new {@link RunProcess} instance for the specified command. * 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) { public RunProcess(String... command) {
this(null, command); this(null, command);
...@@ -63,7 +63,7 @@ public class RunProcess { ...@@ -63,7 +63,7 @@ public class RunProcess {
* command. * command.
* @param workingDirectory the working directory of the child process or {@code null} * @param workingDirectory the working directory of the child process or {@code null}
* to run in the working directory of the current Java process * 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) { public RunProcess(File workingDirectory, String... command) {
this.workingDirectory = workingDirectory; this.workingDirectory = workingDirectory;
......
...@@ -65,7 +65,7 @@ public class ExplodedArchive implements Archive { ...@@ -65,7 +65,7 @@ public class ExplodedArchive implements Archive {
* Create a new {@link ExplodedArchive} instance. * Create a new {@link ExplodedArchive} instance.
* @param root the root folder * @param root the root folder
* @param recursive if recursive searching should be used to locate the manifest. * @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}. * false}.
*/ */
public ExplodedArchive(File root, boolean recursive) { public ExplodedArchive(File root, boolean recursive) {
......
...@@ -89,7 +89,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { ...@@ -89,7 +89,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
/** /**
* Current working directory to use for the application. If not specified, basedir * 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. * started by forking a new JVM.
* @since 1.5 * @since 1.5
*/ */
......
...@@ -185,7 +185,14 @@ public class ErrorPageFilter implements Filter, ErrorPageRegistry { ...@@ -185,7 +185,14 @@ public class ErrorPageFilter implements Filter, ErrorPageRegistry {
request.getRequestDispatcher(path).forward(request, response); 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() return "[" + request.getServletPath()
+ (request.getPathInfo() == null ? "" : request.getPathInfo()) + "]"; + (request.getPathInfo() == null ? "" : request.getPathInfo()) + "]";
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment