001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.web.servlet.view;
018:
019: import java.util.Locale;
020:
021: import org.springframework.beans.BeansException;
022: import org.springframework.beans.factory.BeanFactory;
023: import org.springframework.beans.factory.DisposableBean;
024: import org.springframework.beans.factory.NoSuchBeanDefinitionException;
025: import org.springframework.beans.factory.xml.ResourceEntityResolver;
026: import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
027: import org.springframework.context.ConfigurableApplicationContext;
028: import org.springframework.core.Ordered;
029: import org.springframework.core.io.Resource;
030: import org.springframework.web.context.support.GenericWebApplicationContext;
031: import org.springframework.web.servlet.View;
032:
033: /**
034: * Implementation of ViewResolver that uses bean definitions in an
035: * XML file, specified by resource location. The file will typically
036: * be located in the WEB-INF directory; default is "/WEB-INF/views.xml".
037: *
038: * <p>This ViewResolver does not support internationalization.
039: * Consider ResourceBundleViewResolver if you need to apply
040: * different view resources per locale.
041: *
042: * <p>Note: This ViewResolver implements the Ordered interface to allow for
043: * flexible participation in ViewResolver chaining. For example, some special
044: * views could be defined via this ViewResolver (giving it 0 as "order" value),
045: * while all remaining views could be resolved by a UrlBasedViewResolver.
046: *
047: * @author Juergen Hoeller
048: * @since 18.06.2003
049: * @see org.springframework.context.ApplicationContext#getResource
050: * @see ResourceBundleViewResolver
051: * @see UrlBasedViewResolver
052: */
053: public class XmlViewResolver extends AbstractCachingViewResolver
054: implements Ordered, DisposableBean {
055:
056: /** Default if no other location is supplied */
057: public final static String DEFAULT_LOCATION = "/WEB-INF/views.xml";
058:
059: private int order = Integer.MAX_VALUE; // default: same as non-Ordered
060:
061: private Resource location;
062:
063: private ConfigurableApplicationContext cachedFactory;
064:
065: public void setOrder(int order) {
066: this .order = order;
067: }
068:
069: public int getOrder() {
070: return order;
071: }
072:
073: /**
074: * Set the location of the XML file that defines the view beans.
075: * <p>The default is "/WEB-INF/views.xml".
076: * @param location the location of the XML file.
077: */
078: public void setLocation(Resource location) {
079: this .location = location;
080: }
081:
082: /**
083: * Pre-initialize the factory from the XML file.
084: * Only effective if caching is enabled.
085: */
086: protected void initApplicationContext() throws BeansException {
087: if (isCache()) {
088: initFactory();
089: }
090: }
091:
092: /**
093: * This implementation returns just the view name,
094: * as XmlViewResolver doesn't support localized resolution.
095: */
096: protected Object getCacheKey(String viewName, Locale locale) {
097: return viewName;
098: }
099:
100: protected View loadView(String viewName, Locale locale)
101: throws BeansException {
102: BeanFactory factory = initFactory();
103: try {
104: return (View) factory.getBean(viewName, View.class);
105: } catch (NoSuchBeanDefinitionException ex) {
106: // to allow for ViewResolver chaining
107: return null;
108: }
109: }
110:
111: /**
112: * Initialize the view bean factory from the XML file.
113: * Synchronized because of access by parallel threads.
114: * @throws BeansException in case of initialization errors
115: */
116: protected synchronized BeanFactory initFactory()
117: throws BeansException {
118: if (this .cachedFactory != null) {
119: return this .cachedFactory;
120: }
121:
122: Resource actualLocation = this .location;
123: if (actualLocation == null) {
124: actualLocation = getApplicationContext().getResource(
125: DEFAULT_LOCATION);
126: }
127:
128: // Create child ApplicationContext for views.
129: GenericWebApplicationContext factory = new GenericWebApplicationContext();
130: factory.setParent(getApplicationContext());
131: factory.setServletContext(getServletContext());
132:
133: // Load XML resource with context-aware entity resolver.
134: XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(
135: factory);
136: reader.setEntityResolver(new ResourceEntityResolver(
137: getApplicationContext()));
138: reader.loadBeanDefinitions(actualLocation);
139:
140: factory.refresh();
141:
142: if (isCache()) {
143: this .cachedFactory = factory;
144: }
145: return factory;
146: }
147:
148: /**
149: * Close the view bean factory on context shutdown.
150: */
151: public void destroy() throws BeansException {
152: if (this.cachedFactory != null) {
153: this.cachedFactory.close();
154: }
155: }
156:
157: }
|