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