Restored support for placeholders in mvc namespace resource locations
With the recent charset mechanism in place, we cannot rely on implicit placeholder parsing during String-to-Resource conversion anymore.
This commit is contained in:
@@ -31,7 +31,6 @@ import org.springframework.core.io.ResourceLoader;
|
|||||||
import org.springframework.core.io.UrlResource;
|
import org.springframework.core.io.UrlResource;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.PathMatcher;
|
import org.springframework.util.PathMatcher;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
|
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
|
||||||
@@ -251,7 +250,9 @@ public abstract class MvcNamespaceUtils {
|
|||||||
location = location.trim();
|
location = location.trim();
|
||||||
if (location.startsWith(URL_RESOURCE_CHARSET_PREFIX)) {
|
if (location.startsWith(URL_RESOURCE_CHARSET_PREFIX)) {
|
||||||
int endIndex = location.indexOf("]", URL_RESOURCE_CHARSET_PREFIX.length());
|
int endIndex = location.indexOf("]", URL_RESOURCE_CHARSET_PREFIX.length());
|
||||||
Assert.isTrue(endIndex != -1, "Invalid charset syntax in location: " + location);
|
if (endIndex == -1) {
|
||||||
|
throw new IllegalArgumentException("Invalid charset syntax in location: " + location);
|
||||||
|
}
|
||||||
String value = location.substring(URL_RESOURCE_CHARSET_PREFIX.length(), endIndex);
|
String value = location.substring(URL_RESOURCE_CHARSET_PREFIX.length(), endIndex);
|
||||||
charset = Charset.forName(value);
|
charset = Charset.forName(value);
|
||||||
location = location.substring(endIndex + 1);
|
location = location.substring(endIndex + 1);
|
||||||
@@ -259,7 +260,9 @@ public abstract class MvcNamespaceUtils {
|
|||||||
Resource resource = resourceLoader.getResource(location);
|
Resource resource = resourceLoader.getResource(location);
|
||||||
outputLocations.add(resource);
|
outputLocations.add(resource);
|
||||||
if (charset != null) {
|
if (charset != null) {
|
||||||
Assert.isInstanceOf(UrlResource.class, resource, "Unexpected charset for: " + resource);
|
if (!(resource instanceof UrlResource)) {
|
||||||
|
throw new IllegalArgumentException("Unexpected charset for non-UrlResource: " + resource);
|
||||||
|
}
|
||||||
outputLocationCharsets.put(resource, charset);
|
outputLocationCharsets.put(resource, charset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.w3c.dom.Element;
|
|||||||
|
|
||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||||
@@ -139,13 +140,13 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerUrlProvider(ParserContext parserContext, @Nullable Object source) {
|
private void registerUrlProvider(ParserContext context, @Nullable Object source) {
|
||||||
if (!parserContext.getRegistry().containsBeanDefinition(RESOURCE_URL_PROVIDER)) {
|
if (!context.getRegistry().containsBeanDefinition(RESOURCE_URL_PROVIDER)) {
|
||||||
RootBeanDefinition urlProvider = new RootBeanDefinition(ResourceUrlProvider.class);
|
RootBeanDefinition urlProvider = new RootBeanDefinition(ResourceUrlProvider.class);
|
||||||
urlProvider.setSource(source);
|
urlProvider.setSource(source);
|
||||||
urlProvider.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
urlProvider.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||||
parserContext.getRegistry().registerBeanDefinition(RESOURCE_URL_PROVIDER, urlProvider);
|
context.getRegistry().registerBeanDefinition(RESOURCE_URL_PROVIDER, urlProvider);
|
||||||
parserContext.registerComponent(new BeanComponentDefinition(urlProvider, RESOURCE_URL_PROVIDER));
|
context.registerComponent(new BeanComponentDefinition(urlProvider, RESOURCE_URL_PROVIDER));
|
||||||
|
|
||||||
RootBeanDefinition interceptor = new RootBeanDefinition(ResourceUrlProviderExposingInterceptor.class);
|
RootBeanDefinition interceptor = new RootBeanDefinition(ResourceUrlProviderExposingInterceptor.class);
|
||||||
interceptor.setSource(source);
|
interceptor.setSource(source);
|
||||||
@@ -156,8 +157,8 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
mappedInterceptor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
mappedInterceptor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
|
||||||
mappedInterceptor.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
|
mappedInterceptor.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
|
||||||
mappedInterceptor.getConstructorArgumentValues().addIndexedArgumentValue(1, interceptor);
|
mappedInterceptor.getConstructorArgumentValues().addIndexedArgumentValue(1, interceptor);
|
||||||
String mappedInterceptorName = parserContext.getReaderContext().registerWithGeneratedName(mappedInterceptor);
|
String mappedInterceptorName = context.getReaderContext().registerWithGeneratedName(mappedInterceptor);
|
||||||
parserContext.registerComponent(new BeanComponentDefinition(mappedInterceptor, mappedInterceptorName));
|
context.registerComponent(new BeanComponentDefinition(mappedInterceptor, mappedInterceptorName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,6 +174,13 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String[] locationValues = StringUtils.commaDelimitedListToStringArray(locationAttr);
|
String[] locationValues = StringUtils.commaDelimitedListToStringArray(locationAttr);
|
||||||
|
if (context.getRegistry() instanceof ConfigurableBeanFactory) {
|
||||||
|
ConfigurableBeanFactory cbf = ((ConfigurableBeanFactory) context.getRegistry());
|
||||||
|
for (int i = 0; i < locationValues.length; i++) {
|
||||||
|
locationValues[i] = cbf.resolveEmbeddedValue(locationValues[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ManagedList<Object> locations = new ManagedList<>();
|
ManagedList<Object> locations = new ManagedList<>();
|
||||||
Map<Resource, Charset> locationCharsets = new HashMap<>();
|
Map<Resource, Charset> locationCharsets = new HashMap<>();
|
||||||
ResourceLoader resourceLoader = context.getReaderContext().getResourceLoader();
|
ResourceLoader resourceLoader = context.getReaderContext().getResourceLoader();
|
||||||
@@ -223,29 +231,6 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void parseResourceChain(RootBeanDefinition resourceHandlerDef, ParserContext parserContext,
|
|
||||||
Element element, @Nullable Object source) {
|
|
||||||
|
|
||||||
String autoRegistration = element.getAttribute("auto-registration");
|
|
||||||
boolean isAutoRegistration = !(StringUtils.hasText(autoRegistration) && "false".equals(autoRegistration));
|
|
||||||
|
|
||||||
ManagedList<? super Object> resourceResolvers = new ManagedList<>();
|
|
||||||
resourceResolvers.setSource(source);
|
|
||||||
ManagedList<? super Object> resourceTransformers = new ManagedList<>();
|
|
||||||
resourceTransformers.setSource(source);
|
|
||||||
|
|
||||||
parseResourceCache(resourceResolvers, resourceTransformers, element, source);
|
|
||||||
parseResourceResolversTransformers(isAutoRegistration, resourceResolvers, resourceTransformers,
|
|
||||||
parserContext, element, source);
|
|
||||||
|
|
||||||
if (!resourceResolvers.isEmpty()) {
|
|
||||||
resourceHandlerDef.getPropertyValues().add("resourceResolvers", resourceResolvers);
|
|
||||||
}
|
|
||||||
if (!resourceTransformers.isEmpty()) {
|
|
||||||
resourceHandlerDef.getPropertyValues().add("resourceTransformers", resourceTransformers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private CacheControl parseCacheControl(Element element) {
|
private CacheControl parseCacheControl(Element element) {
|
||||||
CacheControl cacheControl = CacheControl.empty();
|
CacheControl cacheControl = CacheControl.empty();
|
||||||
if ("true".equals(element.getAttribute("no-cache"))) {
|
if ("true".equals(element.getAttribute("no-cache"))) {
|
||||||
@@ -286,6 +271,29 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
return cacheControl;
|
return cacheControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parseResourceChain(
|
||||||
|
RootBeanDefinition resourceHandlerDef, ParserContext context, Element element, @Nullable Object source) {
|
||||||
|
|
||||||
|
String autoRegistration = element.getAttribute("auto-registration");
|
||||||
|
boolean isAutoRegistration = !(StringUtils.hasText(autoRegistration) && "false".equals(autoRegistration));
|
||||||
|
|
||||||
|
ManagedList<? super Object> resourceResolvers = new ManagedList<>();
|
||||||
|
resourceResolvers.setSource(source);
|
||||||
|
ManagedList<? super Object> resourceTransformers = new ManagedList<>();
|
||||||
|
resourceTransformers.setSource(source);
|
||||||
|
|
||||||
|
parseResourceCache(resourceResolvers, resourceTransformers, element, source);
|
||||||
|
parseResourceResolversTransformers(
|
||||||
|
isAutoRegistration, resourceResolvers, resourceTransformers, context, element, source);
|
||||||
|
|
||||||
|
if (!resourceResolvers.isEmpty()) {
|
||||||
|
resourceHandlerDef.getPropertyValues().add("resourceResolvers", resourceResolvers);
|
||||||
|
}
|
||||||
|
if (!resourceTransformers.isEmpty()) {
|
||||||
|
resourceHandlerDef.getPropertyValues().add("resourceTransformers", resourceTransformers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void parseResourceCache(ManagedList<? super Object> resourceResolvers,
|
private void parseResourceCache(ManagedList<? super Object> resourceResolvers,
|
||||||
ManagedList<? super Object> resourceTransformers, Element element, @Nullable Object source) {
|
ManagedList<? super Object> resourceTransformers, Element element, @Nullable Object source) {
|
||||||
|
|
||||||
@@ -324,16 +332,15 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void parseResourceResolversTransformers(boolean isAutoRegistration,
|
private void parseResourceResolversTransformers(boolean isAutoRegistration,
|
||||||
ManagedList<? super Object> resourceResolvers, ManagedList<? super Object> resourceTransformers,
|
ManagedList<? super Object> resourceResolvers, ManagedList<? super Object> resourceTransformers,
|
||||||
ParserContext parserContext, Element element, @Nullable Object source) {
|
ParserContext context, Element element, @Nullable Object source) {
|
||||||
|
|
||||||
Element resolversElement = DomUtils.getChildElementByTagName(element, "resolvers");
|
Element resolversElement = DomUtils.getChildElementByTagName(element, "resolvers");
|
||||||
if (resolversElement != null) {
|
if (resolversElement != null) {
|
||||||
for (Element beanElement : DomUtils.getChildElements(resolversElement)) {
|
for (Element beanElement : DomUtils.getChildElements(resolversElement)) {
|
||||||
if (VERSION_RESOLVER_ELEMENT.equals(beanElement.getLocalName())) {
|
if (VERSION_RESOLVER_ELEMENT.equals(beanElement.getLocalName())) {
|
||||||
RootBeanDefinition versionResolverDef = parseVersionResolver(parserContext, beanElement, source);
|
RootBeanDefinition versionResolverDef = parseVersionResolver(context, beanElement, source);
|
||||||
versionResolverDef.setSource(source);
|
versionResolverDef.setSource(source);
|
||||||
resourceResolvers.add(versionResolverDef);
|
resourceResolvers.add(versionResolverDef);
|
||||||
if (isAutoRegistration) {
|
if (isAutoRegistration) {
|
||||||
@@ -344,7 +351,7 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Object object = parserContext.getDelegate().parsePropertySubElement(beanElement, null);
|
Object object = context.getDelegate().parsePropertySubElement(beanElement, null);
|
||||||
resourceResolvers.add(object);
|
resourceResolvers.add(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,15 +373,13 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
Element transformersElement = DomUtils.getChildElementByTagName(element, "transformers");
|
Element transformersElement = DomUtils.getChildElementByTagName(element, "transformers");
|
||||||
if (transformersElement != null) {
|
if (transformersElement != null) {
|
||||||
for (Element beanElement : DomUtils.getChildElementsByTagName(transformersElement, "bean", "ref")) {
|
for (Element beanElement : DomUtils.getChildElementsByTagName(transformersElement, "bean", "ref")) {
|
||||||
Object object = parserContext.getDelegate().parsePropertySubElement(beanElement, null);
|
Object object = context.getDelegate().parsePropertySubElement(beanElement, null);
|
||||||
resourceTransformers.add(object);
|
resourceTransformers.add(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private RootBeanDefinition parseVersionResolver(
|
private RootBeanDefinition parseVersionResolver(ParserContext context, Element element, @Nullable Object source) {
|
||||||
ParserContext parserContext, Element element, @Nullable Object source) {
|
|
||||||
|
|
||||||
ManagedMap<String, ? super Object> strategyMap = new ManagedMap<>();
|
ManagedMap<String, ? super Object> strategyMap = new ManagedMap<>();
|
||||||
strategyMap.setSource(source);
|
strategyMap.setSource(source);
|
||||||
RootBeanDefinition versionResolverDef = new RootBeanDefinition(VersionResourceResolver.class);
|
RootBeanDefinition versionResolverDef = new RootBeanDefinition(VersionResourceResolver.class);
|
||||||
@@ -402,7 +407,7 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
|||||||
}
|
}
|
||||||
else if (VERSION_STRATEGY_ELEMENT.equals(beanElement.getLocalName())) {
|
else if (VERSION_STRATEGY_ELEMENT.equals(beanElement.getLocalName())) {
|
||||||
Element childElement = DomUtils.getChildElementsByTagName(beanElement, "bean", "ref").get(0);
|
Element childElement = DomUtils.getChildElementsByTagName(beanElement, "bean", "ref").get(0);
|
||||||
strategy = parserContext.getDelegate().parsePropertySubElement(childElement, null);
|
strategy = context.getDelegate().parsePropertySubElement(childElement, null);
|
||||||
}
|
}
|
||||||
for (String pattern : patterns) {
|
for (String pattern : patterns) {
|
||||||
strategyMap.put(pattern, strategy);
|
strategyMap.put(pattern, strategy);
|
||||||
|
|||||||
Reference in New Issue
Block a user