/* * Copyright 2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.myfaces.context.servlet; import org.apache.myfaces.util.EnumerationIterator; import javax.faces.FacesException; import javax.faces.application.ViewHandler; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.security.Principal; import java.util.*; import java.lang.reflect.Method; import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.Log; import org.apache.myfaces.context.ReleaseableExternalContext; /** * JSF 1.0 PRD2, 6.1.1 * @author Manfred Geiler (latest modification by $Author$) * @author Anton Koinov * @version $Revision$ $Date$ * * Revision 1.11 Sylvain Vieujot * Forward the message when an exception is thrown in dispatch */ public class ServletExternalContextImpl extends ExternalContext implements ReleaseableExternalContext { private static final Log log = LogFactory.getLog(ServletExternalContextImpl.class); private static final String INIT_PARAMETER_MAP_ATTRIBUTE = InitParameterMap.class.getName(); private ServletContext _servletContext; private ServletRequest _servletRequest; private ServletResponse _servletResponse; private Map _applicationMap; private Map _sessionMap; private Map _requestMap; private Map _requestParameterMap; private Map _requestParameterValuesMap; private Map _requestHeaderMap; private Map _requestHeaderValuesMap; private Map _requestCookieMap; private Map _initParameterMap; private boolean _isHttpServletRequest; private String _requestServletPath; private String _requestPathInfo; private static Method setCharacterEncodingMethod = null; static { try { setCharacterEncodingMethod = ServletRequest.class.getMethod("setCharacterEncoding", new Class[]{String.class}); } catch (Exception e) { log.warn("Detecting request character encoding is disable."); log.warn("Failed to obtain ServletRequest#setCharacterEncoding() method: " + e); } } public ServletExternalContextImpl(ServletContext servletContext, ServletRequest servletRequest, ServletResponse servletResponse) { _servletContext = servletContext; _servletRequest = servletRequest; _servletResponse = servletResponse; _applicationMap = null; _sessionMap = null; _requestMap = null; _requestParameterMap = null; _requestParameterValuesMap = null; _requestHeaderMap = null; _requestHeaderValuesMap = null; _requestCookieMap = null; _initParameterMap = null; _isHttpServletRequest = (servletRequest != null && servletRequest instanceof HttpServletRequest); if (_isHttpServletRequest) { //HACK: MultipartWrapper scrambles the servletPath for some reason in Tomcat 4.1.29 embedded in JBoss 3.2.3!? // (this was reported by frederic.auge [frederic.auge@laposte.net]) HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest; _requestServletPath = httpServletRequest.getServletPath(); _requestPathInfo = httpServletRequest.getPathInfo(); // try to set character encoding as described in section 2.5.2.2 of JSF 1.1 spec // we have to use reflection as method setCharacterEncoding is not supported Servlet API <= 2.3 try { if (setCharacterEncodingMethod != null) { String contentType = httpServletRequest.getHeader("Content-Type"); String characterEncoding = lookupCharacterEncoding(contentType); if (characterEncoding == null) { HttpSession session = httpServletRequest.getSession(false); if (session != null) { characterEncoding = (String) session.getAttribute(ViewHandler.CHARACTER_ENCODING_KEY); } if (characterEncoding != null) { setCharacterEncodingMethod.invoke(servletRequest, new Object[]{characterEncoding}); } } } } catch (Exception e) { if (log.isWarnEnabled()) log.warn("Failed to set character encoding " + e); } } } private String lookupCharacterEncoding(String contentType) { String characterEncoding = null; if (contentType != null) { int charsetFind = contentType.indexOf("charset="); if (charsetFind != -1) { if (charsetFind == 0) { //charset at beginning of Content-Type, curious characterEncoding = contentType.substring(8); } else { char charBefore = contentType.charAt(charsetFind - 1); if (charBefore == ';' || Character.isWhitespace(charBefore)) { //Correct charset after mime type characterEncoding = contentType.substring(charsetFind + 8); } } if (log.isDebugEnabled()) log.debug("Incoming request has Content-Type header with character encoding " + characterEncoding); } else { if (log.isDebugEnabled()) log.debug("Incoming request has Content-Type header without character encoding: " + contentType); } } return characterEncoding; } public void release() { _servletContext = null; _servletRequest = null; _servletResponse = null; _applicationMap = null; _sessionMap = null; _requestMap = null; _requestParameterMap = null; _requestParameterValuesMap = null; _requestHeaderMap = null; _requestHeaderValuesMap = null; _requestCookieMap = null; _initParameterMap = null; } public Object getSession(boolean create) { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } return ((HttpServletRequest)_servletRequest).getSession(create); } public Object getContext() { return _servletContext; } public Object getRequest() { return _servletRequest; } public Object getResponse() { return _servletResponse; } public Map getApplicationMap() { if (_applicationMap == null) { _applicationMap = new ApplicationMap(_servletContext); } return _applicationMap; } public Map getSessionMap() { if (_sessionMap == null) { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } _sessionMap = new SessionMap((HttpServletRequest) _servletRequest); } return _sessionMap; } public Map getRequestMap() { if (_requestMap == null) { _requestMap = new RequestMap(_servletRequest); } return _requestMap; } public Map getRequestParameterMap() { if (_requestParameterMap == null) { _requestParameterMap = new RequestParameterMap(_servletRequest); } return _requestParameterMap; } public Map getRequestParameterValuesMap() { if (_requestParameterValuesMap == null) { _requestParameterValuesMap = new RequestParameterValuesMap(_servletRequest); } return _requestParameterValuesMap; } public Iterator getRequestParameterNames() { final Enumeration enumer = _servletRequest.getParameterNames(); Iterator it = new Iterator() { public boolean hasNext() { return enumer.hasMoreElements(); } public Object next() { return enumer.nextElement(); } public void remove() { throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException"); } }; return it; } public Map getRequestHeaderMap() { if (_requestHeaderMap == null) { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } _requestHeaderMap = new RequestHeaderMap((HttpServletRequest)_servletRequest); } return _requestHeaderMap; } public Map getRequestHeaderValuesMap() { if (_requestHeaderValuesMap == null) { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } _requestHeaderValuesMap = new RequestHeaderValuesMap((HttpServletRequest)_servletRequest); } return _requestHeaderValuesMap; } public Map getRequestCookieMap() { if (_requestCookieMap == null) { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } _requestCookieMap = new CookieMap((HttpServletRequest)_servletRequest); } return _requestCookieMap; } public Locale getRequestLocale() { return _servletRequest.getLocale(); } public String getRequestPathInfo() { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } //return ((HttpServletRequest)_servletRequest).getPathInfo(); //HACK: see constructor return _requestPathInfo; } public String getRequestContextPath() { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } return ((HttpServletRequest)_servletRequest).getContextPath(); } public String getInitParameter(String s) { return _servletContext.getInitParameter(s); } public Map getInitParameterMap() { if (_initParameterMap == null) { // We cache it as an attribute in ServletContext itself (is this circular reference a problem?) if ((_initParameterMap = (Map) _servletContext.getAttribute(INIT_PARAMETER_MAP_ATTRIBUTE)) == null) { _initParameterMap = new InitParameterMap(_servletContext); _servletContext.setAttribute(INIT_PARAMETER_MAP_ATTRIBUTE, _initParameterMap); } } return _initParameterMap; } public Set getResourcePaths(String s) { return _servletContext.getResourcePaths(s); } public InputStream getResourceAsStream(String s) { return _servletContext.getResourceAsStream(s); } public String encodeActionURL(String s) { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } return ((HttpServletResponse)_servletResponse).encodeURL(s); } public String encodeResourceURL(String s) { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } return ((HttpServletResponse)_servletResponse).encodeURL(s); } public String encodeNamespace(String s) { return s; } public void dispatch(String requestURI) throws IOException, FacesException { RequestDispatcher requestDispatcher = _servletRequest.getRequestDispatcher(requestURI); // If there is no dispatcher, send NOT_FOUND if (requestDispatcher == null) { ((HttpServletResponse)_servletResponse).sendError( HttpServletResponse.SC_NOT_FOUND); return; } try { requestDispatcher.forward(_servletRequest, _servletResponse); } catch (ServletException e) { if (e.getMessage() != null) { throw new FacesException(e.getMessage(), e); } else { throw new FacesException(e); } } } public String getRequestServletPath() { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } //return ((HttpServletRequest)_servletRequest).getServletPath(); //HACK: see constructor return _requestServletPath; } public String getAuthType() { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } return ((HttpServletRequest)_servletRequest).getAuthType(); } public String getRemoteUser() { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } return ((HttpServletRequest)_servletRequest).getRemoteUser(); } public boolean isUserInRole(String role) { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } return ((HttpServletRequest)_servletRequest).isUserInRole(role); } public Principal getUserPrincipal() { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } return ((HttpServletRequest)_servletRequest).getUserPrincipal(); } public void log(String message) { _servletContext.log(message); } public void log(String message, Throwable t) { _servletContext.log(message, t); } public void redirect(String url) throws IOException { if (_servletResponse instanceof HttpServletResponse) { ((HttpServletResponse)_servletResponse).sendRedirect(url); FacesContext.getCurrentInstance().responseComplete(); } else { throw new IllegalArgumentException("Only HttpServletResponse supported"); } } public Iterator getRequestLocales() { if (!_isHttpServletRequest) { throw new IllegalArgumentException("Only HttpServletRequest supported"); } return new EnumerationIterator(((HttpServletRequest)_servletRequest).getLocales()); } public URL getResource(String s) throws MalformedURLException { return _servletContext.getResource(s); } }