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