001/*
002 * Copyright 2002-2018 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.theme;
018
019import javax.servlet.http.Cookie;
020import javax.servlet.http.HttpServletRequest;
021import javax.servlet.http.HttpServletResponse;
022
023import org.springframework.lang.Nullable;
024import org.springframework.util.Assert;
025import org.springframework.util.StringUtils;
026import org.springframework.web.servlet.ThemeResolver;
027import org.springframework.web.util.CookieGenerator;
028import org.springframework.web.util.WebUtils;
029
030/**
031 * {@link ThemeResolver} implementation that uses a cookie sent back to the user
032 * in case of a custom setting, with a fallback to the default theme.
033 * This is particularly useful for stateless applications without user sessions.
034 *
035 * <p>Custom controllers can thus override the user's theme by calling
036 * {@code setThemeName}, e.g. responding to a certain theme change request.
037 *
038 * @author Jean-Pierre Pawlak
039 * @author Juergen Hoeller
040 * @since 17.06.2003
041 * @see #setThemeName
042 */
043public class CookieThemeResolver extends CookieGenerator implements ThemeResolver {
044
045        /**
046         * The default theme name used if no alternative is provided.
047         */
048        public static final String ORIGINAL_DEFAULT_THEME_NAME = "theme";
049
050        /**
051         * Name of the request attribute that holds the theme name. Only used
052         * for overriding a cookie value if the theme has been changed in the
053         * course of the current request! Use RequestContext.getTheme() to
054         * retrieve the current theme in controllers or views.
055         * @see org.springframework.web.servlet.support.RequestContext#getTheme
056         */
057        public static final String THEME_REQUEST_ATTRIBUTE_NAME = CookieThemeResolver.class.getName() + ".THEME";
058
059        /**
060         * The default name of the cookie that holds the theme name.
061         */
062        public static final String DEFAULT_COOKIE_NAME = CookieThemeResolver.class.getName() + ".THEME";
063
064
065        private String defaultThemeName = ORIGINAL_DEFAULT_THEME_NAME;
066
067
068        public CookieThemeResolver() {
069                setCookieName(DEFAULT_COOKIE_NAME);
070        }
071
072
073        /**
074         * Set the name of the default theme.
075         */
076        public void setDefaultThemeName(String defaultThemeName) {
077                this.defaultThemeName = defaultThemeName;
078        }
079
080        /**
081         * Return the name of the default theme.
082         */
083        public String getDefaultThemeName() {
084                return this.defaultThemeName;
085        }
086
087
088        @Override
089        public String resolveThemeName(HttpServletRequest request) {
090                // Check request for preparsed or preset theme.
091                String themeName = (String) request.getAttribute(THEME_REQUEST_ATTRIBUTE_NAME);
092                if (themeName != null) {
093                        return themeName;
094                }
095
096                // Retrieve cookie value from request.
097                String cookieName = getCookieName();
098                if (cookieName != null) {
099                        Cookie cookie = WebUtils.getCookie(request, cookieName);
100                        if (cookie != null) {
101                                String value = cookie.getValue();
102                                if (StringUtils.hasText(value)) {
103                                        themeName = value;
104                                }
105                        }
106                }
107
108                // Fall back to default theme.
109                if (themeName == null) {
110                        themeName = getDefaultThemeName();
111                }
112                request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);
113                return themeName;
114        }
115
116        @Override
117        public void setThemeName(
118                        HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName) {
119
120                Assert.notNull(response, "HttpServletResponse is required for CookieThemeResolver");
121
122                if (StringUtils.hasText(themeName)) {
123                        // Set request attribute and add cookie.
124                        request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);
125                        addCookie(response, themeName);
126                }
127                else {
128                        // Set request attribute to fallback theme and remove cookie.
129                        request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, getDefaultThemeName());
130                        removeCookie(response);
131                }
132        }
133
134}