1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.wotonomy.web;
20
21 import java.io.InputStream;
22 import java.util.Enumeration;
23
24 import javax.servlet.http.Cookie;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpSession;
27
28 import net.wotonomy.foundation.NSArray;
29 import net.wotonomy.foundation.NSData;
30 import net.wotonomy.foundation.NSDictionary;
31 import net.wotonomy.foundation.NSMutableArray;
32 import net.wotonomy.foundation.NSMutableData;
33 import net.wotonomy.foundation.NSMutableDictionary;
34
35 /***
36 * A pure java implementation of WORequest.
37 * This implementation is backed by an HttpServletRequest,
38 * and thus does not support application-specific subclassing.
39 * Future implementations may remove this limitation.
40 *
41 * @author michael@mpowers.net
42 * @author $Author: cgruber $
43 * @version $Revision: 905 $
44 */
45 public class WORequest extends WOResponse
46 {
47 HttpServletRequest request;
48 private WOApplication application;
49 private NSArray languages;
50 private String requestHandlerKey;
51 private String requestHandlerPath;
52 private String pageName;
53 private String contextID;
54 private String senderID;
55 private String defaultFormValueEncoding;
56
57 /***
58 * Parameterless constructor which should not be called.
59 */
60 public WORequest ()
61 {
62 throw new RuntimeException(
63 "This constructor is not yet supported." );
64 }
65
66 /***
67 * Standard constructor. Method and URL are required.
68 * HeaderMap is a map of header names to arrays containing
69 * one or more values. Data is the content of the request.
70 * UserInfo contains application-defined paramters that get
71 * passed to all objects involved in dispatching the request.
72 */
73 public WORequest
74 (String aMethod, String aURL, String aProtocolName,
75 NSDictionary headerMap, NSData aData, NSDictionary userInfo)
76 {
77 throw new RuntimeException(
78 "This constructor is not yet supported." );
79 }
80
81 /***
82 * The only supported constructor for this implementation.
83 * This WORequest will wrap the specified servlet request.
84 */
85 public WORequest( HttpServletRequest aRequest, WOApplication anApplication )
86 {
87 request = aRequest;
88 application = anApplication;
89
90 languages = null;
91 senderID = null;
92 pageName = null;
93 contextID = null;
94 defaultFormValueEncoding = "ISO8859_1";
95 requestHandlerKey = WOApplication.directActionRequestHandlerKey();
96 requestHandlerPath = request.getServletPath();
97 String remainder = requestHandlerPath;
98 if ( requestHandlerPath == null ) requestHandlerPath = "";
99 if ( requestHandlerPath.length() > 0 )
100 {
101 int i;
102
103
104 i = requestHandlerPath.indexOf( "/", 1 );
105 if ( i != -1 )
106 {
107 requestHandlerKey = requestHandlerPath.substring( 1, i );
108 requestHandlerPath = requestHandlerPath.substring( i );
109 }
110
111 Enumeration e = requestHandlerPathArray().objectEnumerator();
112
113 if ( e.hasMoreElements() )
114 {
115 pageName = e.nextElement().toString();
116 }
117 if ( e.hasMoreElements() )
118 {
119 contextID = e.nextElement().toString();
120 }
121 if ( e.hasMoreElements() )
122 {
123 senderID = e.nextElement().toString();
124 }
125 }
126 }
127
128 /***
129 * Returns the HTTP method of the request: "GET" or "POST",
130 * or possibly "PUT".
131 */
132 public String method ()
133 {
134 return request.getMethod();
135 }
136
137 /***
138 * Returns the Uniform Resource Identifier, which is the part
139 * of the request URL after the protocol name (after the port
140 * number) and before the query parameters (before the question mark).
141 */
142 public String uri ()
143 {
144 return request.getRequestURI();
145 }
146
147 /***
148 * Returns the name of the protocol (presumably HTTP) and the
149 * version used by the client as sent in the request headers.
150 */
151 public String httpVersion ()
152 {
153 return request.getProtocol();
154 }
155
156 /***
157 * Returns an array of the header names in this request
158 * in no particular order.
159 */
160 public NSArray headerKeys ()
161 {
162 return arrayFromEnumeration( request.getHeaderNames() );
163 }
164
165 /***
166 * Returns an array of the header values for the specified key
167 * in no particular order.
168 */
169 public NSArray headersForKey (String aString)
170 {
171 return arrayFromEnumeration( request.getHeaders( aString ) );
172 }
173
174 /***
175 * Returns one value for the specified header key.
176 * Provided as a convenience since most headers have
177 * only one value. Returns null if not found.
178 */
179 public String headerForKey (String aKey)
180 {
181 return request.getHeader( aKey );
182 }
183
184 /***
185 * Returns the content of the request, or null if no content.
186 * The type of the content is determined by the "content-type" header.
187 * On error, null is returned.
188 */
189 public NSData content ()
190 {
191
192 NSMutableData data = new NSMutableData();
193 try
194 {
195 byte[] buf = new byte[ request.getContentLength() ];
196 InputStream is = request.getInputStream();
197
198
199 int len;
200 while ( ( len = is.read( buf ) ) > -1 )
201 {
202
203 data.appendData( new NSData( buf, 0, len ) );
204 }
205 }
206 catch ( Exception exc )
207 {
208 return null;
209 }
210 return data;
211 }
212
213 /***
214 * Returns the application-specific userInfo dictionary.
215 * This implementation returns the servlet attribute map.
216 */
217 public NSDictionary userInfo ()
218 {
219
220 Object key, value;
221 NSMutableDictionary info = new NSMutableDictionary();
222 java.util.Enumeration e = request.getAttributeNames();
223 while ( e.hasMoreElements() )
224 {
225 key = e.nextElement();
226 value = request.getAttribute( e.nextElement().toString() );
227 if ( value != null )
228 {
229 info.setObjectForKey( value, key );
230 }
231 }
232 return info;
233 }
234
235 /***
236 * Returns the items in the request handler path parsed
237 * by the "/" delimiter and put into an array.
238 */
239 public NSArray requestHandlerPathArray ()
240 {
241 return NSArray.componentsSeparatedByString( requestHandlerPath(), "/" );
242 }
243
244 /***
245 * Returns the client's preferred languages in decreasing
246 * order of preference. The strings are returned in java
247 * Locale format, meaning dashes (-) are converted to
248 * underbars (_): see java.util.Locale.toString().
249 */
250 public NSArray browserLanguages ()
251 {
252 if ( languages == null )
253 {
254 languages = arrayFromEnumeration( request.getLocales() );
255 }
256 return languages;
257 }
258
259 /***
260 * Returns the portion of the URI specifying the engine within which
261 * this web application is running. This is important for generating
262 * URLs to be used in the content of the response.
263 */
264 public String adaptorPrefix ()
265 {
266
267 String name = request.getServletPath();
268 return name;
269
270
271
272
273 }
274
275 /***
276 * Returns the application name as specified in the request URI.
277 * Note that wotonomy web applications do not typically have a .woa
278 * extension, but the extension will be included for those that do.
279 */
280 public String applicationName ()
281 {
282 return request.getContextPath();
283 }
284
285 /***
286 * Returns the id of the application instance that is needed to
287 * service this request. -1 indicates that the request is not
288 * specific to a particular instance of the application.
289 * This implementation currently returns -1.
290 */
291 public int applicationNumber ()
292 {
293 return -1;
294 }
295
296 /***
297 * Returns the portion of the URI that specifies which request handler
298 * should handle the request.
299 */
300 public String requestHandlerKey ()
301 {
302 return requestHandlerKey;
303 }
304
305 /***
306 * Returns the portion of the URI that specifies path information
307 * for the request, not including the query string.
308 */
309 public String requestHandlerPath ()
310 {
311 return requestHandlerPath;
312 }
313
314 /***
315 * Returns the unique identifier for the sessions associated with
316 * this request, or null if no session is found.
317 */
318 public String sessionID ()
319 {
320 HttpSession session = request.getSession( false );
321 if ( session == null ) return null;
322 return session.getId();
323 }
324
325 /***
326 * Returns an array containing all the form keys in the request.
327 */
328 public NSArray formValueKeys ()
329 {
330 return arrayFromEnumeration( request.getParameterNames() );
331 }
332
333 /***
334 * Returns an array of the values for the specified key in
335 * no particular order.
336 */
337 public NSArray formValuesForKey (String aKey)
338 {
339 NSMutableArray result = new NSMutableArray();
340 String[] values = request.getParameterValues( aKey );
341 if ( values != null )
342 {
343 for ( int i = 0; i < values.length; i++ )
344 {
345 result.addObject( values[i] );
346 }
347 }
348 return result;
349 }
350
351 /***
352 * Returns one value for the specified key.
353 * Provided as a convenience since most keys have
354 * only one value. Returns null if not found.
355 */
356 public Object formValueForKey (String aKey)
357 {
358 return request.getParameter( aKey );
359 }
360
361 /***
362 * Returns the value for the specified key, as a String.
363 */
364 public String stringFormValueForKey(String key) {
365 Object x = formValueForKey(key);
366 if (x != null)
367 return x.toString();
368 return null;
369 }
370
371 /***
372 * Returns a dictionary containing all the key-value
373 * mappings in the request.
374 */
375 public NSDictionary formValues ()
376 {
377 NSMutableDictionary result = new NSMutableDictionary ();
378 java.util.Enumeration e = request.getParameterNames();
379 String key;
380 while ( e.hasMoreElements() )
381 {
382 key = e.nextElement().toString();
383 result.setObjectForKey( formValuesForKey( key ), key );
384 }
385 return result;
386 }
387
388 /***
389 * Returns whether the request is from a java-based client component.
390 * This implementation returns false.
391 */
392 public boolean isFromClientComponent ()
393 {
394 return false;
395 }
396
397 /***
398 * Returns an array of cookie values for the specified key in
399 * no particular order.
400 */
401 public NSArray cookieValuesForKey (String aKey)
402 {
403
404 NSMutableArray result = new NSMutableArray();
405 Cookie[] cookies = request.getCookies();
406 if ( cookies == null ) return result;
407
408 for ( int i = 0; i < cookies.length; i++ )
409 {
410 if ( cookies[i].getName().equals( aKey ) )
411 {
412 result.addObject( cookies[i].getValue() );
413 }
414 }
415
416 return result;
417 }
418
419 /***
420 * Returns one value for the specified cookie key.
421 * Provided as a convenience since most cookies have
422 * only one value. Returns null if not found.
423 */
424 public String cookieValueForKey (String aKey)
425 {
426
427 Cookie[] cookies = request.getCookies();
428 if ( cookies == null ) return null;
429
430 for ( int i = 0; i < cookies.length; i++ )
431 {
432 if ( cookies[i].getName().equals( aKey ) )
433 {
434 return cookies[i].getValue();
435 }
436 }
437
438 return null;
439 }
440
441 /***
442 * Returns a dictionary of cookie key-value mappings.
443 */
444 public NSDictionary cookieValues ()
445 {
446
447 NSMutableDictionary result = new NSMutableDictionary();
448 Cookie[] cookies = request.getCookies();
449 if ( cookies == null ) return result;
450
451 NSMutableArray value;
452 for ( int i = 0; i < cookies.length; i++ )
453 {
454 value = (NSMutableArray) result.objectForKey(
455 cookies[i].getName() );
456 if ( value == null )
457 {
458 value = new NSMutableArray();
459 result.setObjectForKey(
460 cookies[i].getValue(), cookies[i].getName() );
461 }
462 value.addObject( cookies[i].getValue() );
463 }
464
465 return result;
466 }
467
468 /***
469 * Sets the default character encoding.
470 */
471 public void setDefaultFormValueEncoding (String encoding)
472 {
473 defaultFormValueEncoding = encoding;
474 }
475
476 /***
477 * Returns the default form value encoding ("ISO8859_1").
478 */
479 public String defaultFormValueEncoding ()
480 {
481 return defaultFormValueEncoding;
482 }
483
484 /***
485 * Sets whether the appropriate encoding scheme for decoding
486 * the form values will be automatically determined.
487 */
488 public void setFormValueEncodingDetectionEnabled (boolean enabled)
489 {
490 throw new RuntimeException( "Not yet implemented." );
491 }
492
493 /***
494 * Gets whether the appropriate encoding scheme for decoding
495 * the form values is currently automatically determined.
496 */
497 public boolean isFormValueEncodingDetectionEnabled ()
498 {
499 throw new RuntimeException( "Not yet implemented." );
500 }
501
502 /***
503 * Gets the current method used for decoding form values.
504 */
505 public int formValueEncoding ()
506 {
507 throw new RuntimeException( "Not yet implemented." );
508 }
509
510 /***
511 * Returns the host name of the server that is the target of this request.
512 * NOTE: This method is not published in the WORequest specification.
513 */
514 String applicationHost ()
515 {
516
517 return request.getServerName();
518 }
519
520 /***
521 * Returns the port of the server that is the target of this request.
522 * NOTE: This method is not published in the WORequest specification.
523 */
524 int port()
525 {
526
527 return request.getServerPort();
528 }
529
530 /***
531 * Returns the backing HttpServletRequest.
532 */
533 HttpServletRequest servletRequest ()
534 {
535 return request;
536 }
537
538 /***
539 * Returns the application that was the target of this request.
540 * This method is not published in the WORequest specification.
541 */
542 WOApplication application ()
543 {
544 return application;
545 }
546
547 /***
548 * This method is not published in the WORequest specification.
549 * This sender id from the URI, which is the id of the element
550 * that generated this request.
551 */
552 String senderID ()
553 {
554 return senderID;
555 }
556
557 /***
558 * This method is not published in the WORequest specification.
559 * This returns the context id from the URI.
560 */
561 String contextID ()
562 {
563 return contextID;
564 }
565
566 /***
567 * This method is not published in the WORequest specification.
568 */
569 String pageName ()
570 {
571 return pageName;
572 }
573
574 /***
575 * Convenience method to populate an NSArray from an Enumeration.
576 */
577 private static NSArray arrayFromEnumeration( java.util.Enumeration e )
578 {
579 NSMutableArray result = new NSMutableArray();
580 while ( e.hasMoreElements() )
581 {
582 result.addObject( e.nextElement() );
583 }
584 return result;
585 }
586 }