diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChain.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChain.java index 2b34163e2f..9446c3bc20 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChain.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ConditionalOnEnabledResourceChain.java @@ -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. @@ -26,7 +26,8 @@ import org.springframework.context.annotation.Conditional; /** * {@link Conditional} that checks whether or not the Spring resource handling chain is - * enabled. Matches if {@link ResourceProperties.Chain#getEnabled()} is {@code true}. + * enabled. Matches if {@link ResourceProperties.Chain#getEnabled()} is {@code true} or + * if {@code webjars-locator} is on the classpath. * * @author Stephane Nicoll * @since 1.3.0 diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/OnEnabledResourceChainCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/OnEnabledResourceChainCondition.java index 05a6dd43b4..34ac6198bb 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/OnEnabledResourceChainCondition.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/OnEnabledResourceChainCondition.java @@ -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. @@ -24,6 +24,7 @@ import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.util.ClassUtils; /** * {@link Condition} that checks whether or not the Spring resource handling chain is @@ -33,6 +34,8 @@ import org.springframework.core.type.AnnotatedTypeMetadata; */ class OnEnabledResourceChainCondition extends SpringBootCondition { + public static final String WEBJAR_ASSERT_LOCATOR = "org.webjars.WebJarAssetLocator"; + @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { @@ -42,6 +45,13 @@ class OnEnabledResourceChainCondition extends SpringBootCondition { RelaxedDataBinder binder = new RelaxedDataBinder(properties, "spring.resources"); binder.bind(new PropertySourcesPropertyValues(environment.getPropertySources())); Boolean match = properties.getChain().getEnabled(); + if (match == null) { + boolean webJarsLocatorPresent = ClassUtils.isPresent( + WEBJAR_ASSERT_LOCATOR, getClass().getClassLoader()); + return new ConditionOutcome(webJarsLocatorPresent, + "Webjars locator (" + WEBJAR_ASSERT_LOCATOR + ") is " + + (webJarsLocatorPresent ? "present" : "absent")); + } return new ConditionOutcome(match, "Resource chain is " + (match ? "enabled" : "disabled")); } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java index 29fa2699b2..d962d2a1d9 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java @@ -172,10 +172,15 @@ public class ResourceProperties implements ResourceLoaderAware { @NestedConfigurationProperty private final Strategy strategy = new Strategy(); + /** + * Return whether the resource chain is enabled. Return {@code null} if no + * specific settings are present. + */ public Boolean getEnabled() { - return Boolean.TRUE.equals(this.enabled) - || getStrategy().getFixed().isEnabled() + // Check if at least one of the available strategy has been enabled + Boolean strategyEnabled = getStrategy().getFixed().isEnabled() || getStrategy().getContent().isEnabled(); + return (strategyEnabled ? Boolean.TRUE : this.enabled); } public void setEnabled(boolean enabled) { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java index 68b229feb9..cd8a7a2ea5 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java @@ -148,6 +148,9 @@ public class WebMvcAutoConfiguration { @Autowired private HttpMessageConverters messageConverters; + @Autowired(required = false) + ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer; + @Override public void configureMessageConverters(List> converters) { converters.addAll(this.messageConverters.getConverters()); @@ -255,51 +258,24 @@ public class WebMvcAutoConfiguration { } Integer cachePeriod = this.resourceProperties.getCachePeriod(); if (!registry.hasMappingForPattern("/webjars/**")) { - registerResourceChain(registry.addResourceHandler("/webjars/**") + customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/") .setCachePeriod(cachePeriod)); } String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { - registerResourceChain(registry.addResourceHandler(staticPathPattern) + customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern) .addResourceLocations( this.resourceProperties.getStaticLocations()) .setCachePeriod(cachePeriod)); } } - private void registerResourceChain(ResourceHandlerRegistration registration) { - ResourceProperties.Chain properties = this.resourceProperties.getChain(); - if (properties.getEnabled()) { - configureResourceChain(properties, - registration.resourceChain(properties.isCache())); + private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) { + if (this.resourceHandlerRegistrationCustomizer != null) { + this.resourceHandlerRegistrationCustomizer.customize(registration); } - } - private void configureResourceChain(ResourceProperties.Chain properties, - ResourceChainRegistration chain) { - Strategy strategy = properties.getStrategy(); - if (strategy.getFixed().isEnabled() || strategy.getContent().isEnabled()) { - chain.addResolver(getVersionResourceResolver(strategy)); - } - if (properties.isHtmlApplicationCache()) { - chain.addTransformer(new AppCacheManifestTransformer()); - } - } - - private ResourceResolver getVersionResourceResolver( - ResourceProperties.Strategy properties) { - VersionResourceResolver resolver = new VersionResourceResolver(); - if (properties.getFixed().isEnabled()) { - String version = properties.getFixed().getVersion(); - String[] paths = properties.getFixed().getPaths(); - resolver.addFixedVersionStrategy(version, paths); - } - if (properties.getContent().isEnabled()) { - String[] paths = properties.getContent().getPaths(); - resolver.addContentVersionStrategy(paths); - } - return resolver; } @Override @@ -380,4 +356,61 @@ public class WebMvcAutoConfiguration { } + @Configuration + @ConditionalOnEnabledResourceChain + static class ResourceChainCustomizerConfiguration { + + @Bean + public ResourceChainResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer() { + return new ResourceChainResourceHandlerRegistrationCustomizer(); + } + + } + + interface ResourceHandlerRegistrationCustomizer { + + void customize(ResourceHandlerRegistration registration); + + } + + private static class ResourceChainResourceHandlerRegistrationCustomizer + implements ResourceHandlerRegistrationCustomizer { + + @Autowired + private ResourceProperties resourceProperties = new ResourceProperties(); + + @Override + public void customize(ResourceHandlerRegistration registration) { + ResourceProperties.Chain properties = this.resourceProperties.getChain(); + configureResourceChain(properties, + registration.resourceChain(properties.isCache())); + } + + private void configureResourceChain(ResourceProperties.Chain properties, + ResourceChainRegistration chain) { + Strategy strategy = properties.getStrategy(); + if (strategy.getFixed().isEnabled() || strategy.getContent().isEnabled()) { + chain.addResolver(getVersionResourceResolver(strategy)); + } + if (properties.isHtmlApplicationCache()) { + chain.addTransformer(new AppCacheManifestTransformer()); + } + } + + private ResourceResolver getVersionResourceResolver( + ResourceProperties.Strategy properties) { + VersionResourceResolver resolver = new VersionResourceResolver(); + if (properties.getFixed().isEnabled()) { + String version = properties.getFixed().getVersion(); + String[] paths = properties.getFixed().getPaths(); + resolver.addFixedVersionStrategy(version, paths); + } + if (properties.getContent().isEnabled()) { + String[] paths = properties.getContent().getPaths(); + resolver.addContentVersionStrategy(paths); + } + return resolver; + } + } + } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ResourcePropertiesTest.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ResourcePropertiesTest.java new file mode 100644 index 0000000000..4a288ab182 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/ResourcePropertiesTest.java @@ -0,0 +1,58 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http://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.autoconfigure.web; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +/** + * Tests for {@link ResourceProperties}. + * + * @author Stephane Nicoll + */ +public class ResourcePropertiesTest { + + private final ResourceProperties properties = new ResourceProperties(); + + @Test + public void resourceChainNoCustomization() { + System.out.println(this.properties.getChain().getEnabled()); + assertThat(this.properties.getChain().getEnabled(), is(nullValue())); + } + + @Test + public void resourceChainStrategyEnabled() { + this.properties.getChain().getStrategy().getFixed().setEnabled(true); + assertThat(this.properties.getChain().getEnabled(), is(true)); + } + + @Test + public void resourceChainEnabled() { + this.properties.getChain().setEnabled(true); + assertThat(this.properties.getChain().getEnabled(), is(true)); + } + + @Test + public void resourceChainDisabled() { + this.properties.getChain().setEnabled(false); + assertThat(this.properties.getChain().getEnabled(), is(false)); + } + +}