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