001/*
002 * Copyright 2002-2016 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 *      https://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
017package org.springframework.web.servlet.view;
018
019import javax.servlet.http.HttpServletRequest;
020
021import org.springframework.util.Assert;
022import org.springframework.util.StringUtils;
023import org.springframework.web.servlet.RequestToViewNameTranslator;
024import org.springframework.web.util.UrlPathHelper;
025
026/**
027 * {@link RequestToViewNameTranslator} that simply transforms the URI of
028 * the incoming request into a view name.
029 *
030 * <p>Can be explicitly defined as the {@code viewNameTranslator} bean in a
031 * {@link org.springframework.web.servlet.DispatcherServlet} context.
032 * Otherwise, a plain default instance will be used.
033 *
034 * <p>The default transformation simply strips leading and trailing slashes
035 * as well as the file extension of the URI, and returns the result as the
036 * view name with the configured {@link #setPrefix prefix} and a
037 * {@link #setSuffix suffix} added as appropriate.
038 *
039 * <p>The stripping of the leading slash and file extension can be disabled
040 * using the {@link #setStripLeadingSlash stripLeadingSlash} and
041 * {@link #setStripExtension stripExtension} properties, respectively.
042 *
043 * <p>Find below some examples of request to view name translation.
044 * <ul>
045 * <li>{@code http://localhost:8080/gamecast/display.html} &raquo; {@code display}</li>
046 * <li>{@code http://localhost:8080/gamecast/displayShoppingCart.html} &raquo; {@code displayShoppingCart}</li>
047 * <li>{@code http://localhost:8080/gamecast/admin/index.html} &raquo; {@code admin/index}</li>
048 * </ul>
049 *
050 * @author Rob Harrop
051 * @author Juergen Hoeller
052 * @since 2.0
053 * @see org.springframework.web.servlet.RequestToViewNameTranslator
054 * @see org.springframework.web.servlet.ViewResolver
055 */
056public class DefaultRequestToViewNameTranslator implements RequestToViewNameTranslator {
057
058        private static final String SLASH = "/";
059
060
061        private String prefix = "";
062
063        private String suffix = "";
064
065        private String separator = SLASH;
066
067        private boolean stripLeadingSlash = true;
068
069        private boolean stripTrailingSlash = true;
070
071        private boolean stripExtension = true;
072
073        private UrlPathHelper urlPathHelper = new UrlPathHelper();
074
075
076        /**
077         * Set the prefix to prepend to generated view names.
078         * @param prefix the prefix to prepend to generated view names
079         */
080        public void setPrefix(String prefix) {
081                this.prefix = (prefix != null ? prefix : "");
082        }
083
084        /**
085         * Set the suffix to append to generated view names.
086         * @param suffix the suffix to append to generated view names
087         */
088        public void setSuffix(String suffix) {
089                this.suffix = (suffix != null ? suffix : "");
090        }
091
092        /**
093         * Set the value that will replace '{@code /}' as the separator
094         * in the view name. The default behavior simply leaves '{@code /}'
095         * as the separator.
096         */
097        public void setSeparator(String separator) {
098                this.separator = separator;
099        }
100
101        /**
102         * Set whether or not leading slashes should be stripped from the URI when
103         * generating the view name. Default is "true".
104         */
105        public void setStripLeadingSlash(boolean stripLeadingSlash) {
106                this.stripLeadingSlash = stripLeadingSlash;
107        }
108
109        /**
110         * Set whether or not trailing slashes should be stripped from the URI when
111         * generating the view name. Default is "true".
112         */
113        public void setStripTrailingSlash(boolean stripTrailingSlash) {
114                this.stripTrailingSlash = stripTrailingSlash;
115        }
116
117        /**
118         * Set whether or not file extensions should be stripped from the URI when
119         * generating the view name. Default is "true".
120         */
121        public void setStripExtension(boolean stripExtension) {
122                this.stripExtension = stripExtension;
123        }
124
125        /**
126         * Set if URL lookup should always use the full path within the current servlet
127         * context. Else, the path within the current servlet mapping is used
128         * if applicable (i.e. in the case of a ".../*" servlet mapping in web.xml).
129         * Default is "false".
130         * @see org.springframework.web.util.UrlPathHelper#setAlwaysUseFullPath
131         */
132        public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
133                this.urlPathHelper.setAlwaysUseFullPath(alwaysUseFullPath);
134        }
135
136        /**
137         * Set if the context path and request URI should be URL-decoded.
138         * Both are returned <i>undecoded</i> by the Servlet API,
139         * in contrast to the servlet path.
140         * <p>Uses either the request encoding or the default encoding according
141         * to the Servlet spec (ISO-8859-1).
142         * @see org.springframework.web.util.UrlPathHelper#setUrlDecode
143         */
144        public void setUrlDecode(boolean urlDecode) {
145                this.urlPathHelper.setUrlDecode(urlDecode);
146        }
147
148        /**
149         * Set if ";" (semicolon) content should be stripped from the request URI.
150         * @see org.springframework.web.util.UrlPathHelper#setRemoveSemicolonContent(boolean)
151         */
152        public void setRemoveSemicolonContent(boolean removeSemicolonContent) {
153                this.urlPathHelper.setRemoveSemicolonContent(removeSemicolonContent);
154        }
155
156        /**
157         * Set the {@link org.springframework.web.util.UrlPathHelper} to use for
158         * the resolution of lookup paths.
159         * <p>Use this to override the default UrlPathHelper with a custom subclass,
160         * or to share common UrlPathHelper settings across multiple web components.
161         */
162        public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
163                Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
164                this.urlPathHelper = urlPathHelper;
165        }
166
167
168        /**
169         * Translates the request URI of the incoming {@link HttpServletRequest}
170         * into the view name based on the configured parameters.
171         * @see org.springframework.web.util.UrlPathHelper#getLookupPathForRequest
172         * @see #transformPath
173         */
174        @Override
175        public String getViewName(HttpServletRequest request) {
176                String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
177                return (this.prefix + transformPath(lookupPath) + this.suffix);
178        }
179
180        /**
181         * Transform the request URI (in the context of the webapp) stripping
182         * slashes and extensions, and replacing the separator as required.
183         * @param lookupPath the lookup path for the current request,
184         * as determined by the UrlPathHelper
185         * @return the transformed path, with slashes and extensions stripped
186         * if desired
187         */
188        protected String transformPath(String lookupPath) {
189                String path = lookupPath;
190                if (this.stripLeadingSlash && path.startsWith(SLASH)) {
191                        path = path.substring(1);
192                }
193                if (this.stripTrailingSlash && path.endsWith(SLASH)) {
194                        path = path.substring(0, path.length() - 1);
195                }
196                if (this.stripExtension) {
197                        path = StringUtils.stripFilenameExtension(path);
198                }
199                if (!SLASH.equals(this.separator)) {
200                        path = StringUtils.replace(path, SLASH, this.separator);
201                }
202                return path;
203        }
204
205}