Coverage Report - net.wotonomy.web.WORequest
 
Classes in this File Line Coverage Branch Coverage Complexity
WORequest
0% 
0% 
1.927
 
 1  
 /*
 2  
 Wotonomy: OpenStep design patterns for pure Java applications.
 3  
 Copyright (C) 2000 Blacksmith, Inc.
 4  
 
 5  
 This library is free software; you can redistribute it and/or
 6  
 modify it under the terms of the GNU Lesser General Public
 7  
 License as published by the Free Software Foundation; either
 8  
 version 2.1 of the License, or (at your option) any later version.
 9  
 
 10  
 This library is distributed in the hope that it will be useful,
 11  
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 Lesser General Public License for more details.
 14  
 
 15  
 You should have received a copy of the GNU Lesser General Public
 16  
 License along with this library; if not, see http://www.gnu.org
 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  0
     public WORequest ()
 61  0
     {
 62  0
                 throw new RuntimeException( 
 63  0
                         "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  0
     public WORequest 
 74  
             (String aMethod, String aURL, String aProtocolName, 
 75  
             NSDictionary headerMap, NSData aData, NSDictionary userInfo)
 76  0
         {
 77  0
                 throw new RuntimeException( 
 78  0
                         "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  0
         public WORequest( HttpServletRequest aRequest, WOApplication anApplication )
 86  0
         {
 87  0
                 request = aRequest;
 88  0
         application = anApplication;
 89  
         
 90  0
         languages = null;
 91  0
         senderID = null;
 92  0
         pageName = null;
 93  0
         contextID = null;
 94  0
         defaultFormValueEncoding = "ISO8859_1";
 95  0
         requestHandlerKey = WOApplication.directActionRequestHandlerKey();
 96  0
         requestHandlerPath = request.getServletPath(); // request.getPathInfo();
 97  0
         String remainder = requestHandlerPath;
 98  0
         if ( requestHandlerPath == null ) requestHandlerPath = "";
 99  0
         if ( requestHandlerPath.length() > 0 )
 100  
         {
 101  
             int i;
 102  
             
 103  
             // get request handler key
 104  0
             i = requestHandlerPath.indexOf( "/", 1 );
 105  0
             if ( i != -1 )
 106  
             {
 107  0
                 requestHandlerKey = requestHandlerPath.substring( 1, i );
 108  0
                 requestHandlerPath = requestHandlerPath.substring( i );
 109  
             }
 110  
             
 111  0
             Enumeration e = requestHandlerPathArray().objectEnumerator();
 112  
             // skipping session ID for now
 113  0
             if ( e.hasMoreElements() )
 114  
             {
 115  0
                 pageName = e.nextElement().toString();
 116  
             }
 117  0
             if ( e.hasMoreElements() )
 118  
             {
 119  0
                 contextID = e.nextElement().toString();
 120  
             }
 121  0
             if ( e.hasMoreElements() )
 122  
             {
 123  0
                 senderID = e.nextElement().toString();
 124  
             }
 125  
         }
 126  0
         }
 127  
 
 128  
     /**
 129  
     * Returns the HTTP method of the request: "GET" or "POST", 
 130  
     * or possibly "PUT".
 131  
     */
 132  
     public String method ()
 133  
     {
 134  0
             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  0
             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  0
             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  0
             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  0
             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  0
             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  
             //TODO: This is broken!
 192  0
             NSMutableData data = new NSMutableData();
 193  
             try
 194  
             {
 195  0
                     byte[] buf = new byte[ request.getContentLength() ];
 196  0
                     InputStream is = request.getInputStream();
 197  
                         
 198  
                         // this is so very not efficient
 199  
                         int len;
 200  0
                     while ( ( len = is.read( buf ) ) > -1 )
 201  
                     {
 202  
                             // copies data twice...
 203  0
                             data.appendData( new NSData( buf, 0, len ) ); 
 204  0
                     }
 205  
                 }
 206  0
                 catch ( Exception exc )
 207  
                 {
 208  0
                         return null;
 209  0
                 }
 210  0
                 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  
             //TODO: Test this logic.
 220  
             Object key, value;
 221  0
             NSMutableDictionary info = new NSMutableDictionary();
 222  0
             java.util.Enumeration e = request.getAttributeNames();
 223  0
             while ( e.hasMoreElements() )
 224  
             {
 225  0
                     key = e.nextElement();
 226  0
                     value = request.getAttribute( e.nextElement().toString() );
 227  0
                     if ( value != null )
 228  
                     {
 229  0
                             info.setObjectForKey( value, key ); 
 230  0
                     }
 231  
             }
 232  0
             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  0
             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  0
         if ( languages == null )
 253  
         {
 254  0
                 languages = arrayFromEnumeration( request.getLocales() );
 255  
         }
 256  0
         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  
             //TODO: Test this logic.
 267  0
             String name = request.getServletPath();
 268  0
         return name;
 269  
         
 270  
 //            String uri = request.getRequestURI();
 271  
 //            int end = uri.indexOf( request.getPathInfo() );
 272  
 //            return uri.substring( request.getContextPath().length(), end );
 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  0
         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  0
                 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  0
         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  0
         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  0
             HttpSession session = request.getSession( false );
 321  0
             if ( session == null ) return null;
 322  0
             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  0
             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  0
             NSMutableArray result = new NSMutableArray();
 340  0
             String[] values = request.getParameterValues( aKey );
 341  0
         if ( values != null )
 342  
         {
 343  0
             for ( int i = 0; i < values.length; i++ )
 344  
             {
 345  0
                 result.addObject( values[i] );
 346  
             }
 347  
         }
 348  0
             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  0
             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  0
         Object x = formValueForKey(key);
 366  0
         if (x != null)
 367  0
             return x.toString();
 368  0
         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  0
             NSMutableDictionary result = new NSMutableDictionary ();
 378  0
             java.util.Enumeration e = request.getParameterNames();
 379  
             String key;
 380  0
             while ( e.hasMoreElements() )
 381  
             {
 382  0
                     key = e.nextElement().toString();
 383  0
                     result.setObjectForKey( formValuesForKey( key ), key );
 384  0
             }
 385  0
             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  0
             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  
             // TODO: Test this logic.
 404  0
             NSMutableArray result = new NSMutableArray();
 405  0
             Cookie[] cookies = request.getCookies();
 406  0
             if ( cookies == null ) return result;
 407  
             
 408  0
             for ( int i = 0; i < cookies.length; i++ )
 409  
             {
 410  0
                     if ( cookies[i].getName().equals( aKey ) )
 411  
                     {
 412  0
                             result.addObject( cookies[i].getValue() );
 413  
                     } 
 414  
             }
 415  
             
 416  0
             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  
             // TODO: Test this logic.
 427  0
             Cookie[] cookies = request.getCookies();
 428  0
             if ( cookies == null ) return null;
 429  
             
 430  0
             for ( int i = 0; i < cookies.length; i++ )
 431  
             {
 432  0
                     if ( cookies[i].getName().equals( aKey ) )
 433  
                     {
 434  0
                             return cookies[i].getValue();
 435  
                     } 
 436  
             }
 437  
             
 438  0
             return null;
 439  
     }
 440  
     
 441  
     /**
 442  
     * Returns a dictionary of cookie key-value mappings. 
 443  
     */
 444  
     public NSDictionary cookieValues ()
 445  
     {
 446  
             // TODO: Test this logic.
 447  0
             NSMutableDictionary result = new NSMutableDictionary();
 448  0
             Cookie[] cookies = request.getCookies();
 449  0
             if ( cookies == null ) return result;
 450  
             
 451  
             NSMutableArray value;
 452  0
             for ( int i = 0; i < cookies.length; i++ )
 453  
             {
 454  0
                     value = (NSMutableArray) result.objectForKey( 
 455  0
                             cookies[i].getName() );
 456  0
                     if ( value == null ) 
 457  
                     {
 458  0
                             value = new NSMutableArray();
 459  0
                 result.setObjectForKey( 
 460  0
                                         cookies[i].getValue(), cookies[i].getName() );
 461  
                         }
 462  0
                     value.addObject( cookies[i].getValue() );
 463  
             }
 464  
             
 465  0
             return result;
 466  
     }
 467  
 
 468  
     /**
 469  
     * Sets the default character encoding.
 470  
     */
 471  
     public void setDefaultFormValueEncoding (String encoding)
 472  
     {
 473  0
             defaultFormValueEncoding = encoding;
 474  0
     }
 475  
     
 476  
     /**
 477  
     * Returns the default form value encoding ("ISO8859_1").
 478  
     */
 479  
     public String defaultFormValueEncoding ()
 480  
     {
 481  0
             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  0
             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  0
             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  0
             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  
         // FIXME: this should call WOApplication.hostname();
 517  0
         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  
         // FIXME: this should call WOApplication.port();
 527  0
         return request.getServerPort();
 528  
     }
 529  
     
 530  
     /**
 531  
     * Returns the backing HttpServletRequest.
 532  
     */
 533  
     HttpServletRequest servletRequest ()
 534  
     {
 535  0
             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  0
             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  0
             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  0
             return contextID;
 564  
     }
 565  
     
 566  
     /**
 567  
     * This method is not published in the WORequest specification.
 568  
     */
 569  
     String pageName ()
 570  
     {
 571  0
             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  0
             NSMutableArray result = new NSMutableArray();
 580  0
             while ( e.hasMoreElements() )
 581  
             {
 582  0
                     result.addObject( e.nextElement() );
 583  0
             }
 584  0
             return result;
 585  
     }
 586  
 }