001/* 002 * Copyright 2002-2017 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.support; 018 019import java.util.Locale; 020import java.util.Map; 021import java.util.TimeZone; 022 023import javax.servlet.http.HttpServletRequest; 024import javax.servlet.http.HttpServletResponse; 025import javax.servlet.jsp.PageContext; 026import javax.servlet.jsp.jstl.core.Config; 027 028import org.springframework.lang.Nullable; 029 030/** 031 * JSP-aware (and JSTL-aware) subclass of RequestContext, allowing for 032 * population of the context from a {@code javax.servlet.jsp.PageContext}. 033 * 034 * <p>This context will detect a JSTL locale attribute in page/request/session/application 035 * scope, in addition to the fallback locale strategy provided by the base class. 036 * 037 * @author Juergen Hoeller 038 * @since 1.1.4 039 * @see #getFallbackLocale 040 */ 041public class JspAwareRequestContext extends RequestContext { 042 043 private PageContext pageContext; 044 045 046 /** 047 * Create a new JspAwareRequestContext for the given page context, 048 * using the request attributes for Errors retrieval. 049 * @param pageContext current JSP page context 050 */ 051 public JspAwareRequestContext(PageContext pageContext) { 052 this(pageContext, null); 053 } 054 055 /** 056 * Create a new JspAwareRequestContext for the given page context, 057 * using the given model attributes for Errors retrieval. 058 * @param pageContext current JSP page context 059 * @param model the model attributes for the current view 060 * (can be {@code null}, using the request attributes for Errors retrieval) 061 */ 062 public JspAwareRequestContext(PageContext pageContext, @Nullable Map<String, Object> model) { 063 super((HttpServletRequest) pageContext.getRequest(), (HttpServletResponse) pageContext.getResponse(), 064 pageContext.getServletContext(), model); 065 this.pageContext = pageContext; 066 } 067 068 069 /** 070 * Return the underlying PageContext. 071 * Only intended for cooperating classes in this package. 072 */ 073 protected final PageContext getPageContext() { 074 return this.pageContext; 075 } 076 077 /** 078 * This implementation checks for a JSTL locale attribute in page, 079 * request, session or application scope; if not found, returns the 080 * {@code HttpServletRequest.getLocale()}. 081 */ 082 @Override 083 protected Locale getFallbackLocale() { 084 if (jstlPresent) { 085 Locale locale = JstlPageLocaleResolver.getJstlLocale(getPageContext()); 086 if (locale != null) { 087 return locale; 088 } 089 } 090 return getRequest().getLocale(); 091 } 092 093 /** 094 * This implementation checks for a JSTL time zone attribute in page, 095 * request, session or application scope; if not found, returns {@code null}. 096 */ 097 @Override 098 protected TimeZone getFallbackTimeZone() { 099 if (jstlPresent) { 100 TimeZone timeZone = JstlPageLocaleResolver.getJstlTimeZone(getPageContext()); 101 if (timeZone != null) { 102 return timeZone; 103 } 104 } 105 return null; 106 } 107 108 109 /** 110 * Inner class that isolates the JSTL dependency. 111 * Just called to resolve the fallback locale if the JSTL API is present. 112 */ 113 private static class JstlPageLocaleResolver { 114 115 @Nullable 116 public static Locale getJstlLocale(PageContext pageContext) { 117 Object localeObject = Config.find(pageContext, Config.FMT_LOCALE); 118 return (localeObject instanceof Locale ? (Locale) localeObject : null); 119 } 120 121 @Nullable 122 public static TimeZone getJstlTimeZone(PageContext pageContext) { 123 Object timeZoneObject = Config.find(pageContext, Config.FMT_TIME_ZONE); 124 return (timeZoneObject instanceof TimeZone ? (TimeZone) timeZoneObject : null); 125 } 126 } 127 128}