Skip to content

Commit 03fef65

Browse files
committed
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. (cherry picked from commit 7af9910)
1 parent a9e2040 commit 03fef65

File tree

2 files changed

+125
-115
lines changed

2 files changed

+125
-115
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import org.springframework.core.io.ResourceLoader;
3131
import org.springframework.core.io.UrlResource;
3232
import org.springframework.util.AntPathMatcher;
33-
import org.springframework.util.Assert;
3433
import org.springframework.util.PathMatcher;
3534
import org.springframework.web.cors.CorsConfiguration;
3635
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
@@ -129,44 +128,44 @@ else if (!parserContext.getRegistry().isAlias(PATH_MATCHER_BEAN_NAME)
129128
* Registers an {@link HttpRequestHandlerAdapter} under a well-known
130129
* name unless already registered.
131130
*/
132-
private static void registerBeanNameUrlHandlerMapping(ParserContext parserContext, Object source) {
133-
if (!parserContext.getRegistry().containsBeanDefinition(BEAN_NAME_URL_HANDLER_MAPPING_BEAN_NAME)){
134-
RootBeanDefinition beanNameMappingDef = new RootBeanDefinition(BeanNameUrlHandlerMapping.class);
135-
beanNameMappingDef.setSource(source);
136-
beanNameMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
137-
beanNameMappingDef.getPropertyValues().add("order", 2); // consistent with WebMvcConfigurationSupport
138-
RuntimeBeanReference corsConfigurationsRef = MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);
139-
beanNameMappingDef.getPropertyValues().add("corsConfigurations", corsConfigurationsRef);
140-
parserContext.getRegistry().registerBeanDefinition(BEAN_NAME_URL_HANDLER_MAPPING_BEAN_NAME, beanNameMappingDef);
141-
parserContext.registerComponent(new BeanComponentDefinition(beanNameMappingDef, BEAN_NAME_URL_HANDLER_MAPPING_BEAN_NAME));
131+
private static void registerBeanNameUrlHandlerMapping(ParserContext context, Object source) {
132+
if (!context.getRegistry().containsBeanDefinition(BEAN_NAME_URL_HANDLER_MAPPING_BEAN_NAME)){
133+
RootBeanDefinition mappingDef = new RootBeanDefinition(BeanNameUrlHandlerMapping.class);
134+
mappingDef.setSource(source);
135+
mappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
136+
mappingDef.getPropertyValues().add("order", 2); // consistent with WebMvcConfigurationSupport
137+
RuntimeBeanReference corsRef = MvcNamespaceUtils.registerCorsConfigurations(null, context, source);
138+
mappingDef.getPropertyValues().add("corsConfigurations", corsRef);
139+
context.getRegistry().registerBeanDefinition(BEAN_NAME_URL_HANDLER_MAPPING_BEAN_NAME, mappingDef);
140+
context.registerComponent(new BeanComponentDefinition(mappingDef, BEAN_NAME_URL_HANDLER_MAPPING_BEAN_NAME));
142141
}
143142
}
144143

145144
/**
146145
* Registers an {@link HttpRequestHandlerAdapter} under a well-known
147146
* name unless already registered.
148147
*/
149-
private static void registerHttpRequestHandlerAdapter(ParserContext parserContext, Object source) {
150-
if (!parserContext.getRegistry().containsBeanDefinition(HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME)) {
151-
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(HttpRequestHandlerAdapter.class);
152-
handlerAdapterDef.setSource(source);
153-
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
154-
parserContext.getRegistry().registerBeanDefinition(HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
155-
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME));
148+
private static void registerHttpRequestHandlerAdapter(ParserContext context, Object source) {
149+
if (!context.getRegistry().containsBeanDefinition(HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME)) {
150+
RootBeanDefinition adapterDef = new RootBeanDefinition(HttpRequestHandlerAdapter.class);
151+
adapterDef.setSource(source);
152+
adapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
153+
context.getRegistry().registerBeanDefinition(HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME, adapterDef);
154+
context.registerComponent(new BeanComponentDefinition(adapterDef, HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME));
156155
}
157156
}
158157

159158
/**
160159
* Registers a {@link SimpleControllerHandlerAdapter} under a well-known
161160
* name unless already registered.
162161
*/
163-
private static void registerSimpleControllerHandlerAdapter(ParserContext parserContext, Object source) {
164-
if (!parserContext.getRegistry().containsBeanDefinition(SIMPLE_CONTROLLER_HANDLER_ADAPTER_BEAN_NAME)) {
165-
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(SimpleControllerHandlerAdapter.class);
166-
handlerAdapterDef.setSource(source);
167-
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
168-
parserContext.getRegistry().registerBeanDefinition(SIMPLE_CONTROLLER_HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);
169-
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, SIMPLE_CONTROLLER_HANDLER_ADAPTER_BEAN_NAME));
162+
private static void registerSimpleControllerHandlerAdapter(ParserContext context, Object source) {
163+
if (!context.getRegistry().containsBeanDefinition(SIMPLE_CONTROLLER_HANDLER_ADAPTER_BEAN_NAME)) {
164+
RootBeanDefinition beanDef = new RootBeanDefinition(SimpleControllerHandlerAdapter.class);
165+
beanDef.setSource(source);
166+
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
167+
context.getRegistry().registerBeanDefinition(SIMPLE_CONTROLLER_HANDLER_ADAPTER_BEAN_NAME, beanDef);
168+
context.registerComponent(new BeanComponentDefinition(beanDef, SIMPLE_CONTROLLER_HANDLER_ADAPTER_BEAN_NAME));
170169
}
171170
}
172171

@@ -177,21 +176,21 @@ private static void registerSimpleControllerHandlerAdapter(ParserContext parserC
177176
* @return a RuntimeBeanReference to this {@code Map<String, CorsConfiguration>} instance
178177
*/
179178
public static RuntimeBeanReference registerCorsConfigurations(
180-
Map<String, CorsConfiguration> corsConfigurations, ParserContext parserContext, Object source) {
179+
Map<String, CorsConfiguration> corsConfigurations, ParserContext context, Object source) {
181180

182-
if (!parserContext.getRegistry().containsBeanDefinition(CORS_CONFIGURATION_BEAN_NAME)) {
183-
RootBeanDefinition corsConfigurationsDef = new RootBeanDefinition(LinkedHashMap.class);
184-
corsConfigurationsDef.setSource(source);
185-
corsConfigurationsDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
181+
if (!context.getRegistry().containsBeanDefinition(CORS_CONFIGURATION_BEAN_NAME)) {
182+
RootBeanDefinition corsDef = new RootBeanDefinition(LinkedHashMap.class);
183+
corsDef.setSource(source);
184+
corsDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
186185
if (corsConfigurations != null) {
187-
corsConfigurationsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations);
186+
corsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations);
188187
}
189-
parserContext.getReaderContext().getRegistry().registerBeanDefinition(CORS_CONFIGURATION_BEAN_NAME, corsConfigurationsDef);
190-
parserContext.registerComponent(new BeanComponentDefinition(corsConfigurationsDef, CORS_CONFIGURATION_BEAN_NAME));
188+
context.getReaderContext().getRegistry().registerBeanDefinition(CORS_CONFIGURATION_BEAN_NAME, corsDef);
189+
context.registerComponent(new BeanComponentDefinition(corsDef, CORS_CONFIGURATION_BEAN_NAME));
191190
}
192191
else if (corsConfigurations != null) {
193-
BeanDefinition corsConfigurationsDef = parserContext.getRegistry().getBeanDefinition(CORS_CONFIGURATION_BEAN_NAME);
194-
corsConfigurationsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations);
192+
BeanDefinition corsDef = context.getRegistry().getBeanDefinition(CORS_CONFIGURATION_BEAN_NAME);
193+
corsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations);
195194
}
196195
return new RuntimeBeanReference(CORS_CONFIGURATION_BEAN_NAME);
197196
}
@@ -214,7 +213,7 @@ private static void registerHandlerMappingIntrospector(ParserContext parserConte
214213
/**
215214
* Find the {@code ContentNegotiationManager} bean created by or registered
216215
* with the {@code annotation-driven} element.
217-
* @return a bean definition, bean reference, or {@code null}
216+
* @return a bean definition, bean reference, or {@code null} if none defined
218217
*/
219218
public static Object getContentNegotiationManager(ParserContext context) {
220219
String name = AnnotationDrivenBeanDefinitionParser.HANDLER_MAPPING_BEAN_NAME;
@@ -232,12 +231,11 @@ public static Object getContentNegotiationManager(ParserContext context) {
232231
/**
233232
* Load the {@link Resource}'s for the given locations with the given
234233
* {@link ResourceLoader} and add them to the output list. Also for
235-
* {@link org.springframework.core.io.UrlResource URL-based resources} (e.g.
236-
* files, HTTP URLs, etc) this method supports a special prefix to indicate
237-
* the charset associated with the URL so that relative paths appended to it
238-
* can be encoded correctly, e.g.
239-
* {@code [charset=Windows-31J]http://example.org/path}. The charsets, if
240-
* any, are added to the output map.
234+
* {@link org.springframework.core.io.UrlResource URL-based resources} (e.g. files,
235+
* HTTP URLs, etc) this method supports a special prefix to indicate the charset
236+
* associated with the URL so that relative paths appended to it can be encoded
237+
* correctly, e.g. {@code [charset=Windows-31J]http://example.org/path}.
238+
* The charsets, if any, are added to the output map.
241239
* @since 4.3.13
242240
*/
243241
public static void loadResourceLocations(String[] locations, ResourceLoader resourceLoader,
@@ -248,15 +246,19 @@ public static void loadResourceLocations(String[] locations, ResourceLoader reso
248246
location = location.trim();
249247
if (location.startsWith(URL_RESOURCE_CHARSET_PREFIX)) {
250248
int endIndex = location.indexOf("]", URL_RESOURCE_CHARSET_PREFIX.length());
251-
Assert.isTrue(endIndex != -1, "Invalid charset syntax in location: " + location);
249+
if (endIndex == -1) {
250+
throw new IllegalArgumentException("Invalid charset syntax in location: " + location);
251+
}
252252
String value = location.substring(URL_RESOURCE_CHARSET_PREFIX.length(), endIndex);
253253
charset = Charset.forName(value);
254254
location = location.substring(endIndex + 1);
255255
}
256256
Resource resource = resourceLoader.getResource(location);
257257
outputLocations.add(resource);
258258
if (charset != null) {
259-
Assert.isInstanceOf(UrlResource.class, resource, "Unexpected charset for: " + resource);
259+
if (!(resource instanceof UrlResource)) {
260+
throw new IllegalArgumentException("Unexpected charset for non-UrlResource: " + resource);
261+
}
260262
outputLocationCharsets.put(resource, charset);
261263
}
262264
}

0 commit comments

Comments
 (0)