struts-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ar...@apache.org
Subject cvs commit: jakarta-struts/src/share/org/apache/struts/taglib/nested package.html NestedTagSupport.java NestedRootTag.java NestedPropertyTag.java NestedPropertySupport.java NestedPropertyHelper.java NestedParentSupport.java NestedNameSupport.java
Date Fri, 18 Jan 2002 07:22:03 GMT
arron       02/01/17 23:22:03

  Added:       src/share/org/apache/struts/taglib/nested package.html
                        NestedTagSupport.java NestedRootTag.java
                        NestedPropertyTag.java NestedPropertySupport.java
                        NestedPropertyHelper.java NestedParentSupport.java
                        NestedNameSupport.java
  Log:
  Initital commit of the nested extension.
  
  Revision  Changes    Path
  1.1                  jakarta-struts/src/share/org/apache/struts/taglib/nested/package.html
  
  Index: package.html
  ===================================================================
  <html>
  <head>
  <title>Package Documentation for org.apache.struts.taglib.bean Package</title>
  </head>
  <body bgcolor="white">
  Nested tags & supporting classes extend the base struts tags to allow them to
  relate to each other in a nested nature. The fundamental logic of the original
  tags don't change, except in that all references to beans and bean properties
  will be managed in a nested context.
  <br><br>
  <a name="doc.Description"></a>
  <div align="center">
  [&nbsp;<a href="#doc.Intro">Introduction</a>&nbsp;]
  [&nbsp;<a href="#doc.FoundationConcepts">Foundation&nbsp;Concepts&nbsp;-&nbsp;model</a>&nbsp;]
  [&nbsp;<a href="#doc.TaggingConcepts">Foundation&nbsp;Concepts&nbsp;-&nbsp;tags</a>&nbsp;]
  [&nbsp;<a href="#doc.TagList">Nested&nbsp;Tag&nbsp;List</a>&nbsp;]
  [&nbsp;<a href="#doc.PropertyProperty">The&nbsp;"property"&nbsp;Property</a>&nbsp;]
  [&nbsp;<a href="#doc.ImplementationDetails">Implementation&nbsp;Details</a>&nbsp;]
  </div>
  
  <hr>
  
  <a name="doc.Intro"></a>
  <h3>Introduction</h3>
    <p>The nesting extension provides the ability to define a nested object model and
    efficiently represent and manage that model through JSP's custom tags.</p>
    
    <p>It's written in a layer that extends the current Struts tags, building on
    their logic and functionality. The layer enables the tags to be aware of the
    tags which surround them so they can correctly provide the nesting property
    reference to the Struts system. Struts already supported properties which use
    "dot notation" in accessing nested objects and properties.</p>
  
    <pre>e.g. myProperty.childProperty.finalProperty</pre>
    
    <p>Because of this the controller servlet excellently manages this nested
    model. These tags are about bringing such ease of management to the JSP view
    of the architecture.</p>
  
  <hr>
  <a name="doc.FoundationConcepts"></a>
  <H3>Foundation Concepts - model.</H3></a>
   
    <p>
    A bean holds a reference to another bean internally, and all access to that 
    bean is handled through the current bean. This act of having one bean's access 
    go through another bean is known as "nesting beans". The first bean is known 
    as the parent bean. The bean which it references, is known as a child bean. 
    The terms "parent" and "child" are commonly used to describe the model's 
    hierarchy.
    </p>
    <p>
    <b>A simple example...</b><br />
    Take an object which represents a monkey. The monkey's job is to pick bunches 
    of bananas. On each bunch picked hangs many bananas. If this case was 
    translated to bean objects, the monkey object would have a reference to the 
    bunch objects he picked, and each bunch object would hold a reference to the 
    bananas hanging in the bunch.
    <p>
    <p>
    <b>To describe this...</b><br />
    The monkey object is the parent to the bunch object, and the bunch object is a 
    child of the monkey object. The bunch object is parent to its child banana 
    objects, and the child banana objects children of the bunch object. The monkey 
    is higher in the hierarchy than the bananas, and the bananas lower in the 
    hierarchy to the bunches.
    </p>
    <p>
    One special term to remember is for the most parent class, which is known as 
    the "root" object which starts the hierarchy.
    </p>
    
  <hr>
  <a name="doc.TaggingConcepts"></a>
  <H3>Foundation Concepts - tags.</H3></a>
    
    <p>
    What the tags provide is an efficient way or representing the above models
    within JSP tag markup. As a result the tags take on similar relationships to
    each other. A tag can be the parent of another, and similarly be a child of a
    parent tag. However the most important part to remember, is that the
    properties of parent tags define the nested property for the child tags'
    properties.
    </p>
    <p>
    One issue which may confuse the new developer, is that even though a tag
    is a parent tag in a markup sense (the opening tag and closing tag are either
    side of another tag) does not immediately mean that the child tag will be
    relative to that tag. Why? Some tags make bad parents. In other words, they're
    not logical steps in defining a hierarchy.
    </p>
    <p>
    For example the relationship between the select tag and the options tag. The
    html:options tag "must" be surrounded by a parent html:select tag.
    </p>
    <pre>eg:
    &lt;html:select name="myBean" property="mySelectProperty" &gt;
      &lt;html:options name="myBean" property="myOptionsProperty" &gt;
    &lt;/html:select&gt;</pre>
    <p>
    In the nested context, this would cause undesired results if the select tag
    was a parent. The bean reference would become...
    <pre>  mySelectProperty.myOptionsProperty</pre>
    ...which when translated, Struts would go to the value of the select property
    and then try to get your options list from that returned value. The extended
    logic tags are the same. You don't want to extend your properties within the
    objects the logic tags are evaluating.
    </p>
    <p>
    To get manage this, the tags in the nested extension are categorised into
    parent tags and non-parent tags. Those which implement
    <code>org.apache.struts.taglib.nested.NestedParentSupport</code> are classed
    as parents, and the nested system knows they define levels in the nested
    hierarchy. Every other tag, does not, and will be skipped if found to be a
    "markup parent" (like our select tag) and not a "nested parent".
    </p>
    <p>
    There are also the special case of starting off the hierarchy with a "root"
    tag. These tags are what the extension requires to provide them with the bean
    by which the structure will be based on.
    </p>
    
  <hr>
  <a name="doc.TagList"></a>
  <H3>Nested Tag List.</H3></a>
    <p>
    Here's a list of tags in the nested extension, grouped by parent/context
    functionality. "root", "nested parent", "markup parent" & "basic".
    </p>
    <p>
    <b>Root Tags</b>
    <table border="1">
      <tr><th>markup name</th><th>brief description</th></tr>
      <tr><td>html:form</td>
          <td>For backwards compatibility, you can use the typical form tag to
              implement your nested hierarchy.</td></tr>
      <tr><td>nested:form</td>
          <td>An extension of the above <code>html:form</code>, this is just to
              provide definition in the nested tag library.</td></tr>
      <tr><td>nested:root</td>
          <td>When you don't want to configure a form, you can use any bean which
              is in "scope" by specifying its name within this tag.</td></tr>
    </table>
    </table>
    </p>
    <br />
    <p>
    <b>Nested Parent Tags</b> (Affect the hierarchy)
    <table border="1">
      <tr><th>markup name</th><th>brief description</th></tr>
      <tr><td>nested:nest</td>
          <td>This tag executes no logic, simply representing a nesting level
              for the rest of the markup to relate to.</td></tr>
      <tr><td>nested:iterate</td>
          <td>Extension of <code>logic:iterate</code> you can use it to iterate
              through a list, and have all child references nest within the beans
              returned from this iterated collection.</td></tr>
    </table>
    </table>
    </p>
    <br />
    <p>
    <b>Markup Parent Tags</b> (marked-up like parent tags, but don't affect the hierarchy)
    <table border="1">
      <tr><th>markup name</th><th>brief description</th></tr>
      <tr><td>nested:select</td>
          <td><code>html:select</code> extension. Provides the logic to render
              a select box in Html.</td></tr>
      <tr><td>nested:empty</td>
          <td> <code>logic:empty</code> extension.</td></tr>
      <tr><td>nested:notEmpty</td>
          <td> <code>logic:notEmpty</code> extension.</td></tr>
      <tr><td>nested:equal</td>
          <td> <code>logic:equal</code> extension.</td></tr>
      <tr><td>nested:notEqual</td>
          <td> <code>logic:notEqual</code> extension.</td></tr>
      <tr><td>nested:greaterEqual</td>
          <td> <code>logic:greaterEqual</code> extension.</td></tr>
      <tr><td>nested:greaterThan</td>
          <td> <code>logic:greaterThan</code> extension.</td></tr>
      <tr><td>nested:lessEqual</td>
          <td> <code>logic:lessEqual</code> extension.</td></tr>
      <tr><td>nested:lessThan</td>
          <td> <code>logic:lessThan</code> extension.</td></tr>
      <tr><td>nested:match</td>
          <td> <code>logic:match</code> extension.</td></tr>
      <tr><td>nested:notMatch</td>
          <td> <code>logic:notMatch</code> extension.</td></tr>
      <tr><td>nested:present</td>
          <td> <code>logic:present</code> extension.</td></tr>
      <tr><td>nested:notPresent</td>
          <td> <code>logic:notPresent</code> extension.</td></tr>
    </table>
    </table>
    </p>
    <br />
    <p>
    <b>Base tags</b> (usually a tag which has no body content)
    <table border="1">
      <tr><th>markup name</th><th>brief description</th></tr>
      <tr><td>nested:checkbox</td>
          <td> <code>html:</code> extension.</td></tr>
      <tr><td>nested:hidden</td>
          <td> <code>html:hidden</code> extension.</td></tr>
      <tr><td>nested:image</td>
          <td> <code>html:image</code> extension.</td></tr>
      <tr><td>nested:link</td>
          <td> <code>html:link</code> extension.</td></tr>
      <tr><td>nested:multibox</td>
          <td> <code>html:multibox</code> extension.</td></tr>
      <tr><td>nested:options</td>
          <td> <code>html:options</code> extension.</td></tr>
      <tr><td>nested:password</td>
          <td> <code>html:password</code> extension.</td></tr>
      <tr><td>nested:radio</td>
          <td> <code>html:radio</code> extension.</td></tr>
      <tr><td>nested:select</td>
          <td> <code>html:select</code> extension.</td></tr>
      <tr><td>nested:submit</td>
          <td> <code>html:submit</code> extension.</td></tr>
      <tr><td>nested:text</td>
          <td> <code>html:text</code> extension.</td></tr>
      <tr><td>nested:textarea</td>
          <td> <code>html:textarea</code> extension.</td></tr>
    </table>
    </p>
  
  <hr>
  <a name="doc.PropertyProperty"></a>
  <H3>The "property" property.</H3></a>
  
  
    <p>Use of the "property" property is exactly the same as the original Struts tag 
    with minor addition. Appends the provided property to the nested property of
    the tags that surround it. You can use additional nesting (use "dot notation")
    within the provided property as the current struts system allows but there is
    now a tag which can provide this in a "cleaner" fashion.  :)</p>
    
    <p>The one other addition to the "property" property, is the ability to step
    backwards in the heirarchy in the familiar directory fashion;
    e.g. "../../myPropertyName"</p>
    
    <p>As expected this allows you to step backwards in the nested model to access
    a higher level in the object tree. The implementation uses the StringTokenizer
    working off the "/" delimiter and counts the tokens. This was going to be
    denied, enforcing the ".." fashion, but on consideration, allowed for some
    easier-to-read naming possibilities.</p>
    
    <p>Consider "propertyOne.propertyTwo.propertyThree.propertyFour". With the 
    current nesting level beneath "propertyFour" you can instead use
    "two/three/four/anotherProperty" which is easier to understand than
    "../../../anotherProperty". Doesn't sound like much, but makes life easier
    when traversing large jsp pages for tags defining your object model.</p>
    
    <p>Also implemented is the also familiar directory fashion of a leading "/" to
    reference from the root of the model and start over. e.g. "/propertyOne".
    This allow a convenient way to move around a few levels as well as "forking"
    in the object structure among other felixble approaches to structure.</p>
    
    <p><b>Note:</b> The logic identifies the leading "/" and then reads the property
    from the last index of "/".  Resulting in "/three/four/anotherProperty" working
    the same as "/anotherProperty".</p>
    
    <p><b>Note:</b> If you're busily nesting away, and a parent tag has a leading "/"
    property, the  contained tags will append to this new structure. Handy, but
    you have to keep it in mind.</p>
    
    <p><b>Note:</b> If you try to reference beneath the level of the nesting, it will
    simply act like as if a leading "/" property was defined.</p>
  
  
  <hr>
  <a name="doc.ImplementationDetails"></a>
  <H3>Implementation Details.</H3></a>
    
  <b>NestedPropertyHelper</b>
  <dir>
    <p>This class embodies all of the logic that runs the nested tagging system. It
    defines a static method, "setNestedProperties", which the nested tags pass
    themselves into to have their appropriate properties set.</p>
    
    <p>The tag extensions themselves implement options of three interfaces which
    define functionality for the various types of nested usage. When traversing
    the tag hierarchy back up to the root of the structure, these tags define the
    result of the current tag.</p>
  </dir>
  
  <b>NestedTagSupport Interface...</b>
  <dir>
    <p>This is the base of the interfaces. Simply put, any tag that we need to single
    out of the standard struts tags for use by the nesting system can implement
    this or its children.</p>
  </dir>
  
  <b>NestedPropertySupport Interface...</b>
  <dir>
    <p>Tags that implement this interface will have the provided property attribute
    appended to the parenting nested attribute. This is the heart of the matter.
    </p>
    
    <p>This is the basic property, and so far all the nested tags support this
    to have their nested properties written correctly.</p>
  </dir>
  
  <b>NestedNameSupport Interface...</b>
  <dir>
    <p>This interface means that the implementing tag wants to have it's name tag
    looked after by the nesting system. This is automatic, and the name is written
    for the tag from the root tag. If the JSP is a form, then it will look to the
    form tag and get a hold of the bean name that is defined in the
    struts-config.xml file for the action, otherwise, a nested:root tag must be
    provided for this means.</p>
  
    <p>This extends the NestedPropertySupport interface as, at time of writing,
    all tags which used a "name" attribute, required a property attribute in some
    way to make it useful. This could change, and it's only a small refactoring to
    make it work for the instance if it's relevant for nesting.</p>
    
    <p><b>Note:</b> At the moment, if the tag implements this interface, the name
    attribute will be rewritten by the system on all counts. I find it hard to
    picture a valid requirement for inter-mixing multiple object structures (which
    distinguishable names would allow) in the one JSP page which couldn't be
    more efficiently provided by the current nesting model working over the one
    model. Time may prove this idea wrong.</p>
  </dir>
  
  <b>ParentTagSupport</b>
  <dir>
    <p>This tag identifies for the system those tags which define levels in the
    nested heirarchy.  Namely the "getNestedProperty()" method that yields to
    calling tags the fully qualified nested property of the parent tag. In the
    case of a NestedIterator being the parent tag, it will also append the current
    index reference. e.g. propertyOne.propertyTwo[5]<p>
  </dir>
  
  
  <br />
  <br />
  </body>
  </html>
  
  
  1.1                  jakarta-struts/src/share/org/apache/struts/taglib/nested/NestedTagSupport.java
  
  Index: NestedTagSupport.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Struts", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.struts.taglib.nested;
  
  /**
   * This is to simply allow managing classes to identify the tags to invoke
   * common methods against them.
   * This interface is empty and is for identification only.
   *
   * @author Arron Bates <arron@keyboardmonkey.com>
   */
  public interface NestedTagSupport {}
  
  
  1.1                  jakarta-struts/src/share/org/apache/struts/taglib/nested/NestedRootTag.java
  
  Index: NestedRootTag.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Struts", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.struts.taglib.nested;
  
  import javax.servlet.jsp.*;
  import javax.servlet.jsp.tagext.*;
  import org.apache.struts.util.*;
  
  /**
   * NestedRootTag.
   *
   * The only other addition in this nested suite of tags.
   * This tag allows for a nested structure to start without relying on the bean
   * and workings of the FormTag. Useful for view pages that don't update when
   * returning to the server, or use hyperlinks rather than form submits.
   *
   * The Bean that it uses can come out of a jsp:useBean tag or define another
   * bean that's already in scope. As long as the other Struts tags can find the
   * bean by name, it'll work.
   *
   * It's simply recognised by the helper class and it's property is added to the
   * nesting list.
   *
   * @author Arron Bates <arron@keyboardmonkey.com>
   */
  public class NestedRootTag extends BodyTagSupport implements NestedParentSupport, NestedNameSupport {
    
    /** Getter method for the <i>property</i> property
     * @return String value of the property property
     */
    public String getProperty() {
      return "";
    }
    /** Setter method for the <i>property</i> property
     * @param property new value for the property property
     */
    public void setProperty(String property) {}
    
    /** Getter method for the <i>name</i> property
     * @return String value of the name property
     */
    public String getName() {
      return this.name;
    }
    /** Setter method for the <i>name</i> property
     * @param property new value for the name property
     */
    public void setName(String name) {
      this.name = name;
    }
    
    
    /** Getter method for the nestedProperty property
     * @return String value of the nestedProperty property
     */
    public String getNestedProperty() {
      return "";
    }
    
    /**
     * Overriding method of the heart of the tag. Gets the relative property
     * and tells the JSP engine to evaluate its body content.
     *
     * @return int JSP continuation directive.
     */
    public int doStartTag() throws JspException {
      return (EVAL_BODY_TAG);
    }
    
    /**
     * Render the resulting content evaluation.
     *
     * @return int JSP continuation directive.
     */
    public int doAfterBody() throws JspException {
      /* Render the output */
      if (bodyContent != null) {
        ResponseUtils.writePrevious(pageContext, bodyContent.getString());
        bodyContent.clearBody();
      }
      
      return (SKIP_BODY);
    }
    
    /**
     * Evaluate the rest of the page
     *
     * @return int JSP continuation directive.
     */
    public int doEndTag() throws JspException {
      return (EVAL_PAGE);
    }
    
    
    /**
     * JSP method to release all resources held by the tag.
     */
    public void release() {
      super.release();
      this.name = null;
    }
    
    private String name = null;
  }
  
  
  1.1                  jakarta-struts/src/share/org/apache/struts/taglib/nested/NestedPropertyTag.java
  
  Index: NestedPropertyTag.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Struts", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.struts.taglib.nested;
  
  import javax.servlet.jsp.*;
  import javax.servlet.jsp.tagext.*;
  import org.apache.struts.util.*;
  
  /**
   * NestedPropertyTag.
   *
   * The one of only two additions in this nested suite of tags. This is so that
   * you can specify extra levels of nesting in one elegant tag rather than having
   * to propagate and manage an extra dot notated property in nested child tags.
   *
   * It's simply recognised by the helper class and it's property is added to the
   * nesting list.
   *
   * @author Arron Bates <arron@keyboardmonkey.com>
   */
  public class NestedPropertyTag extends BodyTagSupport implements NestedParentSupport, NestedNameSupport {
    
    /** Getter method for the <i>property</i> property
     * @return String value of the property property
     */
    public String getProperty() {
      return this.property;
    }
  
    /** Setter method for the <i>property</i> property
     * Also, only setting the original property value to those values not
     * set by the nested logic.
     * @param property new value for the property property
     */
    public void setProperty(String newProperty) {
      property = newProperty;
      if (!isNesting) {
        originalProperty = newProperty;
      }
    }
    
    /** Getter method for the <i>name</i> property
     * @return String value of the name property
     */
    public String getName() {
      return this.name;
    }
    /** Setter method for the <i>name</i> property
     * @param property new value for the name property
     */
    public void setName(String name) {
      this.name = name;
    }
    
    
    /** Getter method for the nestedProperty property
     * @return String value of the nestedProperty property
     */
    public String getNestedProperty() {
      return property;
    }
    
    /**
     * Overriding method of the heart of the tag. Gets the relative property
     * and tells the JSP engine to evaluate its body content.
     *
     * @return int JSP continuation directive.
     */
    public int doStartTag() throws JspException {
      
      /* Set back to the original property */
      property = originalProperty;
      
      /* let the NestedHelper set the properties it can */
      isNesting = true;
      NestedPropertyHelper.setNestedProperties(this);
      isNesting = false;
      return (EVAL_BODY_TAG);
    }
    
    
    /**
     * Render the resulting content evaluation.
     *
     * @return int JSP continuation directive.
     */
    public int doAfterBody() throws JspException {
      /* Render the output */
      if (bodyContent != null) {
        ResponseUtils.writePrevious(pageContext, bodyContent.getString());
        bodyContent.clearBody();
      }
      
      return (SKIP_BODY);
    }
    
    
    /**
     * Evaluate the rest of the page
     *
     * @return int JSP continuation directive.
     */
    public int doEndTag() throws JspException {
      return (EVAL_PAGE);
    }
    
    
    /**
     * JSP method to release all resources held by the tag.
     */
    public void release() {
      super.release();
      this.property = null;
      this.name = null;
    }
    
    /* the usual private member variable */
    private String property = null;
    private String name = null;
      
    /* hold original property */
    private String originalProperty = null;
    private boolean isNesting = false;
  }
  
  
  1.1                  jakarta-struts/src/share/org/apache/struts/taglib/nested/NestedPropertySupport.java
  
  Index: NestedPropertySupport.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Struts", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.struts.taglib.nested;
  
  /**
   * This interface is for managing classes of the nested extension, so they can
   * know to set the tag's <i>property</i> property.
   *
   * @author Arron Bates <arron@keyboardmonkey.com>
   */
  public interface NestedPropertySupport extends NestedTagSupport {
    
    /**
     * The getters and setters required to set a tags <i>property</i> property.
     * @return String value of the tags' property property
     */
    public String getProperty();
    
    /**
     * The setter for the poroperty property
     * @param newProperty new String value to set the property property to
     */
    public void setProperty(String newProperty);
    
  }
  
  
  1.1                  jakarta-struts/src/share/org/apache/struts/taglib/nested/NestedPropertyHelper.java
  
  Index: NestedPropertyHelper.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Struts", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.struts.taglib.nested;
  
  import java.util.StringTokenizer;
  import javax.servlet.jsp.*;
  import javax.servlet.jsp.tagext.*;
  import org.apache.struts.taglib.nested.html.*;
  import org.apache.struts.taglib.nested.logic.*;
  import org.apache.struts.taglib.html.FormTag;
  
  /** A simple helper class that does everything that needs to be done to get the
   * nested tag extension to work. Knowing what tags can define the lineage of
   * other tags, a tag asks of it to look up to the next nested tag and get it's
   * relative nested property.
   *
   * With all tags keeping track of themselves, we only have to seek to the next
   * level, or parent tag, were a tag will append a dot and it's own property.
   *
   * @author Arron Bates <arron@keyboardmonkey.com>
   */ 
  public class NestedPropertyHelper {
    
    
    /** 
     * The working horse method.
     * This method works its way back up though the tag tree until it reaches
     * a nested tag from which we're meant to be nesting against.
     * It identifies nested tags by their implementing interfaces and via this
     * mechanism might not have to traverse the entire way up the tree to get
     * to the root tag.
     *
     * @param tag The tag to start with
     * @return The parent tag to which we're nesting against
     */
    public static Tag getNestingParentTag(NestedTagSupport tag) {
      Tag namedTag = (Tag)tag;
      Tag parentTag = null;
      
      /* loop all parent tags until we get one that can be nested against  */
      do {
        namedTag = namedTag.getParent();
        if (parentTag == null) {
          if (namedTag instanceof NestedParentSupport ||
              namedTag instanceof FormTag) {
            parentTag = namedTag;
          }
        }
      } while (parentTag == null && namedTag != null);
      
      if (namedTag == null) {
        // need to spit some chips
      }
      
      return parentTag;
    }
    
    
    
    /**
     * Providing a property and the nested tag's parent, this method will return
     * the qualified nested name. It also checks for a relative property to make
     * sure it's handled correctly.
     *
     * @param property String of the property to get the nesting version of
     * @param parentTag the nested tag's nesting parent.
     * @return String of the fully qualified nesting property
     */
    public static String getNestedProperty(String property, Tag parentTag) {
      
      /* if we're just under a root tag no work required */
      if ((parentTag instanceof NestedRootTag)
          || (parentTag instanceof FormTag)) {
        /* don't forget to take care of the relative properties */
        if (property.indexOf('/') == -1) {
          return property;
        } else {
          return property.substring(property.indexOf('/')+1, property.length());
        }
      }
      
      if (!(parentTag instanceof NestedParentSupport)) {
        // need to spit chips
      }
      
      NestedParentSupport nestedParent = (NestedParentSupport)parentTag;
      
      /* return dot notated property from the parent */    
      if (property.indexOf('/') == -1) {
        property = nestedParent.getNestedProperty() +"."+ property;
      } else {
        property = getRelativeProperty(property,nestedParent.getNestedProperty());
      }
      
      return property;
    }
    
    
    /** A convenience method to provide the property straight from a tag using
     * its getProperty() method
     *
     * @param tag the whose property property is to be qualified by nesting
     * @return String of the fully qualified nesting property
     */
    public static String getNestedProperty(NestedPropertySupport tag) {
      Tag parentTag = getNestingParentTag(tag);
      return getNestedProperty(tag.getProperty(), parentTag);
    }
    
    
    
    /**
     * This method works its way back up though the tag tree until it reaches
     * a nested tag which we can get a reliable source of the bean name.
     *
     * @param tag The tag to start with
     * @return name of the nesting bean we're using
     */
    public static String getNestedNameProperty(NestedTagSupport tag) {
      
      Tag namedTag = (Tag)tag;
      
      /* loop all parent tags until we get one which
         gives a reliable bean name  */
      do {
        namedTag = namedTag.getParent();
      } while ( namedTag != null &&
                !(namedTag instanceof FormTag) &&
                !(namedTag instanceof NestedParentSupport) );
      
      if (namedTag == null) {
        // need to spit some chips
      }
      
      String nameTemp = null;
      if (namedTag instanceof FormTag) {
        nameTemp = ((FormTag)namedTag).getName();
      } else if (namedTag instanceof NestedParentSupport) {
        nameTemp = ((NestedParentSupport)namedTag).getName();
      }
      return nameTemp;
    }
    
    
    /**
     * A convenience method by which a tag can just pass itself in and have all of
     * its relevant properties set for it.
     *
     * @param tag The nested tag whose properties are to be set
     */
    public static void setNestedProperties(NestedPropertySupport tag) {
      
      /* get and set the relative property */
      String property = getNestedProperty(tag);
      ((NestedPropertySupport)tag).setProperty(property);
     
      /* if the tag implements NestedNameSupport, set the name for the tag also */
      if (tag instanceof NestedNameSupport) {
        String name = getNestedNameProperty(tag);
        ((NestedNameSupport)tag).setName(name);
      }
    }
    
    
      
    /* This property, providing the property to be appended, and the parent tag
     * to append the property to, will calculate the stepping of the property
     * and return the qualified nested property 
     *
     * @param property the property which is to be appended nesting style
     * @param parent the "dot notated" string representing the structure
     * @return qualified nested property that the property param is to the parent
     */
    private static String getRelativeProperty(String property, String parent) {
      /* remove the stepping from the property */
      String stepping = property.substring(0,property.lastIndexOf('/')+1);
      /* isolate the property */
      property = property.substring(property.lastIndexOf('/')+1,property.length());
      
      if (stepping.startsWith("/")) {
        /* return from root */
        return property;
      } else {
        /* tokenize the nested property */
        StringTokenizer proT = new StringTokenizer(parent, ".");
        int propCount = proT.countTokens();
  
        /* tokenize the stepping */
        StringTokenizer strT = new StringTokenizer(stepping, "/");
        int count = strT.countTokens();
        
        if (count >= propCount) {
          /* return from root */
          return property;
          
        } else {
          /* append the tokens up to the token difference */
          count = propCount - count;
          StringBuffer result = new StringBuffer();
          for (int i = 0; i < count; i++) {
            result.append(proT.nextToken());
            result.append('.');
          }
          result.append(property);
          
          /* return stepped property */
          return result.toString();
        }
      }
    }
  }
  
  
  
  1.1                  jakarta-struts/src/share/org/apache/struts/taglib/nested/NestedParentSupport.java
  
  Index: NestedParentSupport.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Struts", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.struts.taglib.nested;
  
  /**
   * This interface is so managing classes of the nested tag can identify a tag
   * as a parent tag that other tags retrieve nested properties from.
   * 
   * @see org.apache.struts.taglib.nested.NestedPropertyTag
   * @see org.apache.struts.taglib.nested.logic.NestedIterateTag
   *
   * @author Arron Bates <arron@keyboardmonkey.com>
   */
  public interface NestedParentSupport extends NestedNameSupport {
    
    /**
     * This is required by all parent tags so that the child tags can get a hold
     * of their nested property.
     *
     * @return String of the qaulified nested property to this implementing tag
     */
    public String getNestedProperty();
    
  }
  
  
  
  
  1.1                  jakarta-struts/src/share/org/apache/struts/taglib/nested/NestedNameSupport.java
  
  Index: NestedNameSupport.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Struts", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  
  package org.apache.struts.taglib.nested;
  
  /**
   * This is so that managing classes can tell if a nested tag needs to have its
   * <i>name</i> property set. From what I know, these tags use the property 
   * property, and the name is an addition.
   *
   * @author  Arron Bates <arron@keyboardmonkey.com>
   */
  public interface NestedNameSupport extends NestedPropertySupport {
    
    /**
     * The getters and setters required to set a tags <i>name</i> property.
     * @return String value of the tags' name property
     */
    public String getName();
    
    /**
     * The setter for the <i>name</i> property
     * @param newProperty new String value to set the name property to
     */
    public void setName(String newNamed);
    
  }
  
  

--
To unsubscribe, e-mail:   <mailto:struts-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:struts-dev-help@jakarta.apache.org>


Mime
View raw message