001: /* ***** BEGIN LICENSE BLOCK *****
002: * Version: MPL 1.1
003: * The contents of this file are subject to the Mozilla Public License Version
004: * 1.1 (the "License"); you may not use this file except in compliance with
005: * the License. You may obtain a copy of the License at
006: * http://www.mozilla.org/MPL/
007: *
008: * Software distributed under the License is distributed on an "AS IS" basis,
009: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
010: * for the specific language governing rights and limitations under the
011: * License.
012: *
013: * The Original Code is Riot.
014: *
015: * The Initial Developer of the Original Code is
016: * Neteye GmbH.
017: * Portions created by the Initial Developer are Copyright (C) 2006
018: * the Initial Developer. All Rights Reserved.
019: *
020: * Contributor(s):
021: * Felix Gnass [fgnass at neteye dot de]
022: *
023: * ***** END LICENSE BLOCK ***** */
024: package org.riotfamily.common.web.view;
025:
026: import java.util.Locale;
027: import java.util.Map;
028:
029: import org.springframework.core.Ordered;
030: import org.springframework.web.servlet.View;
031: import org.springframework.web.servlet.ViewResolver;
032: import org.springframework.web.servlet.view.AbstractCachingViewResolver;
033: import org.springframework.web.servlet.view.InternalResourceView;
034: import org.springframework.web.servlet.view.RedirectView;
035:
036: /**
037: * View resolver that supports view names with a suffix. For example
038: * <tt>someView.jsp</tt> would be delegated to the ViewResolver
039: * registered for the <tt>jsp</tt> suffix.
040: */
041: public class SuffixViewResolver extends AbstractCachingViewResolver
042: implements Ordered {
043:
044: /**
045: * Prefix for special view names that specify a redirect URL (usually
046: * to a controller after a form has been submitted and processed).
047: * Such view names will not be resolved in the configured default
048: * way but rather be treated as special shortcut.
049: */
050: public static final String REDIRECT_URL_PREFIX = "redirect:";
051:
052: /**
053: * Prefix for special view names that specify a forward URL (usually
054: * to a controller after a form has been submitted and processed).
055: * Such view names will not be resolved in the configured default
056: * way but rather be treated as special shortcut.
057: */
058: public static final String FORWARD_URL_PREFIX = "forward:";
059:
060: private Map resolvers;
061:
062: private String defaultSuffix;
063:
064: private ViewResolver defaultResolver;
065:
066: private boolean redirectContextRelative = true;
067:
068: private boolean redirectHttp10Compatible = true;
069:
070: private int order = Ordered.LOWEST_PRECEDENCE;
071:
072: /**
073: * @param resolvers ViewResolvers keyed by suffix (without dots).
074: */
075: public void setResolvers(Map resolvers) {
076: this .resolvers = resolvers;
077: }
078:
079: /**
080: * Sets a default suffix that will be appended to view names that don't
081: * contain a dot. If set to <code>null</code> (default), view names without
082: * an extension won't be resolved which allows resolver chaining.
083: */
084: public void setDefaultSuffix(String defaultSuffix) {
085: this .defaultSuffix = defaultSuffix;
086: }
087:
088: /**
089: * Set whether to interpret a given redirect URL that starts with a
090: * slash ("/") as relative to the current ServletContext, i.e. as
091: * relative to the web application root.
092: * <p>Default is "true": A redirect URL that starts with a slash will be
093: * interpreted as relative to the web application root, i.e. the context
094: * path will be prepended to the URL.
095: * <p><b>Redirect URLs can be specified via the "redirect:" prefix.</b>
096: * E.g.: "redirect:myAction.do"
097: * @see RedirectView#setContextRelative
098: * @see #REDIRECT_URL_PREFIX
099: */
100: public void setRedirectContextRelative(
101: boolean redirectContextRelative) {
102: this .redirectContextRelative = redirectContextRelative;
103: }
104:
105: /**
106: * Set whether redirects should stay compatible with HTTP 1.0 clients.
107: * <p>In the default implementation, this will enforce HTTP status code 302
108: * in any case, i.e. delegate to <code>HttpServletResponse.sendRedirect</code>.
109: * Turning this off will send HTTP status code 303, which is the correct
110: * code for HTTP 1.1 clients, but not understood by HTTP 1.0 clients.
111: * <p>Many HTTP 1.1 clients treat 302 just like 303, not making any
112: * difference. However, some clients depend on 303 when redirecting
113: * after a POST request; turn this flag off in such a scenario.
114: * <p><b>Redirect URLs can be specified via the "redirect:" prefix.</b>
115: * E.g.: "redirect:myAction.do"
116: * @see RedirectView#setHttp10Compatible
117: * @see #REDIRECT_URL_PREFIX
118: */
119: public void setRedirectHttp10Compatible(
120: boolean redirectHttp10Compatible) {
121: this .redirectHttp10Compatible = redirectHttp10Compatible;
122: }
123:
124: /**
125: * Set the order in which this {@link org.springframework.web.servlet.ViewResolver}
126: * is evaluated. Default is {@link Ordered#LOWEST_PRECEDENCE}.
127: */
128: public void setOrder(int order) {
129: this .order = order;
130: }
131:
132: /**
133: * Return the order in which this {@link org.springframework.web.servlet.ViewResolver}
134: * is evaluated.
135: */
136: public int getOrder() {
137: return this .order;
138: }
139:
140: protected View loadView(String viewName, Locale locale)
141: throws Exception {
142:
143: // Check for special "redirect:" prefix.
144: if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
145: String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX
146: .length());
147: return new RedirectView(redirectUrl,
148: redirectContextRelative, redirectHttp10Compatible);
149: }
150:
151: // Check for special "forward:" prefix.
152: if (viewName.startsWith(FORWARD_URL_PREFIX)) {
153: String forwardUrl = viewName.substring(FORWARD_URL_PREFIX
154: .length());
155: return new InternalResourceView(forwardUrl);
156: }
157:
158: String suffix = null;
159: ViewResolver resolver = null;
160: int i = viewName.lastIndexOf('.');
161: if (i > 0) {
162: suffix = viewName.substring(i + 1);
163: resolver = (ViewResolver) resolvers.get(suffix);
164: if (logger.isDebugEnabled()) {
165: if (resolver != null) {
166: logger.debug("Using " + resolver + " for suffix ["
167: + suffix + ']');
168: }
169: }
170: }
171:
172: if (resolver == null) {
173: if (suffix != null) {
174: throw new IllegalArgumentException(
175: "No resolver defined for " + "suffix ["
176: + suffix + ']');
177: }
178: if (defaultSuffix != null) {
179: viewName += "." + defaultSuffix;
180: resolver = defaultResolver;
181: } else {
182: return null;
183: }
184: }
185: return resolver.resolveViewName(viewName, locale);
186: }
187:
188: }
|