001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012 013package org.apache.tapestry5.internal.services; 014 015import org.apache.tapestry5.ioc.internal.util.InternalUtils; 016import org.apache.tapestry5.services.Request; 017import org.apache.tapestry5.services.Session; 018 019import javax.servlet.http.HttpServletRequest; 020import java.io.UnsupportedEncodingException; 021import java.util.List; 022import java.util.Locale; 023 024/** 025 * Basic implementation of {@link org.apache.tapestry5.services.Request} that wraps around an 026 * {@link javax.servlet.http.HttpServletRequest}. This is not threadsafe, nor should it need to be (each Request is 027 * handled by its own Thread). 028 */ 029public class RequestImpl implements Request 030{ 031 static final String REQUESTED_WITH_HEADER = "X-Requested-With"; 032 033 static final String XML_HTTP_REQUEST = "XMLHttpRequest"; 034 035 static final String X_FORWARDED_PROTO_HEADER = "X-Forwarded-Proto"; 036 static final String X_FORWARDED_PROTO_HTTPS = "https"; 037 038 private final HttpServletRequest request; 039 040 private final String applicationCharset; 041 042 private final TapestrySessionFactory sessionFactory; 043 044 private boolean encodingSet; 045 046 private Session session; 047 048 public RequestImpl( 049 HttpServletRequest request, 050 String applicationCharset, 051 TapestrySessionFactory sessionFactory) 052 { 053 this.request = request; 054 this.applicationCharset = applicationCharset; 055 this.sessionFactory = sessionFactory; 056 } 057 058 public List<String> getParameterNames() 059 { 060 setupEncoding(); 061 062 return InternalUtils.toList(request.getParameterNames()); 063 } 064 065 public List<String> getHeaderNames() 066 { 067 return InternalUtils.toList(request.getHeaderNames()); 068 } 069 070 public String getParameter(String name) 071 { 072 setupEncoding(); 073 074 return request.getParameter(name); 075 } 076 077 public String[] getParameters(String name) 078 { 079 setupEncoding(); 080 081 return request.getParameterValues(name); 082 } 083 084 public String getHeader(String name) 085 { 086 return request.getHeader(name); 087 } 088 089 public String getPath() 090 { 091 String pathInfo = request.getPathInfo(); 092 093 if (pathInfo == null) 094 return request.getServletPath(); 095 096 // Websphere 6.1 is a bit wonky (see TAPESTRY-1713), and tends to return the empty string 097 // for the servlet path, and return the true path in pathInfo. 098 099 return pathInfo.length() == 0 ? "/" : pathInfo; 100 } 101 102 public String getContextPath() 103 { 104 return request.getContextPath(); 105 } 106 107 108 public boolean isSessionInvalidated() 109 { 110 // Double check to ensure that the session exists, but don't create it. 111 if (session == null) 112 { 113 session = sessionFactory.getSession(false); 114 } 115 116 return session != null && session.isInvalidated(); 117 } 118 119 public Session getSession(boolean create) 120 { 121 if (session != null && session.isInvalidated()) 122 { 123 session = null; 124 } 125 126 if (session == null) 127 { 128 // TAP5-1489 - Re-storage of session attributes at end of request should be configurable 129 session = sessionFactory.getSession(create); 130 } 131 132 return session; 133 } 134 135 public Locale getLocale() 136 { 137 return request.getLocale(); 138 } 139 140 public long getDateHeader(String name) 141 { 142 return request.getDateHeader(name); 143 } 144 145 private void setupEncoding() 146 { 147 if (encodingSet) 148 { 149 return; 150 } 151 152 // The request may specify an encoding, which is better than the application, which can only 153 // guess at what the client is doing! 154 155 String requestEncoding = request.getCharacterEncoding(); 156 157 try 158 { 159 request.setCharacterEncoding(requestEncoding != null ? requestEncoding : applicationCharset); 160 } catch (UnsupportedEncodingException ex) 161 { 162 throw new RuntimeException(ex); 163 } 164 165 encodingSet = true; 166 } 167 168 public boolean isXHR() 169 { 170 return XML_HTTP_REQUEST.equals(request.getHeader(REQUESTED_WITH_HEADER)); 171 } 172 173 public boolean isSecure() 174 { 175 return request.isSecure() || 176 X_FORWARDED_PROTO_HTTPS.equals(request.getHeader(X_FORWARDED_PROTO_HEADER)); 177 } 178 179 public boolean isRequestedSessionIdValid() 180 { 181 return request.isRequestedSessionIdValid(); 182 } 183 184 public Object getAttribute(String name) 185 { 186 return request.getAttribute(name); 187 } 188 189 public List<String> getAttributeNames() 190 { 191 setupEncoding(); 192 193 return InternalUtils.toList(request.getAttributeNames()); 194 } 195 196 public void setAttribute(String name, Object value) 197 { 198 request.setAttribute(name, value); 199 } 200 201 public String getMethod() 202 { 203 return request.getMethod(); 204 } 205 206 public String getServerName() 207 { 208 return request.getServerName(); 209 } 210 211 public int getLocalPort() 212 { 213 return request.getLocalPort(); 214 } 215 216 /** 217 * @since 5.2.5 218 */ 219 public int getServerPort() 220 { 221 return request.getServerPort(); 222 } 223 224 public String getRemoteHost() 225 { 226 return request.getRemoteHost(); 227 } 228 229}