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.http.internal.services; 014 015import java.io.UnsupportedEncodingException; 016import java.util.Collections; 017import java.util.Enumeration; 018import java.util.List; 019import java.util.Locale; 020 021import javax.servlet.http.HttpServletRequest; 022 023import org.apache.tapestry5.commons.util.CollectionFactory; 024import org.apache.tapestry5.http.services.Request; 025import org.apache.tapestry5.http.services.Session; 026 027/** 028 * Basic implementation of {@link org.apache.tapestry5.http.services.Request} that wraps around an 029 * {@link javax.servlet.http.HttpServletRequest}. This is not threadsafe, nor should it need to be (each Request is 030 * handled by its own Thread). 031 */ 032public class RequestImpl implements Request 033{ 034 /** 035 * @deprecated Use {@link Request#REQUESTED_WITH_HEADER} instead 036 */ 037 static final String REQUESTED_WITH_HEADER = Request.REQUESTED_WITH_HEADER; 038 039 static final String XML_HTTP_REQUEST = "XMLHttpRequest"; 040 041 /** 042 * @deprecated Use {@link Request#X_FORWARDED_PROTO_HEADER} instead 043 */ 044 static final String X_FORWARDED_PROTO_HEADER = Request.X_FORWARDED_PROTO_HEADER; 045 static final String X_FORWARDED_PROTO_HTTPS = "https"; 046 047 private final HttpServletRequest request; 048 049 private final String applicationCharset; 050 051 private final TapestrySessionFactory sessionFactory; 052 053 private boolean encodingSet; 054 055 private Session session; 056 057 public RequestImpl( 058 HttpServletRequest request, 059 String applicationCharset, 060 TapestrySessionFactory sessionFactory) 061 { 062 this.request = request; 063 this.applicationCharset = applicationCharset; 064 this.sessionFactory = sessionFactory; 065 } 066 067 public List<String> getParameterNames() 068 { 069 setupEncoding(); 070 071 return toList(request.getParameterNames()); 072 } 073 074 public List<String> getHeaderNames() 075 { 076 return toList(request.getHeaderNames()); 077 } 078 079 public String getParameter(String name) 080 { 081 setupEncoding(); 082 083 return request.getParameter(name); 084 } 085 086 public String[] getParameters(String name) 087 { 088 setupEncoding(); 089 090 return request.getParameterValues(name); 091 } 092 093 public String getHeader(String name) 094 { 095 return request.getHeader(name); 096 } 097 098 public String getPath() 099 { 100 String pathInfo = request.getPathInfo(); 101 102 if (pathInfo == null) 103 return request.getServletPath(); 104 105 // Websphere 6.1 is a bit wonky (see TAPESTRY-1713), and tends to return the empty string 106 // for the servlet path, and return the true path in pathInfo. 107 108 return pathInfo.length() == 0 ? "/" : pathInfo; 109 } 110 111 public String getContextPath() 112 { 113 return request.getContextPath(); 114 } 115 116 117 public boolean isSessionInvalidated() 118 { 119 // Double check to ensure that the session exists, but don't create it. 120 if (session == null) 121 { 122 session = sessionFactory.getSession(false); 123 } 124 125 return session != null && session.isInvalidated(); 126 } 127 128 public Session getSession(boolean create) 129 { 130 if (session != null && session.isInvalidated()) 131 { 132 session = null; 133 } 134 135 if (session == null) 136 { 137 // TAP5-1489 - Re-storage of session attributes at end of request should be configurable 138 session = sessionFactory.getSession(create); 139 } 140 141 return session; 142 } 143 144 public Locale getLocale() 145 { 146 return request.getLocale(); 147 } 148 149 public long getDateHeader(String name) 150 { 151 return request.getDateHeader(name); 152 } 153 154 private void setupEncoding() 155 { 156 if (encodingSet) 157 { 158 return; 159 } 160 161 // The request may specify an encoding, which is better than the application, which can only 162 // guess at what the client is doing! 163 164 String requestEncoding = request.getCharacterEncoding(); 165 166 try 167 { 168 request.setCharacterEncoding(requestEncoding != null ? requestEncoding : applicationCharset); 169 } catch (UnsupportedEncodingException ex) 170 { 171 throw new RuntimeException(ex); 172 } 173 174 encodingSet = true; 175 } 176 177 public boolean isXHR() 178 { 179 return XML_HTTP_REQUEST.equals(request.getHeader(Request.REQUESTED_WITH_HEADER)); 180 } 181 182 public boolean isSecure() 183 { 184 return request.isSecure() || 185 X_FORWARDED_PROTO_HTTPS.equals(request.getHeader(Request.X_FORWARDED_PROTO_HEADER)); 186 } 187 188 public boolean isRequestedSessionIdValid() 189 { 190 return request.isRequestedSessionIdValid(); 191 } 192 193 public Object getAttribute(String name) 194 { 195 return request.getAttribute(name); 196 } 197 198 public List<String> getAttributeNames() 199 { 200 setupEncoding(); 201 202 return toList(request.getAttributeNames()); 203 } 204 205 public void setAttribute(String name, Object value) 206 { 207 request.setAttribute(name, value); 208 } 209 210 public String getMethod() 211 { 212 return request.getMethod(); 213 } 214 215 public String getServerName() 216 { 217 return request.getServerName(); 218 } 219 220 public int getLocalPort() 221 { 222 return request.getLocalPort(); 223 } 224 225 /** 226 * @since 5.2.5 227 */ 228 public int getServerPort() 229 { 230 return request.getServerPort(); 231 } 232 233 public String getRemoteHost() 234 { 235 return request.getRemoteHost(); 236 } 237 238 /** 239 * Converts an enumeration (of Strings) into a sorted list of Strings. 240 */ 241 @SuppressWarnings("rawtypes") 242 private static List<String> toList(Enumeration e) 243 { 244 List<String> result = CollectionFactory.newList(); 245 246 while (e.hasMoreElements()) 247 { 248 String name = (String) e.nextElement(); 249 250 result.add(name); 251 } 252 253 Collections.sort(result); 254 255 return result; 256 } 257 258 259}