Update view-resolver namespace

Issue: SPR-7093
This commit is contained in:
Rossen Stoyanchev
2014-07-12 22:19:18 -04:00
parent f54cee47b0
commit 5e1a5c8d51
16 changed files with 730 additions and 576 deletions

View File

@@ -146,9 +146,10 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv
*/
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
public static final String CONTENT_NEGOTIATION_MANAGER_BEAN_NAME = "mvcContentNegotiationManager";
private static final boolean javaxValidationPresent = ClassUtils.isPresent(
"javax.validation.Validator", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
private static boolean romePresent =
ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", AnnotationDrivenBeanDefinitionParser.class.getClassLoader());
@@ -354,7 +355,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
factoryBeanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
factoryBeanDef.getPropertyValues().add("mediaTypes", getDefaultMediaTypes());
String beanName = "mvcContentNegotiationManager";
String beanName = CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
parserContext.getReaderContext().getRegistry().registerBeanDefinition(beanName , factoryBeanDef);
parserContext.registerComponent(new BeanComponentDefinition(factoryBeanDef, beanName));
contentNegotiationManagerRef = new RuntimeBeanReference(beanName);

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2002-2014 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.web.servlet.config;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import java.util.ArrayList;
import java.util.List;
/**
* Parse the <mvc:velocity> MVC namespace element and register
* FreeMarkerConfigurer bean
*
* @author Rossen Stoyanchev
* @since 4.1
*/
public class FreeMarkerBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
public static final String BEAN_NAME = "mvcFreeMarkerConfigurer";
@Override
protected String getBeanClassName(Element element) {
return "org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer";
}
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {
return BEAN_NAME;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
List<Element> childElements = DomUtils.getChildElementsByTagName(element, "template-loader-path");
if (!childElements.isEmpty()) {
List<String> locations = new ArrayList<String>(childElements.size());
for (Element childElement : childElements) {
locations.add(childElement.getAttribute("location"));
}
if (locations.isEmpty()) {
locations.add("/WEB-INF/");
}
builder.addPropertyValue("templateLoaderPaths", locations.toArray(new String[locations.size()]));
}
}
}

View File

@@ -35,7 +35,10 @@ public class MvcNamespaceHandler extends NamespaceHandlerSupport {
registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
registerBeanDefinitionParser("view-resolution", new ViewResolutionBeanDefinitionParser());
registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
registerBeanDefinitionParser("tiles", new TilesBeanDefinitionParser());
registerBeanDefinitionParser("freemarker", new FreeMarkerBeanDefinitionParser());
registerBeanDefinitionParser("velocity", new VelocityBeanDefinitionParser());
}
}

View File

@@ -50,6 +50,7 @@ abstract class MvcNamespaceUtils {
private static final String PATH_MATCHER_BEAN_NAME = "mvcPathMatcher";
public static void registerDefaultComponents(ParserContext parserContext, Object source) {
registerBeanNameUrlHandlerMapping(parserContext, source);
registerHttpRequestHandlerAdapter(parserContext, source);

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2002-2014 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.web.servlet.config;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import java.util.ArrayList;
import java.util.List;
/**
* Parse the <mvc:tiles> MVC namespace element and register
* TilesConfigurer bean
* @author Rossen Stoyanchev
* @since 4.1
*/
public class TilesBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
public static final String BEAN_NAME = "mvcTilesConfigurer";
@Override
protected String getBeanClassName(Element element) {
return "org.springframework.web.servlet.view.tiles3.TilesConfigurer";
}
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {
return BEAN_NAME;
}
@Override
protected boolean shouldGenerateId() {
return super.shouldGenerateId();
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
List<Element> childElements = DomUtils.getChildElementsByTagName(element, "definitions");
if (!childElements.isEmpty()) {
List<String> locations = new ArrayList<String>(childElements.size());
for (Element childElement : childElements) {
locations.add(childElement.getAttribute("location"));
}
builder.addPropertyValue("definitions", locations.toArray(new String[locations.size()]));
}
if (element.hasAttribute("check-refresh")) {
builder.addPropertyValue("checkRefresh", element.getAttribute("check-refresh"));
}
if (element.hasAttribute("validate-definitions")) {
builder.addPropertyValue("validateDefinitions", element.getAttribute("validate-definitions"));
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2002-2014 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.web.servlet.config;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
/**
* Parse the <mvc:velocity> MVC namespace element and register an
* VelocityConfigurer bean
*
* @author Rossen Stoyanchev
* @since 4.1
*/
public class VelocityBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser {
public static final String BEAN_NAME = "mvcVelocityConfigurer";
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {
return BEAN_NAME;
}
@Override
protected String getBeanClassName(Element element) {
return "org.springframework.web.servlet.view.velocity.VelocityConfigurer";
}
@Override
protected boolean isEligibleAttribute(String attributeName) {
return attributeName.equals("resource-loader-path");
}
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
if (!builder.getBeanDefinition().hasAttribute("resourceLoaderPath")) {
builder.getBeanDefinition().setAttribute("resourceLoaderPath", "/WEB-INF/");
}
}
}

View File

@@ -1,252 +0,0 @@
/*
* Copyright 2002-2014 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.web.servlet.config;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
import org.springframework.web.servlet.view.velocity.VelocityConfigurer;
import org.springframework.web.servlet.view.velocity.VelocityViewResolver;
import org.w3c.dom.Element;
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a
* {@code view-resolution} element to register a set of {@link ViewResolver} definitions.
*
* @author Sivaprasad Valluru
* @author Sebastien Deleuze
* @since 4.1
*/
public class ViewResolutionBeanDefinitionParser implements BeanDefinitionParser {
private Object source;
public BeanDefinition parse(Element element, ParserContext parserContext) {
source= parserContext.extractSource(element);
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(),source);
parserContext.pushContainingComponent(compDefinition);
List<Element> viewResolverElements =
DomUtils.getChildElementsByTagName(element, new String[] { "jsp", "tiles", "bean-name", "freemarker", "velocity", "bean", "ref" });
ManagedList<Object> viewResolvers = new ManagedList<Object>();
viewResolvers.setSource(parserContext.extractSource(element));
int order = 0;
for (Element viewResolverElement : viewResolverElements) {
if ("jsp".equals(viewResolverElement.getLocalName())) {
viewResolvers.add(registerInternalResourceViewResolverBean(viewResolverElement, parserContext, order));
}
if("bean-name".equals(viewResolverElement.getLocalName())){
viewResolvers.add(registerBeanNameViewResolverBean(viewResolverElement, parserContext, order));
}
if ("tiles".equals(viewResolverElement.getLocalName())) {
viewResolvers.add(registerTilesViewResolverBean(viewResolverElement, parserContext, order));
registerTilesConfigurerBean(viewResolverElement, parserContext);
}
if("freemarker".equals(viewResolverElement.getLocalName())){
viewResolvers.add(registerFreemarkerViewResolverBean(viewResolverElement, parserContext, order));
registerFreemarkerConfigurerBean(viewResolverElement, parserContext);
}
if("velocity".equals(viewResolverElement.getLocalName())){
viewResolvers.add(registerVelocityViewResolverBean(viewResolverElement, parserContext, order));
registerVelocityConfigurerBean(viewResolverElement, parserContext);
}
if("bean".equals(viewResolverElement.getLocalName()) || "ref".equals(viewResolverElement.getLocalName())){
viewResolvers.add(parserContext.getDelegate().parsePropertySubElement(viewResolverElement, null));
}
order++;
}
viewResolverElements = DomUtils.getChildElementsByTagName(element, new String[] { "content-negotiating" });
if(!viewResolverElements.isEmpty()) {
registerContentNegotiatingViewResolverBean(viewResolverElements.get(0), parserContext, viewResolvers);
}
parserContext.popAndRegisterContainingComponent();
return null;
}
private BeanDefinition registerBean(Map<String,Object> propertyMap,Class<?> beanClass, ParserContext parserContext ){
RootBeanDefinition beanDef = new RootBeanDefinition(beanClass);
beanDef.setSource(source);
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
for(String propertyName:propertyMap.keySet()){
beanDef.getPropertyValues().add(propertyName, propertyMap.get(propertyName));
}
String beanName = parserContext.getReaderContext().generateBeanName(beanDef);
parserContext.getRegistry().registerBeanDefinition(beanName, beanDef);
parserContext.registerComponent(new BeanComponentDefinition(beanDef, beanName));
return beanDef;
}
private BeanDefinition registerContentNegotiatingViewResolverBean(Element viewResolverElement, ParserContext parserContext, ManagedList<Object> viewResolvers) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
ManagedList<Object> defaultViewBeanDefinitions = new ManagedList<Object>();
List<Element> defaultViewElements =
DomUtils.getChildElementsByTagName(viewResolverElement, new String[] { "default-views" });
if(!defaultViewElements.isEmpty()) {
for(Element beanElem : DomUtils.getChildElementsByTagName(defaultViewElements.get(0), "bean", "ref")) {
defaultViewBeanDefinitions.add(parserContext.getDelegate().parsePropertySubElement(beanElem, null));
}
}
if(viewResolverElement.hasAttribute("use-not-acceptable")) {
propertyMap.put("useNotAcceptableStatusCode", viewResolverElement.getAttribute("use-not-acceptable"));
}
if(viewResolverElement.hasAttribute("manager")) {
propertyMap.put("contentNegotiationManager", new RuntimeBeanReference(viewResolverElement.getAttribute("manager")));
} else {
propertyMap.put("contentNegotiationManager", new RuntimeBeanReference("mvcContentNegotiationManager"));
}
if(viewResolvers != null && !viewResolvers.isEmpty()) {
propertyMap.put("viewResolvers", viewResolvers);
}
if(defaultViewBeanDefinitions != null && !defaultViewBeanDefinitions.isEmpty()) {
propertyMap.put("defaultViews", defaultViewBeanDefinitions);
}
return registerBean(propertyMap, ContentNegotiatingViewResolver.class, parserContext);
}
private BeanDefinition registerFreemarkerConfigurerBean(Element viewResolverElement, ParserContext parserContext) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("template-loader-paths")) {
String[] paths = StringUtils.commaDelimitedListToStringArray(viewResolverElement.getAttribute("template-loader-paths"));
propertyMap.put("templateLoaderPaths", paths);
} else {
propertyMap.put("templateLoaderPaths", new String[]{"/WEB-INF/"});
}
return registerBean(propertyMap, FreeMarkerConfigurer.class, parserContext);
}
private BeanDefinition registerFreemarkerViewResolverBean(Element viewResolverElement, ParserContext parserContext, int order) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("prefix")) {
propertyMap.put("prefix", viewResolverElement.getAttribute("prefix"));
}
if(viewResolverElement.hasAttribute("suffix")) {
propertyMap.put("suffix", viewResolverElement.getAttribute("suffix"));
}
else {
propertyMap.put("suffix", ".ftl");
}
if(viewResolverElement.hasAttribute("cache")) {
propertyMap.put("cache", viewResolverElement.getAttribute("cache"));
}
propertyMap.put("order", order);
return registerBean(propertyMap, FreeMarkerViewResolver.class, parserContext);
}
private BeanDefinition registerVelocityConfigurerBean(Element viewResolverElement, ParserContext parserContext) {
String resourceLoaderPath = viewResolverElement.getAttribute("resource-loader-path");
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("resource-loader-path")) {
propertyMap.put("resourceLoaderPath", resourceLoaderPath);
} else {
propertyMap.put("resourceLoaderPath", "/WEB-INF/");
}
return registerBean(propertyMap, VelocityConfigurer.class, parserContext);
}
private BeanDefinition registerVelocityViewResolverBean(Element viewResolverElement, ParserContext parserContext, int order) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("prefix")) {
propertyMap.put("prefix", viewResolverElement.getAttribute("prefix"));
}
if(viewResolverElement.hasAttribute("suffix")) {
propertyMap.put("suffix", viewResolverElement.getAttribute("suffix"));
}
else {
propertyMap.put("suffix", ".vm");
}
if(viewResolverElement.hasAttribute("cache")) {
propertyMap.put("cache", viewResolverElement.getAttribute("cache"));
}
propertyMap.put("order", order);
return registerBean(propertyMap, VelocityViewResolver.class, parserContext);
}
private BeanDefinition registerBeanNameViewResolverBean(Element viewResolverElement, ParserContext parserContext, int order) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
propertyMap.put("order", order);
return registerBean(propertyMap, BeanNameViewResolver.class, parserContext);
}
private BeanDefinition registerTilesConfigurerBean(Element viewResolverElement, ParserContext parserContext) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("definitions")) {
String[] definitions = StringUtils.commaDelimitedListToStringArray(viewResolverElement.getAttribute("definitions"));
propertyMap.put("definitions", definitions);
}
if(viewResolverElement.hasAttribute("check-refresh")) {
propertyMap.put("checkRefresh", viewResolverElement.getAttribute("check-refresh"));
}
return registerBean(propertyMap, TilesConfigurer.class, parserContext);
}
private BeanDefinition registerTilesViewResolverBean(Element viewResolverElement, ParserContext parserContext, int order) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("prefix")) {
propertyMap.put("prefix", viewResolverElement.getAttribute("prefix"));
}
if(viewResolverElement.hasAttribute("suffix")) {
propertyMap.put("suffix", viewResolverElement.getAttribute("suffix"));
}
propertyMap.put("order", order);
return registerBean(propertyMap, TilesViewResolver.class, parserContext);
}
private BeanDefinition registerInternalResourceViewResolverBean(Element viewResolverElement, ParserContext parserContext, int order) {
Map<String, Object> propertyMap = new HashMap<String, Object>();
if(viewResolverElement.hasAttribute("prefix")) {
propertyMap.put("prefix", viewResolverElement.getAttribute("prefix"));
}
else {
propertyMap.put("prefix", "/WEB-INF/");
}
if(viewResolverElement.hasAttribute("suffix")) {
propertyMap.put("suffix", viewResolverElement.getAttribute("suffix"));
}
else {
propertyMap.put("suffix", ".jsp");
}
propertyMap.put("order", order);
return registerBean(propertyMap, InternalResourceViewResolver.class, parserContext);
}
}

View File

@@ -0,0 +1,189 @@
/*
* Copyright 2002-2014 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.web.servlet.config;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Ordered;
import org.springframework.util.xml.DomUtils;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.ViewResolverComposite;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;
import org.springframework.web.servlet.view.velocity.VelocityViewResolver;
import org.w3c.dom.Element;
/**
* Parse the {@code view-resolvers} MVC namespace element and register
* {@link org.springframework.web.servlet.ViewResolver} bean definitions.
*
* <p>All registered resolvers are wrapped in a single (composite) ViewResolver
* with its order property set to 0 so that other external resolvers may be ordered
* before or after it.
*
* <p>When content negotiation is enabled the order property is set to highest priority
* instead with the ContentNeogitatingViewResolver encapsulating all other registered
* view resolver instances. That way the resolvers registered through the MVC namespace
* form self-encapsulated resolver chain.
*
* @author Sivaprasad Valluru
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
* @since 4.1
* @see org.springframework.web.servlet.config.TilesBeanDefinitionParser
* @see org.springframework.web.servlet.config.FreeMarkerBeanDefinitionParser
* @see org.springframework.web.servlet.config.VelocityBeanDefinitionParser
*/
public class ViewResolversBeanDefinitionParser implements BeanDefinitionParser {
public static final String VIEW_RESOLVER_BEAN_NAME = "mvcViewResolver";
public BeanDefinition parse(Element element, ParserContext context) {
Object source = context.extractSource(element);
context.pushContainingComponent(new CompositeComponentDefinition(element.getTagName(), source));
RootBeanDefinition compositeResolverBeanDef = new RootBeanDefinition(ViewResolverComposite.class);
compositeResolverBeanDef.setSource(source);
compositeResolverBeanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
ManagedList<Object> resolvers = new ManagedList<Object>(4);
resolvers.setSource(context.extractSource(element));
String[] names = new String[] {"jsp", "tiles", "bean-name", "freemarker", "velocity", "bean", "ref"};
for (Element resolverElement : DomUtils.getChildElementsByTagName(element, names)) {
String name = resolverElement.getLocalName();
if ("bean".equals(name) || "ref".equals(name)) {
resolvers.add(context.getDelegate().parsePropertySubElement(resolverElement, null));
continue;
}
RootBeanDefinition resolverBeanDef = null;
if ("jsp".equals(name)) {
resolverBeanDef = new RootBeanDefinition(InternalResourceViewResolver.class);
resolverBeanDef.getPropertyValues().add("prefix", "/WEB-INF/");
resolverBeanDef.getPropertyValues().add("suffix", ".jsp");
addUrlBasedViewResolverProperties(resolverElement, resolverBeanDef);
}
else if ("tiles".equals(name)) {
resolverBeanDef = new RootBeanDefinition(TilesViewResolver.class);
addUrlBasedViewResolverProperties(resolverElement, resolverBeanDef);
}
else if ("freemarker".equals(name)) {
resolverBeanDef = new RootBeanDefinition(FreeMarkerViewResolver.class);
resolverBeanDef.getPropertyValues().add("suffix", ".ftl");
addUrlBasedViewResolverProperties(resolverElement, resolverBeanDef);
}
else if ("velocity".equals(name)) {
resolverBeanDef = new RootBeanDefinition(VelocityViewResolver.class);
resolverBeanDef.getPropertyValues().add("suffix", ".vm");
addUrlBasedViewResolverProperties(resolverElement, resolverBeanDef);
}
else if ("bean-name".equals(name)) {
resolverBeanDef = new RootBeanDefinition(BeanNameViewResolver.class);
}
else {
// Should never happen
throw new IllegalStateException("Unexpected element name: " + name);
}
resolverBeanDef.setSource(source);
resolverBeanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
resolvers.add(resolverBeanDef);
}
List<Element> elementList = DomUtils.getChildElementsByTagName(element, new String[] {"content-negotiation"});
if (elementList.isEmpty()) {
compositeResolverBeanDef.getPropertyValues().add("order", 0);
compositeResolverBeanDef.getPropertyValues().add("viewResolvers", resolvers);
}
else if (elementList.size() == 1) {
BeanDefinition beanDef = createContentNegotiatingViewResolver(elementList.get(0), context);
beanDef.getPropertyValues().add("viewResolvers", resolvers);
ManagedList<Object> list = new ManagedList<Object>(1);
list.add(beanDef);
compositeResolverBeanDef.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
compositeResolverBeanDef.getPropertyValues().add("viewResolvers", list);
}
else if (elementList.size() > 1) {
throw new IllegalArgumentException("Only one <content-negotiation> element is allowed.");
}
String beanName = VIEW_RESOLVER_BEAN_NAME;
context.getReaderContext().getRegistry().registerBeanDefinition(beanName, compositeResolverBeanDef);
context.registerComponent(new BeanComponentDefinition(compositeResolverBeanDef, beanName));
context.popAndRegisterContainingComponent();
return null;
}
private void addUrlBasedViewResolverProperties(Element element, RootBeanDefinition beanDefinition) {
if (element.hasAttribute("prefix")) {
beanDefinition.getPropertyValues().add("prefix", element.getAttribute("prefix"));
}
if (element.hasAttribute("suffix")) {
beanDefinition.getPropertyValues().add("suffix", element.getAttribute("suffix"));
}
if (element.hasAttribute("cache-views")) {
beanDefinition.getPropertyValues().add("cache", element.getAttribute("cache-views"));
}
if (element.hasAttribute("view-class")) {
beanDefinition.getPropertyValues().add("viewClass", element.getAttribute("view-class"));
}
if (element.hasAttribute("view-names")) {
beanDefinition.getPropertyValues().add("viewNames", element.getAttribute("view-names"));
}
}
private BeanDefinition createContentNegotiatingViewResolver(Element resolverElement, ParserContext context) {
RootBeanDefinition beanDef = new RootBeanDefinition(ContentNegotiatingViewResolver.class);
beanDef.setSource(context.extractSource(resolverElement));
beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
MutablePropertyValues values = beanDef.getPropertyValues();
List<Element> elements = DomUtils.getChildElementsByTagName(resolverElement, new String[] {"default-views"});
if (!elements.isEmpty()) {
ManagedList<Object> list = new ManagedList<Object>();
for(Element element : DomUtils.getChildElementsByTagName(elements.get(0), "bean", "ref")) {
list.add(context.getDelegate().parsePropertySubElement(element, null));
}
values.add("defaultViews", list);
}
if (resolverElement.hasAttribute("use-not-acceptable")) {
values.add("useNotAcceptableStatusCode", resolverElement.getAttribute("use-not-acceptable"));
}
String beanName = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
if (context.getRegistry().containsBeanDefinition(beanName)) {
values.add("contentNegotiationManager", new RuntimeBeanReference(beanName));
}
return beanDef;
}
}

View File

@@ -220,6 +220,13 @@ public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
this.useNotAcceptableStatusCode = useNotAcceptableStatusCode;
}
/**
* Whether to return HTTP Status 406 if no suitable is found.
*/
public boolean isUseNotAcceptableStatusCode() {
return this.useNotAcceptableStatusCode;
}
/**
* Set the default views to use when a more specific view can not be obtained
* from the {@link ViewResolver} chain.