Coverage Report - net.wotonomy.web.WOContext
 
Classes in this File Line Coverage Branch Coverage Complexity
WOContext
0% 
0% 
1.636
 
 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.IOException;
 22  
 import java.util.Iterator;
 23  
 import java.util.LinkedList;
 24  
 import java.util.List;
 25  
 import java.util.Map;
 26  
 
 27  
 /**
 28  
 * A pure java implementation of WOContext.
 29  
 *
 30  
 * @author michael@mpowers.net
 31  
 * @author $Author: cgruber $
 32  
 * @version $Revision: 905 $
 33  
 */
 34  0
 public class WOContext
 35  
 {
 36  
         private WOSession session;
 37  
         private WORequest request;
 38  
         private WOResponse response;
 39  
     private List elementStack;
 40  
         private boolean isInForm;
 41  
         private boolean isDistributionEnabled;
 42  
     private static final String EMPTY = "";
 43  
     private static final String SEP = ".";
 44  
     private static final String ZERO = "0";
 45  
     private static final String HTTP = "http://";
 46  
     private static final String HTTPS = "https://";
 47  
 
 48  
         // package access
 49  
         WOComponent page;
 50  
         WOComponent component;
 51  
         StringBuffer elementID;
 52  
     
 53  0
     private static volatile int contextCounter = 0;
 54  
     private String contextID;
 55  
     
 56  
         /**
 57  
         * Default constructor performs necessary initialization.
 58  
         * Subclassers should override the static factory method below.
 59  
         */
 60  0
     public WOContext ()
 61  0
     {
 62  0
         contextID = null;
 63  0
             elementID = new StringBuffer();
 64  0
         elementStack = new LinkedList();
 65  0
     }
 66  
     
 67  
         /**
 68  
         * Preferred constructor performs necessary initialization.
 69  
         * Subclassers should override this method.
 70  
         */
 71  
     public WOContext (WORequest aRequest)
 72  
     {
 73  0
             this();
 74  0
             request = aRequest;
 75  0
         response = new WOResponse();
 76  0
     }
 77  
     
 78  
         /** 
 79  
         * Simply calls the preferred constructor.
 80  
         * Included for compatibility.
 81  
         */
 82  
     public static WOContext contextWithRequest (WORequest aRequest)
 83  
     {
 84  0
         String id = Integer.toString( contextCounter++ );
 85  0
             WOContext result = new WOContext( aRequest );
 86  0
         result.contextID = id;
 87  0
         return result;
 88  
     }
 89  
     
 90  
         /** 
 91  
         * Returns the context id.
 92  
         */
 93  
     public String contextID ()
 94  
     {
 95  0
             return contextID;
 96  
     }
 97  
     
 98  
         /** 
 99  
         * Returns the sender id, or null if it doesn't exist.
 100  
         */
 101  
     public String senderID ()
 102  
     {
 103  0
             return request.senderID();
 104  
     }
 105  
     
 106  
         /** 
 107  
         * Returns the element id, or null if it doesn't exist.
 108  
         */
 109  
     public String elementID ()
 110  
     {
 111  0
             return elementID.toString();
 112  
     }
 113  
 
 114  
         /** 
 115  
         * Returns this context's application, or null if it doesn't exist.
 116  
         */
 117  
     public WOApplication application ()
 118  
     {
 119  0
             return request.application();
 120  
     }
 121  
      
 122  
         /** 
 123  
     * Returns whether a session has been created for the associated request.
 124  
         */
 125  
     public boolean hasSession ()
 126  
     {
 127  0
             return ( session != null );
 128  
     }
 129  
     
 130  
         /** 
 131  
         * Returns this context's session, creating one if it doesn't exist.
 132  
         */
 133  
     public WOSession session ()
 134  
     {
 135  0
             if ( session == null )
 136  
             {
 137  
             // so far we can't figure out how the direct action handler can avoid creating a session
 138  0
             throw new RuntimeException( "WOContext.session: Lazy instantiation not yet implemented." );
 139  
 /*            
 140  
             session = application().restoreSessionWithID( 
 141  
                 request.sessionID(), this );
 142  
             if ( session == null )
 143  
             {
 144  
                 session = application().createSessionForRequest( request );
 145  
                 session.setContext( this );
 146  
             }
 147  
 */            
 148  
             }
 149  0
             return session;
 150  
     }
 151  
     
 152  
     /**
 153  
     * Package access only.
 154  
     */
 155  
     void setSession( WOSession aSession )
 156  
     {
 157  0
         session = aSession;
 158  0
     }
 159  
     
 160  
         /** 
 161  
         * Returns this context's request.
 162  
         */
 163  
     public WORequest request ()
 164  
     {
 165  0
             return request;
 166  
     }
 167  
     
 168  
         /** 
 169  
         * Returns this context's response.
 170  
         */
 171  
     public WOResponse response ()
 172  
     {
 173  0
             return response;
 174  
     }
 175  
     
 176  
         /** 
 177  
         * Returns the current page.
 178  
         */
 179  
     public WOComponent page ()
 180  
     {
 181  0
         return (WOComponent) elementStack.get( elementStack.size()-1 );
 182  
     }
 183  
     
 184  
         /** 
 185  
         * Returns the current component.
 186  
         */
 187  
     public WOComponent component ()
 188  
     {
 189  
         Object o;
 190  0
             Iterator i = elementStack.iterator();
 191  0
         while ( i.hasNext() )
 192  
         {
 193  0
             o = i.next();
 194  0
             if ( o instanceof WOComponent ) return (WOComponent) o;
 195  
         }
 196  0
         return null;
 197  
     }        
 198  
 
 199  
     /**
 200  
     * Returns the current component's parent.
 201  
     */    
 202  
     WOComponent parent ()
 203  
     {
 204  
         Object o;
 205  0
             Iterator i = elementStack.iterator();
 206  0
         if ( i.hasNext() )
 207  
         {
 208  
             // skip current component
 209  0
             o = i.next();
 210  
         }
 211  0
         while ( i.hasNext() )
 212  
         {
 213  0
             o = i.next();
 214  0
             if ( o instanceof WOComponent ) 
 215  
             {
 216  0
                 return (WOComponent) o;
 217  
             }
 218  
         }
 219  0
         return null;
 220  
     }
 221  
     
 222  
     /**
 223  
     * Pushes an element onto the stack.
 224  
     * Package access only.
 225  
     */
 226  
     void pushElement( WOElement aComponent )
 227  
     {
 228  0
         elementStack.add( 0, aComponent );
 229  0
     }
 230  
     
 231  
     /**
 232  
     * Pops an element off the stack.
 233  
     * Package access only.
 234  
     */
 235  
     WOElement popElement()
 236  
     {
 237  0
         return (WOElement) elementStack.remove(0);
 238  
     }
 239  
     
 240  
         /** 
 241  
         * Returns whether the current context is in a form.
 242  
         */
 243  
     public boolean isInForm ()
 244  
     {
 245  0
             return isInForm;
 246  
         }
 247  
     
 248  
         /** 
 249  
         * Sets whether the current context is in a WOForm. 
 250  
         */
 251  
     public void setInForm (boolean inForm)
 252  
     {
 253  0
             isInForm = inForm;
 254  0
     }
 255  
     
 256  
         /** 
 257  
         * Appends the specified string to the end of the element id.
 258  
         * For example, if the element id is "0.1", sending "Test" 
 259  
         * changes the element id to "0.1.Test".
 260  
         */
 261  
     public void appendElementIDComponent (String aString)
 262  
     {
 263  0
         if ( elementID.length() > 0 )
 264  
         {
 265  0
                 elementID.append( SEP );
 266  
         }
 267  0
         elementID.append( aString );
 268  0
     }
 269  
     
 270  
         /** 
 271  
         * Appends a zero to the element id to represent the first
 272  
         * new child component.  For example, if the element id is "0.1",
 273  
         * calling this changes the element id to "0.1.0".
 274  
         */
 275  
     public void appendZeroElementIDComponent ()
 276  
     {
 277  0
         if ( elementID.length() > 0 )
 278  
         {
 279  0
             elementID.append( SEP );
 280  
         }
 281  0
         elementID.append( ZERO );
 282  0
     }
 283  
     
 284  
         /** 
 285  
         * Increments the last component of the element id.
 286  
         * For example, if the element id is "0.1", calling this
 287  
         * changes the element id to "0.2".
 288  
         */
 289  
     public void incrementLastElementIDComponent ()
 290  
     {        
 291  
             String last;
 292  0
         String id = elementID.toString();
 293  0
         int index = id.lastIndexOf( SEP );
 294  0
             if ( index == -1 )
 295  
         {
 296  0
             last = id;
 297  0
         }
 298  
         else
 299  
         {
 300  0
             last = id.substring( index + 1 );
 301  
         }
 302  
         
 303  0
         deleteLastElementIDComponent();
 304  
         
 305  
         try
 306  
         {
 307  0
             appendElementIDComponent( 
 308  0
                 Integer.toString( Integer.parseInt( last ) + 1 ) );
 309  
         }
 310  0
         catch ( Exception exc )
 311  
         {
 312  0
             System.err.println( "Error parsing id: " + last );
 313  0
             appendZeroElementIDComponent();
 314  0
         }
 315  
         //System.out.println( "WOContext: " + elementID );        
 316  0
     }
 317  
     
 318  
         /** 
 319  
         * Deletes the last component of the element id.
 320  
         * For example, if the element id is "0.1", callling this
 321  
         * changes the element id to "0".
 322  
         */
 323  
     public void deleteLastElementIDComponent ()
 324  
     {
 325  0
             int index = elementID.toString().lastIndexOf( SEP );
 326  0
             if ( index == -1 )
 327  
         {
 328  0
             elementID.setLength( 0 );   
 329  0
         }
 330  
         else
 331  
         {
 332  0
             elementID.setLength( index );
 333  
         }
 334  0
     }
 335  
     
 336  
         /** 
 337  
         * Deletes all components of the element id.
 338  
         * This makes the element id an empty string.
 339  
         */
 340  
     public void deleteAllElementIDComponents ()
 341  
     {
 342  0
             elementID.setLength( 0 );
 343  0
     }
 344  
     
 345  
         /** 
 346  
         * Returns a URL for the named action with query parameters
 347  
         * as specified by the dictionary.
 348  
         */
 349  
     public String directActionURLForActionNamed (
 350  
             String anActionName, Map aQueryDict)
 351  
     {
 352  0
             StringBuffer query = new StringBuffer();
 353  
         
 354  
         try
 355  
         {
 356  
             String key;
 357  0
             Iterator i = aQueryDict.keySet().iterator();
 358  0
             while ( i.hasNext() )
 359  
             {
 360  0
                 key = i.next().toString();
 361  0
                 query.append( URI.encode( key, 
 362  0
                     URI.allowed_within_query ) );
 363  0
                 query.append( '=' );
 364  0
                 query.append( URI.encode( aQueryDict.get( key ).toString(), 
 365  0
                     URI.allowed_within_query ) );
 366  0
                 if ( i.hasNext() )
 367  
                 {
 368  0
                     query.append( '&' );
 369  0
                 }
 370  
             }
 371  
         } 
 372  0
         catch ( IOException exc )
 373  
         {
 374  
             // report error
 375  0
             System.err.println( 
 376  0
                 "directActionURLForActionNamed: " + anActionName + " : " + aQueryDict );
 377  0
             System.err.println( exc );
 378  
             
 379  
             // delete query string
 380  0
             query = new StringBuffer();
 381  0
         }
 382  
         
 383  0
         return urlWithRequestHandlerKey(
 384  0
             WOApplication.directActionRequestHandlerKey(), 
 385  0
             anActionName, query.toString() );
 386  
     }
 387  
     
 388  
         /** 
 389  
         * Returns the complete URL for the current component action.
 390  
         */
 391  
     public String componentActionURL ()
 392  
     {
 393  0
         StringBuffer buffer = new StringBuffer();
 394  0
         buffer.append( request().applicationName() );
 395  0
         buffer.append( '/' );
 396  0
         buffer.append( WOApplication.application().componentRequestHandlerKey() );
 397  0
         buffer.append( '/' );
 398  0
         buffer.append( page().name() );
 399  0
         buffer.append( '/' );
 400  0
         buffer.append( contextID );
 401  0
         buffer.append( '/' );
 402  0
         buffer.append( elementID );
 403  0
             return buffer.toString();
 404  
     }
 405  
     
 406  
         /** 
 407  
         * Returns a URL relative to the servlet for the specified 
 408  
         * request handler, action, and query string.
 409  
         */
 410  
     public String urlWithRequestHandlerKey (
 411  
             String aRequestHandlerKey, String aPath, String aQueryString)
 412  
     {
 413  0
         StringBuffer buffer = new StringBuffer();
 414  0
         buffer.append( request().applicationName() );
 415  0
         buffer.append( '/' );
 416  0
         buffer.append( aRequestHandlerKey );
 417  0
         buffer.append( '/' );
 418  0
         buffer.append( aPath );
 419  0
         if ( aQueryString != null && aQueryString.trim().length() > 0 )
 420  
         {
 421  0
             buffer.append( '?' );
 422  0
             buffer.append( aQueryString );
 423  
         }
 424  0
             return buffer.toString();
 425  
     }
 426  
     
 427  
         /** 
 428  
         * Returns the complete URL for the specified request handler,
 429  
         * path, and query string.  isSecure determines the protocol:
 430  
         * http or https.  port is appended to the protocol, if zero,
 431  
         * the port is omitted from the URL.
 432  
         */
 433  
     public String completeURLWithRequestHandlerKey (     
 434  
             String aRequestHandlerKey, String aPath, String aQueryString,
 435  
                 boolean isSecure, int port)
 436  
     {
 437  0
             StringBuffer buffer = new StringBuffer();
 438  
         
 439  0
         if ( isSecure )
 440  
         {
 441  0
             buffer.append( HTTPS );
 442  0
         }
 443  
         else
 444  
         {
 445  0
             buffer.append( HTTP );
 446  
         }
 447  
         
 448  0
         buffer.append( request.applicationHost() );
 449  
         
 450  0
         if ( port != 0 && port != 80 )
 451  
         {
 452  0
             buffer.append( ':' );
 453  0
             buffer.append( Integer.toString( port ) );
 454  
         }
 455  
         
 456  0
         buffer.append( urlWithRequestHandlerKey( 
 457  0
             aRequestHandlerKey, aPath, aQueryString ) );
 458  
         
 459  0
         return buffer.toString();
 460  
     }
 461  
     
 462  
         /** 
 463  
         * Sets whether distribution is enabled.
 464  
         */
 465  
     public void setDistributionEnabled (boolean distributionEnabled)
 466  
     {
 467  0
             isDistributionEnabled = distributionEnabled;
 468  0
     }
 469  
     
 470  
         /** 
 471  
         * Returns whether distribution is enabled.
 472  
         */
 473  
     public boolean isDistributionEnabled ()
 474  
     {
 475  0
             return isDistributionEnabled;
 476  
     }
 477  
     
 478  
         /** 
 479  
         * This method is not included in the WOContext specification.
 480  
     * This implementation returns "" since only cookie ids are 
 481  
     * currently supported.
 482  
         */
 483  
     String urlSessionPrefix ()
 484  
     {
 485  0
             return EMPTY; // "/" + sessionid;
 486  
     }
 487  
     
 488  
         /** 
 489  
         * Returns the relative URL for the current page.
 490  
         */
 491  
     String url ()
 492  
     {
 493  0
             throw new RuntimeException( "Not implemented yet." );
 494  
     }
 495  
     
 496  
     public String toString()
 497  
     {
 498  0
         return "[WOContext@"+Integer.toHexString(System.identityHashCode(this))
 499  0
             +":id=" + contextID +":page=" + page + ":component=" + component + ":element=" + elementID + "]";
 500  
     }
 501  
 }
 502  
 
 503  
 /*
 504  
  * $Log$
 505  
  * Revision 1.2  2006/02/19 01:44:02  cgruber
 506  
  * Add xmlrpc files
 507  
  * Remove jclark and replace with dom4j and javax.xml.sax stuff
 508  
  * Re-work dependencies and imports so it all compiles.
 509  
  *
 510  
  * Revision 1.1  2006/02/16 13:22:22  cgruber
 511  
  * Check in all sources in eclipse-friendly maven-enabled packages.
 512  
  *
 513  
  * Revision 1.19  2003/08/07 00:15:15  chochos
 514  
  * general cleanup (mostly removing unused imports)
 515  
  *
 516  
  * Revision 1.18  2003/02/21 16:40:23  mpowers
 517  
  * Now reading port and smtp host from system properties.
 518  
  * Implemented WOApplication.main.
 519  
  *
 520  
  * Revision 1.17  2003/01/24 20:12:54  mpowers
 521  
  * Better parent determination.
 522  
  *
 523  
  * Revision 1.16  2003/01/21 22:27:02  mpowers
 524  
  * Corrected context id usage.
 525  
  * Implemented backtracking.
 526  
  *
 527  
  * Revision 1.15  2003/01/17 20:58:19  mpowers
 528  
  * Fixed up WOHyperlink.
 529  
  *
 530  
  * Revision 1.14  2003/01/17 20:34:57  mpowers
 531  
  * Better handling for components and parents in the context's element stack.
 532  
  *
 533  
  * Revision 1.13  2003/01/14 19:48:36  mpowers
 534  
  *  - fixes to property synchronization
 535  
  *    - forms now pass takeValuesFromRequest to children
 536  
  *  - fixes to action invocation
 537  
  *    - now supporting multipleSubmit in forms
 538  
  *
 539  
  * Revision 1.12  2003/01/13 22:24:44  mpowers
 540  
  * Request-response cycle is working with session and page persistence.
 541  
  *
 542  
  * Revision 1.11  2003/01/10 20:17:41  mpowers
 543  
  * Component action urls are now working.
 544  
  *
 545  
  * Revision 1.8  2003/01/09 21:16:48  mpowers
 546  
  * Bringing request-response cycle more into conformance.
 547  
  *
 548  
  * Revision 1.7  2003/01/09 16:13:59  mpowers
 549  
  * Implemented WOComponentRequestHandler:
 550  
  * Bringing the request-response cycle more into conformance.
 551  
  *
 552  
  * Revision 1.4  2002/12/20 22:56:33  mpowers
 553  
  * Reimplemented the template parsing again.
 554  
  * Nested components are now correctly parsed.
 555  
  * ElementID numbering is now working.
 556  
  *
 557  
  * Revision 1.3  2002/12/18 14:12:38  mpowers
 558  
  * Support for differentiated request handlers.
 559  
  * Support url generation for WOContext and WORequest.
 560  
  *
 561  
  * Revision 1.2  2002/12/17 14:57:42  mpowers
 562  
  * Minor corrections to WORequests's parsing, and updated javadocs.
 563  
  *
 564  
  * Revision 1.1.1.1  2000/12/21 15:53:04  mpowers
 565  
  * Contributing wotonomy.
 566  
  *
 567  
  * Revision 1.3  2000/12/20 16:25:49  michael
 568  
  * Added log to all files.
 569  
  *
 570  
  *
 571  
  */
 572