1 #!/usr/bin/env python 2 3 """ 4 Java Servlet classes. 5 """ 6 7 import Generic 8 from StringIO import StringIO 9 10 class Stream: 11 12 """ 13 Wrapper around java.io.BufferedReader. 14 """ 15 16 def __init__(self, stream): 17 18 "Initialise the stream with the given underlying 'stream'." 19 20 self.stream = stream 21 22 def read(self): 23 24 "Read the entire message, returning it as a string." 25 26 characters = StringIO() 27 while 1: 28 c = self.stream.read() 29 if c == -1: 30 return characters.getvalue() 31 else: 32 characters.write(chr(c)) 33 34 def readline(self): 35 36 "Read a line from the stream, returning it as a string." 37 38 return self.stream.readLine() 39 40 class Transaction(Generic.Transaction): 41 42 """ 43 Java Servlet transaction interface. 44 """ 45 46 def __init__(self, request, response): 47 48 """ 49 Initialise the transaction using the Java Servlet HTTP 'request' and 50 'response'. 51 """ 52 53 self.request = request 54 self.response = response 55 self.status = None 56 57 def commit(self): 58 59 """ 60 A special method, synchronising the transaction with framework-specific 61 objects. 62 """ 63 64 self.get_response_stream().close() 65 66 # Request-related methods. 67 68 def get_request_stream(self): 69 70 """ 71 A framework-specific method which returns the request stream for 72 the transaction. 73 """ 74 75 return Stream(self.request.getReader()) 76 77 def get_request_method(self): 78 79 """ 80 A framework-specific method which gets the request method. 81 """ 82 83 return self.request.getMethod() 84 85 def get_headers(self): 86 87 """ 88 A framework-specific method which returns all request headers as a 89 dictionary-like object mapping header names to values. 90 NOTE: If duplicate header names are permitted, then this interface will 91 NOTE: need to change. 92 """ 93 94 headers = {} 95 header_names = self.request.getHeaderNames() 96 if header_names: 97 for header_name in header_names: 98 99 # NOTE: Retrieve only a single value (not using getHeaders). 100 101 headers[header_name] = self.request.getHeader(header_name) 102 103 return headers 104 105 def get_header_values(self, key): 106 107 """ 108 A framework-specific method which returns a list of all request header 109 values associated with the given 'key'. Note that according to RFC 2616, 110 'key' is treated as a case-insensitive string. 111 """ 112 113 return self.request.getHeaders(key) 114 115 def get_content_type(self): 116 117 """ 118 A framework-specific method which gets the content type specified on the 119 request, along with the charset employed. 120 """ 121 122 content_types = self.get_header_values("Content-Type") 123 if len(content_types) >= 1: 124 return self.parse_content_type(content_types[0]) 125 else: 126 return None 127 128 def get_content_charsets(self): 129 130 """ 131 Returns the character set preferences. 132 """ 133 134 accept_charsets = self.get_header_values("Accept-Charset") 135 if len(accept_charsets) >= 1: 136 return self.parse_content_preferences(accept_charsets[0]) 137 else: 138 return None 139 140 def get_content_languages(self): 141 142 """ 143 A framework-specific method which extracts language information from 144 the transaction. 145 """ 146 147 accept_languages = self.get_header_values("Accept-Language") 148 if len(accept_languages) >= 1: 149 return self.parse_content_preferences(accept_languages[0]) 150 else: 151 return None 152 153 def get_path(self): 154 155 """ 156 A framework-specific method which gets the entire path from the request. 157 """ 158 159 return self.request.getServletPath() 160 161 def get_path_info(self): 162 163 """ 164 A framework-specific method which gets the "path info" (the part of the 165 URL after the resource name handling the current request) from the 166 request. 167 """ 168 169 return self.request.getPathInfo() 170 171 def get_query_string(self): 172 173 """ 174 A framework-specific method which gets the query string from the path in 175 the request. 176 """ 177 178 return self.request.getQueryString() 179 180 # Higher level request-related methods. 181 182 def get_fields_from_path(self): 183 184 """ 185 A framework-specific method which extracts the form fields from the 186 path specified in the transaction. The underlying framework may refuse 187 to supply fields from the path if handling a POST transaction. 188 189 Returns a dictionary mapping field names to lists of values (even if a 190 single value is associated with any given field name). 191 192 NOTE: There may not be a reliable means of extracting only the fields 193 NOTE: from the path. 194 """ 195 196 return self.get_fields_from_body() 197 198 def get_fields_from_body(self): 199 200 """ 201 A framework-specific method which extracts the form fields from the 202 message body in the transaction. 203 204 Returns a dictionary mapping field names to lists of values (even if a 205 single value is associated with any given field name). 206 207 NOTE: There may not be a reliable means of extracting only the fields 208 NOTE: from the message body. 209 """ 210 211 parameter_map = self.request.getParameterMap() 212 fields = {} 213 for key in parameter_map.keySet(): 214 fields[key] = parameter_map[key] 215 return fields 216 217 def get_user(self): 218 219 """ 220 A framework-specific method which extracts user information from the 221 transaction. 222 223 Returns a username as a string or None if no user is defined. 224 """ 225 226 return self.request.getRemoteUser() 227 228 # Response-related methods. 229 230 def get_response_stream(self): 231 232 """ 233 A framework-specific method which returns the response stream for 234 the transaction. 235 """ 236 237 return self.response.getWriter() 238 239 def get_response_code(self): 240 241 """ 242 Get the response code associated with the transaction. If no response 243 code is defined, None is returned. 244 """ 245 246 return self.status 247 248 def set_response_code(self, response_code): 249 250 """ 251 Set the 'response_code' using a numeric constant defined in the HTTP 252 specification. 253 """ 254 255 self.status = response_code 256 self.response.setStatus(self.status) 257 258 def set_header_value(self, header, value): 259 260 """ 261 Set the HTTP 'header' with the given 'value'. 262 """ 263 264 self.response.setHeader(self.format_header_value(header), self.format_header_value(value)) 265 266 def set_content_type(self, content_type): 267 268 """ 269 A framework-specific method which sets the 'content_type' for the 270 response. 271 """ 272 273 return self.response.setHeader("Content-Type", self.format_content_type(content_type)) 274 275 # vim: tabstop=4 expandtab shiftwidth=4