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. 89 NOTE: If duplicate header names are permitted, then this interface will 90 NOTE: need to change. 91 """ 92 93 headers = {} 94 header_names = self.request.getHeaderNames() 95 if header_names: 96 for header_name in header_names: 97 98 # NOTE: Retrieve only a single value (not using getHeaders). 99 100 headers[header_name] = self.request.getHeader(header_name) 101 102 return headers 103 104 def get_header_values(self, key): 105 106 """ 107 A framework-specific method which returns a list of all request header 108 values associated with the given 'key'. Note that according to RFC 2616, 109 'key' is treated as a case-insensitive string. 110 """ 111 112 return self.request.getHeaders(key) 113 114 def get_content_type(self): 115 116 """ 117 A framework-specific method which gets the content type specified on the 118 request, along with the charset employed. 119 """ 120 121 content_types = self.get_header_values("Content-Type") 122 if len(content_types) >= 1: 123 return self.parse_content_type(content_types[0]) 124 else: 125 return None 126 127 def get_content_charsets(self): 128 129 """ 130 Returns the character set preferences. 131 """ 132 133 accept_charsets = self.get_header_values("Accept-Charset") 134 if len(accept_charsets) >= 1: 135 return self.parse_content_preferences(accept_charsets[0]) 136 else: 137 return None 138 139 def get_content_languages(self): 140 141 """ 142 A framework-specific method which extracts language information from 143 the transaction. 144 """ 145 146 accept_languages = self.get_header_values("Accept-Language") 147 if len(accept_languages) >= 1: 148 return self.parse_content_preferences(accept_languages[0]) 149 else: 150 return None 151 152 def get_path(self): 153 154 """ 155 A framework-specific method which gets the entire path from the request. 156 """ 157 158 return self.request.getServletPath() 159 160 def get_path_info(self): 161 162 """ 163 A framework-specific method which gets the "path info" (the part of the 164 URL after the resource name handling the current request) from the 165 request. 166 """ 167 168 return self.request.getPathInfo() 169 170 def get_query_string(self): 171 172 """ 173 A framework-specific method which gets the query string from the path in 174 the request. 175 """ 176 177 return self.request.getQueryString() 178 179 # Higher level request-related methods. 180 181 def get_fields_from_path(self): 182 183 """ 184 A framework-specific method which extracts the form fields from the 185 path specified in the transaction. The underlying framework may refuse 186 to supply fields from the path if handling a POST transaction. 187 188 Returns a dictionary mapping field names to lists of values (even if a 189 single value is associated with any given field name). 190 191 NOTE: There may not be a reliable means of extracting only the fields 192 NOTE: from the path. 193 """ 194 195 return self.get_fields_from_body() 196 197 def get_fields_from_body(self): 198 199 """ 200 A framework-specific method which extracts the form fields from the 201 message body in the transaction. 202 203 Returns a dictionary mapping field names to lists of values (even if a 204 single value is associated with any given field name). 205 206 NOTE: There may not be a reliable means of extracting only the fields 207 NOTE: from the message body. 208 """ 209 210 parameter_map = self.request.getParameterMap() 211 fields = {} 212 for key in parameter_map.keySet(): 213 fields[key] = parameter_map[key] 214 return fields 215 216 def get_user(self): 217 218 """ 219 A framework-specific method which extracts user information from the 220 transaction. 221 """ 222 223 return self.request.getRemoteUser() 224 225 # Response-related methods. 226 227 def get_response_stream(self): 228 229 """ 230 A framework-specific method which returns the response stream for 231 the transaction. 232 """ 233 234 return self.response.getWriter() 235 236 def get_response_code(self): 237 238 """ 239 Get the response code associated with the transaction. If no response 240 code is defined, None is returned. 241 """ 242 243 return self.status 244 245 def set_response_code(self, response_code): 246 247 """ 248 Set the 'response_code' using a numeric constant defined in the HTTP 249 specification. 250 """ 251 252 self.status = response_code 253 self.response.setStatus(self.status) 254 255 def set_header_value(self, header, value): 256 257 """ 258 Set the HTTP 'header' with the given 'value'. 259 """ 260 261 self.response.setHeader(self.format_header_value(header), self.format_header_value(value)) 262 263 def set_content_type(self, content_type): 264 265 """ 266 A framework-specific method which sets the 'content_type' for the 267 response. 268 """ 269 270 return self.response.setHeader("Content-Type", self.format_content_type(content_type)) 271 272 # vim: tabstop=4 expandtab shiftwidth=4