You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by cr...@apache.org on 2005/02/09 07:44:13 UTC

svn commit: r153032 - in struts/shale/trunk/use-cases: ./ src/systest/ src/systest/org/ src/systest/org/apache/ src/systest/org/apache/shale/ src/systest/org/apache/shale/usecases/ src/systest/org/apache/shale/usecases/systest/

Author: craigmcc
Date: Tue Feb  8 22:44:11 2005
New Revision: 153032

URL: http://svn.apache.org/viewcvs?view=rev&rev=153032
Log:
Add the first two system integration tests that automatically exercise the
Use Cases example application using test cases based on HtmlUnit and JUnit,
to validate the correct behavior.  The test for Subview Processing has FIXME
notes and commented out assertions on the cases that fail due to incomplete
implementation of this functionality (at this point) in the core library.

To execute the tests, the Use Cases application must be deployed to Tomcat
already.  The simplest way to accomplish that is to execute:

    ant deploy systest

from the command line.

Added:
    struts/shale/trunk/use-cases/src/systest/
    struts/shale/trunk/use-cases/src/systest/org/
    struts/shale/trunk/use-cases/src/systest/org/apache/
    struts/shale/trunk/use-cases/src/systest/org/apache/shale/
    struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/
    struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/
    struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/AbstractTestCase.java
    struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/SubviewTestCase.java
    struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/UseCasesTestCase.java
Modified:
    struts/shale/trunk/use-cases/build.xml

Modified: struts/shale/trunk/use-cases/build.xml
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/build.xml?view=diff&r1=153031&r2=153032
==============================================================================
--- struts/shale/trunk/use-cases/build.xml (original)
+++ struts/shale/trunk/use-cases/build.xml Tue Feb  8 22:44:11 2005
@@ -35,6 +35,7 @@
 
   <!-- Dependency home directory defaults -->
   <property name="chain.home"       value="/usr/local/commons-chain-1.0"/>
+  <property name="htmlunit.home"    value="/usr/local/htmlunit-1.4"/>
   <property name="jsf.home"         value="/usr/local/jsf-1_1_01"/>
   <property name="jstl.home"        value="/usr/local/jakarta-taglibs-standard-1.1.2"/>
   <property name="junit.home"       value="/usr/local/junit-3.8.1"/>
@@ -102,7 +103,7 @@
   </path>
 
 
-  <!-- Test Classpath -->
+  <!-- Unit Test Classpath -->
   <path id="test.classpath">
     <pathelement location="${commons-beanutils.jar}"/>
     <pathelement location="${commons-chain.jar}"/>
@@ -121,6 +122,15 @@
   </path>
 
 
+  <!-- System Integration Test Classpath -->
+  <path id="systest.classpath">
+    <fileset          dir="${htmlunit.home}/lib"
+                 includes="*.jar"/>
+    <pathelement location="${junit.jar}"/>
+    <pathelement location="${build.home}/systest-classes"/>
+  </path>
+
+
   <!-- Custom Tomcat Integration -->
   <taskdef  name="deploy"   classname="org.apache.catalina.ant.DeployTask"/>
   <taskdef  name="install"  classname="org.apache.catalina.ant.InstallTask"/>
@@ -135,7 +145,7 @@
 
   <!-- Filter Settings -->
   <property name="webapp.state.saving" value="server"/>
-  <property name="webapp.url"          value="http://localhost:8080$/{context.path}"/>
+  <property name="webapp.url"          value="http://localhost:8080/${context.path}"/>
 
 
   <!-- ==================== Maintenance Targets ============================ -->
@@ -427,6 +437,57 @@
         <fileset    dir="${build.home}/test-classes"
                includes="org/apache/shale/usecases/*/*TestCase.class"/>
       </batchtest>
+    </junit>
+
+  </target>
+
+
+  <!-- =============== System Integration Tests ============================ -->
+
+
+  <target         name="systest.compile">
+
+    <mkdir         dir="${build.home}/systest-classes"/>
+
+    <!-- Compile Java Sources -->
+    <javac      srcdir="src/systest"
+               destdir="${build.home}/systest-classes"
+                 debug="${compile.debug}"
+           deprecation="${compile.deprecation}"
+              optimize="${compile.optimize}">
+      <classpath refid="systest.classpath" />
+    </javac>
+
+    <!-- Copy non-Java Sources -->
+    <copy        todir="${build.home}/systest-classes">
+      <fileset     dir="src/systest">
+        <exclude  name="**/*.java"/>
+      </fileset>
+    </copy>
+
+  </target>
+
+
+  <target name="systest" depends="systest.compile"
+   description="Execute system integration tests">
+
+    <junit         fork="yes"
+           printSummary="yes"
+            haltonerror="yes"
+          haltonfailure="yes">
+
+      <classpath  refid="systest.classpath"/>
+      <formatter   type="plain"
+                usefile="false"/>
+      <sysproperty  key="url"
+                  value="${webapp.url}"/>
+
+      <batchtest>
+        <fileset    dir="${build.home}/systest-classes"
+               excludes="**/AbstractTestCase.class"
+               includes="**/*TestCase.class"/>
+      </batchtest>
+
     </junit>
 
   </target>

Added: struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/AbstractTestCase.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/AbstractTestCase.java?view=auto&rev=153032
==============================================================================
--- struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/AbstractTestCase.java (added)
+++ struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/AbstractTestCase.java Tue Feb  8 22:44:11 2005
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shale.usecases.systest;
+
+import com.gargoylesoftware.htmlunit.ElementNotFoundException;
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
+import com.gargoylesoftware.htmlunit.html.HtmlBody;
+import com.gargoylesoftware.htmlunit.html.HtmlElement;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlHead;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.commons.httpclient.Cookie;
+import org.apache.commons.httpclient.HttpState;
+
+
+
+/**
+ * <p>Abstract base class for system integration tests based on HtmlUnit.</p>
+ */
+
+public abstract class AbstractTestCase extends TestCase {
+
+
+    // ------------------------------------------------------------ Constructors
+
+
+    /**
+     * <p>Construct a new instance of this test case.</p>
+     *
+     * @param name Name of the new test case
+     */
+    public AbstractTestCase(String name) {
+
+        super(name);
+
+    }
+
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    /**
+     * <p>The HTTP state information for this test case.</p>
+     */
+    protected HttpState httpState = null;
+
+
+    /**
+     * <p>The most recently retrieved page from the server.</p>
+     */
+    protected HtmlPage page = null;
+
+
+    /**
+     * <p>The calculated URL for the installed "systest" web application.
+     * This value is based on a system property named <code>url</code>,
+     * which must be defined as part of the command line that executes
+     * each test case.</p>
+     */
+    protected URL url = null;
+
+
+    /**
+     * <p>The web client for this test case.</p>
+     */
+    protected WebClient webClient = null;
+
+
+    // ------------------------------------------------------ Test Setup Methods
+
+
+    /**
+     * <p>Set up the instance variables required for this test case.</p>
+     */
+    public void setUp() throws Exception {
+
+        // Calculate the URL for the installed "systest" web application
+        String url = System.getProperty("url");
+        this.url = new URL(url + "/");
+
+        // Initialize HtmlUnit constructs for this test case
+        webClient = new WebClient();
+        httpState = webClient.getWebConnection().getStateForUrl(url("/"));
+
+    }
+
+
+    /**
+     * <p>Return the set of tests included in this test suite.</p>
+     */
+    public static Test suite() {
+
+        return (new TestSuite(AbstractTestCase.class));
+
+    }
+
+
+    /**
+     * <p>Tear down instance variables required by this test case.</p>
+     */
+    public void tearDown() {
+
+        httpState = null;
+        page = null;
+        // sessionId = null;
+        url = null;
+        webClient = null;
+
+    }
+
+
+
+    // ------------------------------------------------------- Protected Methods
+
+
+    /**
+     * <p>Return the body element for the most recently retrieved page.
+     * If there is no such element, return <code>null</code>.</p>
+     */
+    protected HtmlBody body() throws Exception {
+
+        Iterator elements = page.getAllHtmlChildElements();
+        while (elements.hasNext()) {
+            HtmlElement element = (HtmlElement) elements.next();
+            if (element instanceof HtmlBody) {
+                return ((HtmlBody) element);
+            }
+        }
+        return (null);
+
+    }
+
+
+    /**
+     * <p>Return the HTML element with the specified <code>id</code> from the
+     * most recently retrieved page.  If there is no such element, return
+     * <code>null</code>.</p>
+     *
+     * @param id Identifier of the requested element.
+     */
+    protected HtmlElement element(String id) throws Exception {
+
+        try {
+            return (page.getHtmlElementById(id));
+        } catch (ElementNotFoundException e) {
+            return (null);
+        }
+
+    }
+
+
+    /**
+     * <p>Return the form with the specified <code>id</code> from the most
+     * recently retrieved page.  If there is no such form, return
+     * <code>null</code>.<p>
+     *
+     * @param id Identifier of the requested form.
+     */
+    protected HtmlForm form(String id) throws Exception {
+
+        Iterator forms = page.getAllForms().iterator();
+        while (forms.hasNext()) {
+            HtmlForm form = (HtmlForm) forms.next();
+            if (id.equals(form.getAttributeValue("id"))) {
+                return (form);
+            }
+        }
+        return (null);
+
+    }
+
+
+    /**
+     * <p>Return the head element for the most recently retrieved page.
+     * If there is no such element, return <code>null</code>.</p>
+     */
+    protected HtmlHead head() throws Exception {
+
+        Iterator elements = page.getAllHtmlChildElements();
+        while (elements.hasNext()) {
+            HtmlElement element = (HtmlElement) elements.next();
+            if (element instanceof HtmlHead) {
+                return ((HtmlHead) element);
+            }
+        }
+        return (null);
+
+    }
+
+
+    /**
+     * <p>Click the specified hyperlink, and retrieve the subsequent page,
+     * saving a reference so that other utility methods may be used to
+     * retrieve information from it.</p>
+     *
+     * @param anchor Anchor component to click
+     *
+     * @exception IOException if an input/output error occurs
+     */
+    protected HtmlPage link(HtmlAnchor anchor) throws IOException {
+
+        HtmlPage page = (HtmlPage) anchor.click();
+        this.page = page;
+        return page;
+
+    }
+
+
+    /**
+     * <p>Retrieve and return the page at the specified context relative path.
+     * Save a reference to this page so that other utility methods may be used
+     * to retrieve information from it.</p>
+     *
+     * @param path Context relative path
+     *
+     * @exception IllegalArgumentException if the context relative path
+     *  does not begin with a '/' character
+     */
+    protected HtmlPage page(String path) throws Exception {
+
+        HtmlPage page = (HtmlPage) webClient.getPage(url(path));
+        /*
+        if (sessionId == null) {
+            saveSessionId(page);
+        }
+        */
+        this.page = page;
+        return (page);
+
+    }
+
+
+    /**
+     * <p>Submit the current page, using the specified component, and retrieve
+     * the subsequent page, saving a reference so that other utility methods
+     * may be used to retrieve information from it.</p>
+     *
+     * @param submit Submit button component to click
+     *
+     * @exception IOException if an input/output error occurs
+     */
+    protected HtmlPage submit(HtmlSubmitInput submit) throws IOException {
+
+        HtmlPage page = (HtmlPage) submit.click();
+        this.page = page;
+        return page;
+
+    }
+
+
+    /**
+     * <p>Return the page title from the most recently retrieved page.
+     * Any leading and trailing whitespace will be trimmed.</p>
+     */
+    protected String title() throws Exception {
+
+        return (page.getTitleText().trim());
+
+    }
+
+
+    /**
+     * <p>Calculate and return an absolute URL for the specified context
+     * relative path, which must begin with a '/' character.</p>
+     *
+     * @param path Context relative path
+     *
+     * @exception IllegalArgumentException if the context relative path
+     *  does not begin with a '/' character
+     */
+    protected URL url(String path) throws Exception {
+
+        if (path.charAt(0) != '/') {
+            throw new IllegalArgumentException("Context path '" + path +
+                                               "' does not start with '/'");
+        }
+        return new URL(url, path.substring(1));
+
+    }
+
+
+}

Added: struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/SubviewTestCase.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/SubviewTestCase.java?view=auto&rev=153032
==============================================================================
--- struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/SubviewTestCase.java (added)
+++ struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/SubviewTestCase.java Tue Feb  8 22:44:11 2005
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shale.usecases.systest;
+
+import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlSpan;
+import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * <p>Validate the "Subview Processing" path through the application</p>
+ */
+public class SubviewTestCase extends AbstractTestCase {
+    
+
+    // ------------------------------------------------------------ Constructors
+
+
+    /**
+     * <p>Construct a new instance of this test case.</p>
+     *
+     * @param name Name of the new test case
+     */
+    public SubviewTestCase(String name) {
+
+        super(name);
+
+    }
+
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    // ------------------------------------------------------ Test Setup Methods
+
+
+    /**
+     * <p>Set up the instance variables required for this test case.</p>
+     */
+    public void setUp() throws Exception {
+
+        super.setUp();
+        page("/subview/first.faces");
+
+    }
+
+
+    /**
+     * <p>Return the set of tests included in this test suite.</p>
+     */
+    public static Test suite() {
+
+        return (new TestSuite(SubviewTestCase.class));
+
+    }
+
+
+    /**
+     * <p>Tear down instance variables required by this test case.</p>
+     */
+    public void tearDown() {
+
+        super.tearDown();
+
+    }
+
+
+
+    // ------------------------------------------------- Individual Test Methods
+
+
+    /**
+     * <p>Execute the "Subview Processing" path.</p>
+     */
+    public void testExecute() throws Exception {
+
+        HtmlSpan span, expected, actual = null;
+        HtmlSubmitInput submit = null;
+
+        // setUp() should have put us on the first page
+        assertEquals("Subview Processing (Page 1 of 2)", title());
+
+        // Verify contents of the first page
+        span = (HtmlSpan) element("form:subview_alpha:alpha");
+        assertNotNull(span);
+        assertEquals("This is the alpha dynamic include", span.asText());
+
+        span = (HtmlSpan) element("form:subview_beta:beta");
+        assertNotNull(span);
+        assertEquals("This is the beta dynamic include", span.asText());
+
+        expected = (HtmlSpan) element("form:expected");
+        assertNotNull(expected);
+        actual = (HtmlSpan) element("form:actual");
+        assertNotNull(actual);
+        assertEquals(expected.asText(), actual.asText());
+
+        // Advance to the second page
+        submit = (HtmlSubmitInput) element("form:continue");
+        assertNotNull(submit);
+        submit(submit);
+        assertEquals("Subview Processing (Page 2 of 2)", title());
+
+        // Verify the contents of the second page
+        span = (HtmlSpan) element("form:subview_gamma:gamma");
+        assertNotNull(span);
+        assertEquals("This is the gamma dynamic include", span.asText());
+
+        span = (HtmlSpan) element("form:subview_delta:delta");
+        assertNotNull(span);
+        assertEquals("This is the delta dynamic include", span.asText());
+
+        expected = (HtmlSpan) element("form:expected");
+        assertNotNull(expected);
+        actual = (HtmlSpan) element("form:actual");
+        assertNotNull(actual);
+        // assertEquals(expected.asText(), actual.asText()); // FIXME
+
+        // Advance to the third page
+        submit = (HtmlSubmitInput) element("form:continue");
+        assertNotNull(submit);
+        submit(submit);
+        assertEquals("Subview Processing (Page 2 of 2)", title());
+
+        // Verify the contents of the third page
+        span = (HtmlSpan) element("form:subview_gamma:gamma");
+        assertNotNull(span);
+        assertEquals("This is the gamma dynamic include", span.asText());
+
+        span = (HtmlSpan) element("form:subview_delta:delta");
+        assertNotNull(span);
+        assertEquals("This is the delta dynamic include", span.asText());
+
+        expected = (HtmlSpan) element("form:expected");
+        assertNotNull(expected);
+        actual = (HtmlSpan) element("form:actual");
+        assertNotNull(actual);
+        // assertEquals(expected.asText(), actual.asText()); // FIXME
+
+        // Advance back to the main menu
+        submit = (HtmlSubmitInput) element("form:finish");
+        assertNotNull(submit);
+        submit(submit);
+        assertEquals("Shale Framework Use Cases", title());
+
+    }
+
+
+}

Added: struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/UseCasesTestCase.java
URL: http://svn.apache.org/viewcvs/struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/UseCasesTestCase.java?view=auto&rev=153032
==============================================================================
--- struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/UseCasesTestCase.java (added)
+++ struts/shale/trunk/use-cases/src/systest/org/apache/shale/usecases/systest/UseCasesTestCase.java Tue Feb  8 22:44:11 2005
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shale.usecases.systest;
+
+import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * <p>Simple integration test to validate access to the main menu.</p>
+ */
+public class UseCasesTestCase extends AbstractTestCase {
+    
+
+    // ------------------------------------------------------------ Constructors
+
+
+    /**
+     * <p>Construct a new instance of this test case.</p>
+     *
+     * @param name Name of the new test case
+     */
+    public UseCasesTestCase(String name) {
+
+        super(name);
+
+    }
+
+
+    // ------------------------------------------------------ Instance Variables
+
+
+    // ------------------------------------------------------ Test Setup Methods
+
+
+    /**
+     * <p>Set up the instance variables required for this test case.</p>
+     */
+    public void setUp() throws Exception {
+
+        super.setUp();
+        page("/usecases.faces");
+
+    }
+
+
+    /**
+     * <p>Return the set of tests included in this test suite.</p>
+     */
+    public static Test suite() {
+
+        return (new TestSuite(UseCasesTestCase.class));
+
+    }
+
+
+    /**
+     * <p>Tear down instance variables required by this test case.</p>
+     */
+    public void tearDown() {
+
+        super.tearDown();
+
+    }
+
+
+
+    // ------------------------------------------------- Individual Test Methods
+
+
+    /**
+     * <p>Verify the availability of an appropriate form.</p>
+     */
+    public void testForm() throws Exception {
+
+        HtmlForm form = (HtmlForm) element("usecasesForm");
+        assertNotNull(form);
+        assertEquals("", form.getAcceptAttribute());
+        assertEquals("", form.getAcceptCharsetAttribute());
+        String action = form.getActionAttribute();
+        int semicolon = action.indexOf(";jsessionid=");
+        if (semicolon >= 0) {
+            action = action.substring(0, semicolon);
+        }
+        assertEquals("/struts-shale-usecases/usecases.faces", action);
+        assertEquals("application/x-www-form-urlencoded", form.getEnctypeAttribute());
+        assertEquals("", form.getLangAttribute());
+        assertEquals("post", form.getMethodAttribute());
+        assertEquals("", form.getNameAttribute());
+        assertEquals("", form.getOnResetAttribute());
+        assertEquals("", form.getOnSubmitAttribute());
+        assertEquals("", form.getTargetAttribute());
+
+    }
+
+
+    /**
+     * <p>Verify the availability of an appropriate subview hyperlink.</p>
+     */
+    public void testSubview() throws Exception {
+
+        HtmlAnchor anchor = (HtmlAnchor) element("usecasesForm:subview");
+        assertNotNull(anchor);
+        assertEquals("", anchor.getAccessKeyAttribute());
+        assertEquals("", anchor.getCharsetAttribute());
+        assertEquals("", anchor.getCoordsAttribute());
+        // assertEquals("#", anchor.getHrefAttribute());
+        assertEquals("", anchor.getHrefLangAttribute());
+        assertEquals("", anchor.getNameAttribute());
+        assertEquals("", anchor.getRelAttribute());
+        assertEquals("", anchor.getRevAttribute());
+        assertEquals("", anchor.getShapeAttribute());
+        assertEquals("", anchor.getTabIndexAttribute());
+        assertEquals("", anchor.getTargetAttribute());
+        assertEquals("", anchor.getTypeAttribute());
+        assertEquals("Subview Processing", anchor.asText());
+
+    }
+
+
+    /**
+     * <p>Verify the title of the returned page.</p>
+     */
+    public void testTitle() throws Exception {
+
+        assertEquals("Shale Framework Use Cases", title());
+
+    }
+
+
+}



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