CVS: Tapestry/framework/src/net/sf/tapestry/form Form.java,1.20.2.1,1.20.2.2 ImageSubmit.java,1.12,1.12.2.1

Howard Lewis Ship <[email protected]>
Newsgroups gmane.comp.java.tapestry.cvs
Message-ID <[email protected]>
Update of /cvsroot/tapestry/Tapestry/framework/src/net/sf/tapestry/form
In directory sc8-pr-cvs1:/tmp/cvs-serv8557/framework/src/net/sf/tapestry/form

Modified Files:
      Tag: hship-2-3
	Form.java ImageSubmit.java 
Log Message:
Change Form to record allocated element ids as a hidden field, and compare against it when the form is submitted.
Change StaleLink page to display the message from the StaleLinkException.

Index: Form.java
===================================================================
RCS file: /cvsroot/tapestry/Tapestry/framework/src/net/sf/tapestry/form/Form.java,v
retrieving revision 1.20.2.1
retrieving revision 1.20.2.2
diff -C2 -d -r1.20.2.1 -r1.20.2.2
*** Form.java	1 Dec 2002 21:43:14 -0000	1.20.2.1
--- Form.java	21 Dec 2002 13:05:45 -0000	1.20.2.2
***************
*** 29,32 ****
--- 29,33 ----
  import net.sf.tapestry.html.Body;
  import net.sf.tapestry.util.IdAllocator;
+ import net.sf.tapestry.util.StringSplitter;
  import net.sf.tapestry.valid.IValidationDelegate;
  
***************
*** 72,82 ****
  
      /**
!      *  Number of element ids allocated.
!      *
!      *  @since 1.0.2
!      *
       **/
  
!     private int _elementCount;
  
      /**
--- 73,96 ----
  
      /**
!      *  Used when rewinding the form to figure to match allocated ids (allocated during
!      *  the rewind) against expected ids (allocated in the previous request cycle, when
!      *  the form was rendered).
!      * 
!      *  @since 2.4
!      * 
       **/
  
!     private int _allocatedIdIndex;
! 
!     /**
!      *  The list of allocated ids for form elements within this form.  This list
!      *  is constructed when a form renders, and is validated against when the
!      *  form is rewound.
!      * 
!      *  @since 2.4
!      * 
!      **/
! 
!     private List _allocatedIds = new ArrayList();
  
      /**
***************
*** 91,95 ****
      private static final int EVENT_MAP_SIZE = 3;
  
!     private IdAllocator _elementIdAllocator;
  
      /**
--- 105,109 ----
      private static final int EVENT_MAP_SIZE = 3;
  
!     private IdAllocator _elementIdAllocator = new IdAllocator();
  
      /**
***************
*** 166,172 ****
       **/
  
!     public String getElementId(IComponent component)
      {
!         return getElementId(component.getId());
      }
  
--- 180,186 ----
       **/
  
!     public String getElementId(IComponent component) throws RequestCycleException
      {
!         return getElementId(component, component.getId());
      }
  
***************
*** 184,195 ****
       **/
  
!     public String getElementId(String baseId)
      {
-         if (_elementIdAllocator == null)
-             _elementIdAllocator = new IdAllocator();
- 
          String result = _elementIdAllocator.allocateId(baseId);
  
!         _elementCount++;
  
          return result;
--- 198,238 ----
       **/
  
!     public String getElementId(IComponent component, String baseId) throws RequestCycleException
      {
          String result = _elementIdAllocator.allocateId(baseId);
  
!         if (_rewinding)
!         {
!             if (_allocatedIdIndex >= _allocatedIds.size())
!             {
!                 throw new StaleLinkException(
!                     Tapestry.getString(
!                         "Form.too-many-ids",
!                         getExtendedId(),
!                         Integer.toString(_allocatedIds.size()),
!                         component.getExtendedId()),
!                     this);
!             }
! 
!             String expected = (String) _allocatedIds.get(_allocatedIdIndex);
! 
!             if (!result.equals(expected))
!                 throw new StaleLinkException(
!                     Tapestry.getString(
!                         "Form.id-mismatch",
!                         new Object[] {
!                             getExtendedId(),
!                             Integer.toString(_allocatedIdIndex + 1),
!                             expected,
!                             result,
!                             component.getExtendedId()}),
!                     this);
!         }
!         else
!         {
!             _allocatedIds.add(result);
!         }
! 
!         _allocatedIdIndex++;
  
          return result;
***************
*** 251,257 ****
          writeGestureParameters(writer, g, !renderForm);
  
!         _elementCount = 0;
  
          _rendering = true;
          renderBody(writer, cycle);
  
--- 294,308 ----
          writeGestureParameters(writer, g, !renderForm);
  
!         _allocatedIdIndex = 0;
  
          _rendering = true;
+ 
+         if (rewound)
+         {
+             String storedIdList = cycle.getRequestContext().getParameter(_name);
+ 
+             reconstructAllocatedIds(storedIdList);
+         }
+ 
          renderBody(writer, cycle);
  
***************
*** 259,277 ****
          {
              // What's this for?  It's part of checking for stale links.  
!             // We record how many elements we allocated ids for.
!             // On rewind, we check that the same number of elements
              // ids were allocated.  If the persistent state of the page or
              // application changed between render (previous request cycle)
!             // and rewind (current request cycle), then
!             // this count might change.
!             //
!             // In some cases, state can change without changing this
!             // number -- hopefully, such changes are benign since we
!             // don't have a way to detect them.
  
              writer.beginEmpty("input");
              writer.attribute("type", "hidden");
              writer.attribute("name", _name);
!             writer.attribute("value", _elementCount);
              writer.println();
  
--- 310,324 ----
          {
              // What's this for?  It's part of checking for stale links.  
!             // We record the list of allocated ids.
!             // On rewind, we check that the stored list against which
              // ids were allocated.  If the persistent state of the page or
              // application changed between render (previous request cycle)
!             // and rewind (current request cycle), then the list
!             // of ids will change as well.
  
              writer.beginEmpty("input");
              writer.attribute("type", "hidden");
              writer.attribute("name", _name);
!             writer.attribute("value", buildAllocatedIdList());
              writer.println();
  
***************
*** 285,292 ****
          if (rewound)
          {
!             String actual = cycle.getRequestContext().getParameter(_name);
  
!             if (actual == null || Integer.parseInt(actual) != _elementCount)
!                 throw new StaleLinkException(Tapestry.getString("Form.bad-element-count", getExtendedId()), getPage());
  
              if (_listener != null)
--- 332,353 ----
          if (rewound)
          {
!             int expected = _allocatedIds.size();
  
!             // The other case, _allocatedIdIndex > expected, is
!             // checked for inside getElementId().  Remember that
!             // _allocatedIdIndex is incremented after allocating.
! 
!             if (_allocatedIdIndex < expected)
!             {
!                 String nextExpectedId = (String) _allocatedIds.get(_allocatedIdIndex);
! 
!                 throw new StaleLinkException(
!                     Tapestry.getString(
!                         "Form.too-few-ids",
!                         getExtendedId(),
!                         Integer.toString(expected - _allocatedIdIndex),
!                         nextExpectedId),
!                     this);
!             }
  
              if (_listener != null)
***************
*** 389,394 ****
                  List l = (List) value;
                  int count = l.size();
!                
!                 
                  for (int j = 0; j < count; j++)
                  {
--- 450,454 ----
                  List l = (List) value;
                  int count = l.size();
! 
                  for (int j = 0; j < count; j++)
                  {
***************
*** 397,401 ****
                      if (j > 0)
                      {
!                         
                          if (combineWithAnd)
                              buffer.append(" &&");
--- 457,461 ----
                      if (j > 0)
                      {
! 
                          if (combineWithAnd)
                              buffer.append(" &&");
***************
*** 413,417 ****
                              buffer.append("  ");
                      }
!     
                      buffer.append(functionName);
                      buffer.append("()");
--- 473,477 ----
                              buffer.append("  ");
                      }
! 
                      buffer.append(functionName);
                      buffer.append("()");
***************
*** 495,499 ****
              // Reserve the name.
  
!             getElementId(name);
  
              if (!reserveOnly)
--- 555,559 ----
              // Reserve the name.
  
!             _elementIdAllocator.allocateId(name);
  
              if (!reserveOnly)
***************
*** 524,532 ****
      {
          _rendering = false;
!         _elementCount = 0;
          _events = null;
!       
!         if (_elementIdAllocator != null)
!             _elementIdAllocator.clear();
  
          super.cleanupAfterRender(cycle);
--- 584,594 ----
      {
          _rendering = false;
! 
!         _allocatedIdIndex = 0;
!         _allocatedIds.clear();
! 
          _events = null;
! 
!         _elementIdAllocator.clear();
  
          super.cleanupAfterRender(cycle);
***************
*** 552,555 ****
--- 614,665 ----
      {
          getPage().addPageDetachListener(this);
+     }
+ 
+     /**
+      *  Converts the allocateIds property into a string, a comma-separated list of ids.
+      *  This is included as a hidden field in the form and is used to identify
+      *  discrepencies when the form is submitted.
+      * 
+      *  @since 2.4
+      * 
+      **/
+ 
+     protected String buildAllocatedIdList()
+     {
+         StringBuffer buffer = new StringBuffer();
+         int count = _allocatedIds.size();
+ 
+         for (int i = 0; i < count; i++)
+         {
+             if (i > 0)
+                 buffer.append(',');
+ 
+             buffer.append(_allocatedIds.get(i));
+         }
+ 
+         return buffer.toString();
+     }
+ 
+     /**
+      *  Converts a string passed as a parameter (and containing a comma
+      *  separated list of ids) back into the allocateIds property.
+      * 
+      *  @see #buildAllocatedIdList()
+      * 
+      *  @since 2.4
+      * 
+      **/
+ 
+     protected void reconstructAllocatedIds(String storedIdList)
+     {
+         if (Tapestry.isNull(storedIdList))
+             return;
+ 
+         StringSplitter splitter = new StringSplitter(',');
+ 
+         String[] ids = splitter.splitToArray(storedIdList);
+ 
+         for (int i = 0; i < ids.length; i++)
+             _allocatedIds.add(ids[i]);
      }
  

Index: ImageSubmit.java
===================================================================
RCS file: /cvsroot/tapestry/Tapestry/framework/src/net/sf/tapestry/form/ImageSubmit.java,v
retrieving revision 1.12
retrieving revision 1.12.2.1
diff -C2 -d -r1.12 -r1.12.2.1
*** ImageSubmit.java	27 Nov 2002 17:58:47 -0000	1.12
--- ImageSubmit.java	21 Dec 2002 13:05:45 -0000	1.12.2.1
***************
*** 77,81 ****
              _name = form.getElementId(this);
          else
!             _name = form.getElementId(_nameOverride);
  
          if (rewinding)
--- 77,81 ----
              _name = form.getElementId(this);
          else
!             _name = form.getElementId(this, _nameOverride);
  
          if (rewinding)



-------------------------------------------------------
This SF.NET email is sponsored by: Order your Holiday Geek Presents Now!
Green Lasers, Hip Geek T-Shirts, Remote Control Tanks, Caffeinated Soap,
MP3 Players,  XBox Games,  Flying Saucers,  WebCams,  Smart Putty.
T H I N K G E E K . C O M       http://www.thinkgeek.com/sf/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.