commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From je...@apache.org
Subject cvs commit: jakarta-commons/latka/src/java/org/apache/commons/latka/validators XPathHandler.java XPathValidator.java
Date Mon, 07 Jan 2002 11:26:24 GMT
jefft       02/01/07 03:26:24

  Modified:    latka    STATUS.html build.properties.sample build.xml
               latka/conf suite.ent tests.ent
               latka/doc latka.html
               latka/resource latka.properties.internal
  Added:       latka/src/java/org/apache/commons/latka/validators
                        XPathHandler.java XPathValidator.java
  Log:
  Implement an XPath validator. Nice for testing web services or anything that
  returns XML/XHTML.
  
  build.xml:
  - Added the jaxen and saxpath jars to the classpath and build.properties.sample
  - Added lib/ to the classpath, so log4j can find it's properties file during
  the automated tests.
  docs:
  - Added documentation for the xpath validator. HTML.. ugh
  - Updated STATUS.html to reflect current goings-on, including a highly
    subjective "TODO" list.
  
  Revision  Changes    Path
  1.4       +20 -0     jakarta-commons/latka/STATUS.html
  
  Index: STATUS.html
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/latka/STATUS.html,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- STATUS.html	13 Sep 2001 22:43:24 -0000	1.3
  +++ STATUS.html	7 Jan 2002 11:26:24 -0000	1.4
  @@ -14,6 +14,7 @@
   <a href="#Committers">[Committers]</a>
   <a href="#Development Status">[Development Status]</a>
   <br><br>
  +<i>Last updated: $Date: 2002/01/07 11:26:24 $</i>
   </div>
   
   <h3><a name="Introduction">INTRODUCTION</a></h3>
  @@ -88,6 +89,7 @@
   <li>Morgan Delagrange</li>
   <li>Doug Sale</li>
   <li>Rodney Waldhoff</li>
  +<li>Jeff Turner (part-time)</li>
   </ul>
   
   <a name="Development Status"></a>
  @@ -103,6 +105,24 @@
     <li>Latka web application (in Commons Sandbox):<br> Experimental, 
         promising but unstable.</li>
   </ul>
  +
  +<p>Todo items:</p>
  +
  +<ul>
  +  <li>Fix the documentation system :) It's currently horrible; a single HTML file,
  +   created by some GUI editor. I would very much recommend the XML DTD +
  +   stylesheet in the Anteater project (see <a
  +       href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/aft/Anteater/doc/">http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/aft/Anteater/doc/</a>),
  +   whose styled output may be (temporarily) viewed <a
  +       href="http://opensource.socialchange.net.au/latka/Anteater.html">here</a>.</li>
  +   <li>Add a universal mechanism for negating validators. Currently regexp and
  +   xpath validators implement negation internally as a special
  +   <code>cond</code> attribute. This adds somewhat to the internal complexity.
  +   It would be better to have the framework handle negation by being able to
  +   wrap tests in a &lt;not/&gt; element.</li>
  +   <li>Make the inclusion of individual validators optional at build time.</li>
  +   <li>Write unit tests for each validator, with a mock object implementing the Response interface</li>
  + </ul>
   
   </body>
   </html>
  
  
  
  1.15      +6 -0      jakarta-commons/latka/build.properties.sample
  
  Index: build.properties.sample
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/latka/build.properties.sample,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- build.properties.sample	17 Oct 2001 15:35:45 -0000	1.14
  +++ build.properties.sample	7 Jan 2002 11:26:24 -0000	1.15
  @@ -14,6 +14,12 @@
   jcert.jar=/java/lib/jcert.jar
   junit.jar=/java/lib/junit.jar
   
  +# For the XPath validator. Jaxen is an XPath library, obtainable from
  +# http://www.jaxen.org/
  +jaxen.home=${user.home}/jaxen
  +jaxen.jar=${jaxen.home}/build/jaxen-full.jar          
  +saxpath.jar=${jaxen.home}/saxpath.jar
  +
   # for application distribution
   xalan.jar=/java/lib/xalan2.jar
   crimson.jar=/java/lib/crimson.jar
  
  
  
  1.13      +6 -4      jakarta-commons/latka/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/latka/build.xml,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- build.xml	5 Jan 2002 05:34:50 -0000	1.12
  +++ build.xml	7 Jan 2002 11:26:24 -0000	1.13
  @@ -1,5 +1,5 @@
  -<!-- $Id: build.xml,v 1.12 2002/01/05 05:34:50 jefft Exp $ -->
  -<project name="commons-latka" default="test" basedir=".">
  +<!-- $Id: build.xml,v 1.13 2002/01/07 11:26:24 jefft Exp $ -->
  +<project name="commons-latka" default="build-java" basedir=".">
   
      <!-- patternset describing files to be copied from the doc directory -->
      <patternset id="patternset-doc"/>
  @@ -40,8 +40,6 @@
         <!-- command line classpath, if any -->
         <property name="cp" value=""/>
   
  -      <!-- now combine the classpaths -->
  -      <property name="classpath" value="${cp}:${regexp.jar}:${junit.jar}:${jaxp.jar}:${jdom.jar}:${log4j.jar}:${httpclient.jar}:${sax2.jar}:${jnet.jar}:${jsse.jar}:${jcert.jar}:${junit.jar}"/>
   
         <property name="name" value="commons-latka"/>
         <property name="Name" value="Commons-Latka"/>
  @@ -53,6 +51,7 @@
         
         <property name="workdir" value="${java.io.tmpdir}/buildtemp_${DSTAMP}${TSTAMP}"/>
         <property name="source" value="${basedir}"/>
  +      <property name="source.props" value="${source}/lib"/> <!-- properties files -->
         <property name="source.src" value="${basedir}/src"/>
         <property name="source.src.java" value="${source.src}/java"/>
         <property name="source.src.test" value="${source.src}/test"/>
  @@ -68,6 +67,9 @@
         <available property="available-doc" file="${source.doc}"/> <!-- does this module have docs? -->
         <available property="available-src-java" file="${source.src.java}"/> <!-- does this module have java src? -->      
         <available property="available-src-test" file="${source.src.test}"/> <!-- does this module have test src? -->      
  +
  +      <!-- now combine the classpaths -->
  +      <property name="classpath" value="${cp}:${regexp.jar}:${jaxp.jar}:${jdom.jar}:${jaxen.jar}:${saxpath.jar}:${log4j.jar}:${httpclient.jar}:${sax2.jar}:${jnet.jar}:${jsse.jar}:${jcert.jar}:${junit.jar}:${source.props}"/>
   
      </target>
   
  
  
  
  1.2       +6 -0      jakarta-commons/latka/conf/suite.ent
  
  Index: suite.ent
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/latka/conf/suite.ent,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- suite.ent	12 Sep 2001 22:44:02 -0000	1.1
  +++ suite.ent	7 Jan 2002 11:26:24 -0000	1.2
  @@ -52,6 +52,12 @@
                    ignoreCase (true | false) "false"
                    label      CDATA          #IMPLIED>
   
  +<!ELEMENT xpath EMPTY>
  +<!ATTLIST xpath select    CDATA          #REQUIRED
  +                cond       (true | false) "true"
  +                value     CDATA          #IMPLIED  
  +                label     CDATA          #IMPLIED>
  +
   <!ELEMENT goldenFile EMPTY>
   <!ATTLIST goldenFile fileName         CDATA          #REQUIRED
                         ignoreWhitespace (true | false) "false"
  
  
  
  1.7       +1 -1      jakarta-commons/latka/conf/tests.ent
  
  Index: tests.ent
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/latka/conf/tests.ent,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- tests.ent	21 Aug 2001 17:08:19 -0000	1.6
  +++ tests.ent	7 Jan 2002 11:26:24 -0000	1.7
  @@ -3,7 +3,7 @@
   
   <!-- add new tests to this array (add top-level element only) -->
   <!ENTITY % tests "statusCode | regexp | byteLength |
  -                  maxRequestTime | cookie | goldenFile | responseHeader">
  +                  maxRequestTime | cookie | goldenFile | responseHeader | xpath">
   
   <!-- 
   
  
  
  
  1.9       +104 -14   jakarta-commons/latka/doc/latka.html
  
  Index: latka.html
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/latka/doc/latka.html,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- latka.html	9 Oct 2001 17:47:36 -0000	1.8
  +++ latka.html	7 Jan 2002 11:26:24 -0000	1.9
  @@ -154,7 +154,31 @@
           <a name="N2655"></a>XML Reference
         </h2>
             
  -      <div class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#latka.ref.byteLength">byteLength</a></dt><dt><a href="#latka.ref.cookie">cookie</a></dt><dt><a href="#latka.ref.credentials">credentials</a></dt><dt><a href="#latka.ref.maxRequestTime">maxRequestTime</a></dt><dt><a href="#latka.ref.param">param</a></dt><dt><a href="#latka.ref.paramName">paramName</a></dt><dt><a href="#latka.ref.paramValue">paramValue</a></dt><dt><a href="#latka.ref.regexp">regexp</a></dt><dt><a href="#latka.ref.request">request</a></dt><dt><a href="#latka.ref.session">session</a></dt><dt><a href="#latka.ref.statusCode">statusCode</a></dt><dt><a href="#latka.ref.suite">suite</a></dt><dt><a href="#latka.ref.validate">validate</a></dt></dl></div><div class="refentry"><h1 class="title"><a name="latka.ref.byteLength"></a>byteLength</h1><div class="refnamediv"><a name="N2665"></a><h2>Name</h2>byteLength &mdash; validates the length of an HTTP(S) response</div><div class="refsynopsisdiv"><a name="N2670"></a><h2>Synopsis</h2><div class="refsect2"><a name="N2671"></a><h3><a name="N2671"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT byteLength EMPTY&gt;
  +      <div class="toc">
  +          <p>
  +          <b>Table of Contents</b>
  +          </p>
  +          <dl>
  +              <dt><a href="#latka.ref.byteLength">byteLength</a></dt>
  +              <dt><a href="#latka.ref.cookie">cookie</a></dt>
  +              <dt><a href="#latka.ref.credentials">credentials</a></dt>
  +              <dt><a href="#latka.ref.maxRequestTime">maxRequestTime</a></dt>
  +              <dt><a href="#latka.ref.param">param</a></dt>
  +              <dt><a href="#latka.ref.paramName">paramName</a></dt>
  +              <dt><a href="#latka.ref.paramValue">paramValue</a></dt>
  +              <dt><a href="#latka.ref.regexp">regexp</a></dt>
  +              <dt><a href="#latka.ref.request">request</a></dt>
  +              <dt><a href="#latka.ref.session">session</a></dt>
  +              <dt><a href="#latka.ref.statusCode">statusCode</a></dt>
  +              <dt><a href="#latka.ref.suite">suite</a></dt>
  +              <dt><a href="#latka.ref.validate">validate</a></dt>
  +              <dt><a href="#latka.ref.xpath">xpath</a></dt>
  +          </dl>
  +      </div>
  +
  +      <div class="refentry">
  +          <h1 class="title"><a name="latka.ref.byteLength"></a>byteLength</h1>
  +          <div class="refnamediv"><a name="N2665"></a><h2>Name</h2>byteLength &mdash; validates the length of an HTTP(S) response</div><div class="refsynopsisdiv"><a name="N2670"></a><h2>Synopsis</h2><div class="refsect2"><a name="N2671"></a><h3><a name="N2671"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT byteLength EMPTY&gt;
   &lt;!ATTLIST byteLength min   CDATA "0"
                         max   CDATA #IMPLIED
                         label CDATA #IMPLIED&gt;</pre></div><div class="refsect2"><a name="N2677"></a><h3><a name="N2677"></a>Attributes</h3><div class="informaltable" id="N2680"><a name="N2680"></a><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Name</th><th>Type</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><tt>min</tt></td><td>NUMBER</td><td><tt>0</tt></td><td>
  @@ -176,7 +200,9 @@
                  <tt>min</tt>
                  bytes long, and (when specified) at most
                  <tt>max</tt> bytes long.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.cookie"></a>cookie</h1><div class="refnamediv"><a name="N2767"></a><h2>Name</h2>cookie &mdash; validates the presence of an HTTP(S) cookie in the current session</div><div class="refsynopsisdiv"><a name="N2772"></a><h2>Synopsis</h2><div class="refsect2"><a name="N2773"></a><h3><a name="N2773"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT cookie EMPTY&gt;
  +               </p></div></div>
  +               
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.cookie"></a>cookie</h1><div class="refnamediv"><a name="N2767"></a><h2>Name</h2>cookie &mdash; validates the presence of an HTTP(S) cookie in the current session</div><div class="refsynopsisdiv"><a name="N2772"></a><h2>Synopsis</h2><div class="refsect2"><a name="N2773"></a><h3><a name="N2773"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT cookie EMPTY&gt;
   &lt;!ATTLIST cookie name  CDATA #REQUIRED
                    value CDATA #IMPLIED
                    label CDATA #IMPLIED&gt;</pre></div><div class="refsect2"><a name="N2779"></a><h3><a name="N2779"></a>Attributes</h3><div class="informaltable" id="N2782"><a name="N2782"></a><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Name</th><th>Type</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><tt>name</tt></td><td>CDATA</td><td><i>none, but required</i></td><td>
  @@ -195,13 +221,17 @@
                  specified  <tt>name</tt>.
                  If a <tt>value</tt> is provided,
                  the cookie must also have the specified value.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.credentials"></a>credentials</h1><div class="refnamediv"><a name="N2864"></a><h2>Name</h2>credentials &mdash; 
  +               </p></div></div>
  +               
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.credentials"></a>credentials</h1><div class="refnamediv"><a name="N2864"></a><h2>Name</h2>credentials &mdash; 
                  username/password credentials for Basic HTTP authentication.
               </div><div class="refsynopsisdiv"><a name="N2869"></a><h2>Synopsis</h2><div class="refsect2"><a name="N2870"></a><h3><a name="N2870"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT credentials EMPTY&gt;
   &lt;!ATTLIST credentials userName CDATA #REQUIRED
                         password  CDATA #REQUIRED&gt;</pre></div><div class="refsect2"><a name="N2876"></a><h3><a name="N2876"></a>Attributes</h3><div class="informaltable" id="N2879"><a name="N2879"></a><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Name</th><th>Type</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><tt>userName</tt></td><td>CDATA</td><td><i>none, required</i></td><td>User name. Required.</td></tr><tr><td><tt>password</tt></td><td>CDATA</td><td><i>none, required</i></td><td>Password. Required.</td></tr></tbody></table></div></div></div><div class="refsect1"><a name="N2917"></a><h2><a name="N2917"></a>Parents</h2><span class="simplelist"><tt><a href="#latka.ref.request">request</a></tt></span></div><div class="refsect1"><a name="N2926"></a><h2><a name="N2926"></a>Description</h2><p>
                  Contains credentials for HTTP Basic Authentication.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.maxRequestTime"></a>maxRequestTime</h1><div class="refnamediv"><a name="N2938"></a><h2>Name</h2>maxRequestTime &mdash; validates the response time for an HTTP(S) request</div><div class="refsynopsisdiv"><a name="N2943"></a><h2>Synopsis</h2><div class="refsect2"><a name="N2944"></a><h3><a name="N2944"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT maxRequestTime EMPTY&gt;
  +               </p></div></div>
  +               
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.maxRequestTime"></a>maxRequestTime</h1><div class="refnamediv"><a name="N2938"></a><h2>Name</h2>maxRequestTime &mdash; validates the response time for an HTTP(S) request</div><div class="refsynopsisdiv"><a name="N2943"></a><h2>Synopsis</h2><div class="refsect2"><a name="N2944"></a><h3><a name="N2944"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT maxRequestTime EMPTY&gt;
   &lt;!ATTLIST maxRequestTime millis CDATA "30000"
                              message  CDATA #IMPLIED&gt;</pre></div><div class="refsect2"><a name="N2950"></a><h3><a name="N2950"></a>Attributes</h3><div class="informaltable" id="N2953"><a name="N2953"></a><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Name</th><th>Type</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><tt>millis</tt></td><td>NUMBER</td><td><tt>30000</tt></td><td>
                                 Maximum amount of time, in milliseconds, in which
  @@ -217,21 +247,29 @@
                  A <tt>maxRequestTime</tt> validation
                  passes if the HTTP(S) response is obtained in no more than
                  <tt>millis</tt> milliseconds.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.param"></a>param</h1><div class="refnamediv"><a name="N3024"></a><h2>Name</h2>param &mdash; indicates a request parameter as part of an HTTP(S) request to be executed</div><div class="refsynopsisdiv"><a name="N3029"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3030"></a><h3><a name="N3030"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT request (<a href="#latka.ref.paramName">paramName</a>, <a href="#latka.ref.paramValue">paramValue</a>)&gt;</pre></div><div class="refsect2"><a name="N3042"></a><h3><a name="N3042"></a>Attributes</h3><p>
  +               </p></div></div>
  +               
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.param"></a>param</h1><div class="refnamediv"><a name="N3024"></a><h2>Name</h2>param &mdash; indicates a request parameter as part of an HTTP(S) request to be executed</div><div class="refsynopsisdiv"><a name="N3029"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3030"></a><h3><a name="N3030"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT request (<a href="#latka.ref.paramName">paramName</a>, <a href="#latka.ref.paramValue">paramValue</a>)&gt;</pre></div><div class="refsect2"><a name="N3042"></a><h3><a name="N3042"></a>Attributes</h3><p>
                     <i>None.</i>
                  </p></div></div><div class="refsect1"><a name="N3050"></a><h2><a name="N3050"></a>Parents</h2><span class="simplelist"><tt><a href="#latka.ref.request">request</a></tt></span></div><div class="refsect1"><a name="N3059"></a><h2><a name="N3059"></a>Description</h2><p>
                  A parameter to be submitted as part of a <tt><a href="#latka.ref.request">request</a></tt>.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.paramName"></a>paramName</h1><div class="refnamediv"><a name="N3075"></a><h2>Name</h2>paramName &mdash; the name part of a name/value pair parameter</div><div class="refsynopsisdiv"><a name="N3080"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3081"></a><h3><a name="N3081"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT paramName (#PCDATA)&gt;</pre></div><div class="refsect2"><a name="N3087"></a><h3><a name="N3087"></a>Attributes</h3><p>
  +               </p></div></div>
  +               
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.paramName"></a>paramName</h1><div class="refnamediv"><a name="N3075"></a><h2>Name</h2>paramName &mdash; the name part of a name/value pair parameter</div><div class="refsynopsisdiv"><a name="N3080"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3081"></a><h3><a name="N3081"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT paramName (#PCDATA)&gt;</pre></div><div class="refsect2"><a name="N3087"></a><h3><a name="N3087"></a>Attributes</h3><p>
                     <i>None.</i>
                  </p></div></div><div class="refsect1"><a name="N3095"></a><h2><a name="N3095"></a>Parents</h2><span class="simplelist"><tt><a href="#latka.ref.param">param</a></tt></span></div><div class="refsect1"><a name="N3104"></a><h2><a name="N3104"></a>Description</h2><p>
                  The name part of <tt><a href="#latka.ref.param">param</a></tt>
                  to be submitted as part of a <tt><a href="#latka.ref.request">request</a></tt>.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.paramValue"></a>paramValue</h1><div class="refnamediv"><a name="N3124"></a><h2>Name</h2>paramValue &mdash; the value part of a name/value pair parameter</div><div class="refsynopsisdiv"><a name="N3129"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3130"></a><h3><a name="N3130"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT paramValue (#PCDATA)&gt;</pre></div><div class="refsect2"><a name="N3136"></a><h3><a name="N3136"></a>Attributes</h3><p>
  +               </p></div></div>
  +               
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.paramValue"></a>paramValue</h1><div class="refnamediv"><a name="N3124"></a><h2>Name</h2>paramValue &mdash; the value part of a name/value pair parameter</div><div class="refsynopsisdiv"><a name="N3129"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3130"></a><h3><a name="N3130"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT paramValue (#PCDATA)&gt;</pre></div><div class="refsect2"><a name="N3136"></a><h3><a name="N3136"></a>Attributes</h3><p>
                     <i>None.</i>
                  </p></div></div><div class="refsect1"><a name="N3144"></a><h2><a name="N3144"></a>Parents</h2><span class="simplelist"><tt><a href="#latka.ref.param">param</a></tt></span></div><div class="refsect1"><a name="N3153"></a><h2><a name="N3153"></a>Description</h2><p>
                  The value part of <tt><a href="#latka.ref.param">param</a></tt>
                  to be submitted as part of a <tt><a href="#latka.ref.request">request</a></tt>.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.regexp"></a>regexp</h1><div class="refnamediv"><a name="N3173"></a><h2>Name</h2>regexp &mdash; validates the presence or absence of a regular expression within an HTTP(S) response</div><div class="refsynopsisdiv"><a name="N3178"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3179"></a><h3><a name="N3179"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT regexp EMPTY&gt;
  +               </p></div></div>
  +               
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.regexp"></a>regexp</h1><div class="refnamediv"><a name="N3173"></a><h2>Name</h2>regexp &mdash; validates the presence or absence of a regular expression within an HTTP(S) response</div><div class="refsynopsisdiv"><a name="N3178"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3179"></a><h3><a name="N3179"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT regexp EMPTY&gt;
   &lt;!ATTLIST regexp pattern    CDATA          #REQUIRED
                    cond       (true | false) "true"
                    ignoreCase (true | false) "false"
  @@ -256,7 +294,9 @@
                  A <tt>maxRequestTime</tt> validation
                  passes if the HTTP(S) response is obtained in no more than
                  <tt>millis</tt> milliseconds.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.request"></a>request</h1><div class="refnamediv"><a name="N3326"></a><h2>Name</h2>request &mdash; indicates an  HTTP(S) request to be executed</div><div class="refsynopsisdiv"><a name="N3331"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3332"></a><h3><a name="N3332"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT request (<a href="#latka.ref.credentials">credentials</a>?, <a href="#latka.ref.param">param</a>*, <a href="#latka.ref.validate">validate</a>?)&gt;
  +               </p></div></div>
  +
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.request"></a>request</h1><div class="refnamediv"><a name="N3326"></a><h2>Name</h2>request &mdash; indicates an  HTTP(S) request to be executed</div><div class="refsynopsisdiv"><a name="N3331"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3332"></a><h3><a name="N3332"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT request (<a href="#latka.ref.credentials">credentials</a>?, <a href="#latka.ref.param">param</a>*, <a href="#latka.ref.validate">validate</a>?)&gt;
   &lt;!ATTLIST request path   CDATA        #REQUIRED
                     method (post | get) "get"
                     host   CDATA        #IMPLIED
  @@ -275,7 +315,9 @@
                                 or reports. Optional.
                              </td></tr></tbody></table></div></div></div><div class="refsect1"><a name="N3448"></a><h2><a name="N3448"></a>Parents</h2><span class="simplelist"><tt><a href="#latka.ref.suite">suite</a></tt>, <tt><a href="#latka.ref.session">session</a></tt></span></div><div class="refsect1"><a name="N3461"></a><h2><a name="N3461"></a>Description</h2><p>
                  An HTTP(S) request to be executed.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.session"></a>session</h1><div class="refnamediv"><a name="N3473"></a><h2>Name</h2>suite &mdash; wrapper for a sequence of <tt><a href="#latka.ref.request">request</a></tt>s associated with the same state (session)</div><div class="refsynopsisdiv"><a name="N3482"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3483"></a><h3><a name="N3483"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT session (<a href="#latka.ref.request">request</a>+)&gt;
  +               </p></div></div>
  +
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.session"></a>session</h1><div class="refnamediv"><a name="N3473"></a><h2>Name</h2>suite &mdash; wrapper for a sequence of <tt><a href="#latka.ref.request">request</a></tt>s associated with the same state (session)</div><div class="refsynopsisdiv"><a name="N3482"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3483"></a><h3><a name="N3483"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT session (<a href="#latka.ref.request">request</a>+)&gt;
   &lt;!ATTLIST session sessionId CDATA #IMPLIED
                     label      CDATA #IMPLIED&gt;</pre></div><div class="refsect2"><a name="N3492"></a><h3><a name="N3492"></a>Attributes</h3><div class="informaltable" id="N3495"><a name="N3495"></a><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Name</th><th>Type</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><tt>sessionId</tt></td><td>CDATA</td><td><i>none</i></td><td>
                                 Unique identifier for this <tt>session</tt>.
  @@ -293,7 +335,9 @@
                  <tt><a href="#latka.ref.request">request</a></tt>
                  will be included in subsequent
                  <tt><a href="#latka.ref.request">request</a></tt>s.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.statusCode"></a>statusCode</h1><div class="refnamediv"><a name="N3579"></a><h2>Name</h2>statusCode &mdash; validates an HTTP response code</div><div class="refsynopsisdiv"><a name="N3584"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3585"></a><h3><a name="N3585"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT statusCode EMPTY&gt;
  +               </p></div></div>
  +               
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.statusCode"></a>statusCode</h1><div class="refnamediv"><a name="N3579"></a><h2>Name</h2>statusCode &mdash; validates an HTTP response code</div><div class="refsynopsisdiv"><a name="N3584"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3585"></a><h3><a name="N3585"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT statusCode EMPTY&gt;
   &lt;!ATTLIST statusCode code  CDATA "200"
                   message CDATA #IMPLIED&gt;</pre></div><div class="refsect2"><a name="N3591"></a><h3><a name="N3591"></a>Attributes</h3><div class="informaltable" id="N3594"><a name="N3594"></a><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Name</th><th>Type</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><tt>code</tt></td><td>NUMBER</td><td><tt>200</tt></td><td>
                                 Numeric HTTP response code to expect.
  @@ -308,7 +352,9 @@
                  passes if the HTTP(S) response code for the given request
                  matches the value specified by
                  <tt>code</tt>.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.suite"></a>suite</h1><div class="refnamediv"><a name="N3665"></a><h2>Name</h2>suite &mdash; root element for a suite of tests</div><div class="refsynopsisdiv"><a name="N3670"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3671"></a><h3><a name="N3671"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT suite ( (<a href="#latka.ref.session">session</a> | <a href="#latka.ref.request">request</a>)+ )&gt;
  +               </p></div></div>
  +
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.suite"></a>suite</h1><div class="refnamediv"><a name="N3665"></a><h2>Name</h2>suite &mdash; root element for a suite of tests</div><div class="refsynopsisdiv"><a name="N3670"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3671"></a><h3><a name="N3671"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT suite ( (<a href="#latka.ref.session">session</a> | <a href="#latka.ref.request">request</a>)+ )&gt;
   &lt;!ATTLIST suite defaultHost CDATA #IMPLIED
                   defaultPort CDATA #IMPLIED
                   label        CDATA #IMPLIED&gt;</pre></div><div class="refsect2"><a name="N3683"></a><h3><a name="N3683"></a>Attributes</h3><div class="informaltable" id="N3686"><a name="N3686"></a><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Name</th><th>Type</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td><tt>defaultHost</tt></td><td>CDATA</td><td><i>none</i></td><td>
  @@ -326,7 +372,9 @@
                  <tt><a href="#latka.ref.request">request</a></tt>s
                  and <tt><a href="#latka.ref.session">session</a></tt>s
                  to execute.
  -            </p></div></div><div class="refentry"><h1 class="title"><a name="latka.ref.validate"></a>validate</h1><div class="refnamediv"><a name="N3778"></a><h2>Name</h2>validate &mdash; 
  +               </p></div></div>
  +
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.validate"></a>validate</h1><div class="refnamediv"><a name="N3778"></a><h2>Name</h2>validate &mdash; 
                  indicates the suite of validations to apply to the
                  current <tt><a href="#latka.ref.request">request</a></tt> (and its response)
               </div><div class="refsynopsisdiv"><a name="N3787"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3788"></a><h3><a name="N3788"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT validate (<a href="#latka.ref.byteLength">byteLength</a> | <a href="#latka.ref.cookie">cookie</a> | <a href="#latka.ref.maxRequestTime">maxRequestTime</a> | <a href="#latka.ref.regexp">regexp</a> | <a href="#latka.ref.statusCode">statusCode</a> )+&gt;</pre></div><div class="refsect2"><a name="N3809"></a><h3><a name="N3809"></a>Attributes</h3><p>
  @@ -335,4 +383,46 @@
                  Contains the set of validations to apply to the
                  current <tt><a href="#latka.ref.request">request</a></tt>
                  (and its response).
  -            </p></div></div></div></div></body></html>
  +               </p></div></div>
  +
  +               
  +               <div class="refentry"><h1 class="title"><a name="latka.ref.xpath"></a>xpath</h1><div class="refnamediv"><a name="N3579"></a><h2>Name</h2>xpath &mdash; assuming the HTTP(s) response contains XML, checks if an <a href="http://www.w3.org/TR/xpath">XPath</a> expression matches</div><div class="refsynopsisdiv"><a name="N3584"></a><h2>Synopsis</h2><div class="refsect2"><a name="N3585"></a><h3><a name="N3585"></a>DTD</h3><pre class="synopsis">&lt;!ELEMENT xpath EMPTY&gt;
  +&lt;!ATTLIST xpath select    CDATA          #REQUIRED
  +                   cond       (true | false) "true"
  +                   value     CDATA          #IMPLIED
  +                   label     CDATA          #IMPLIED&gt;</pre></div><div class="refsect2"><a name="N3591"></a><h3><a name="N3591"></a>Attributes</h3><div class="informaltable" id="N3594"><a name="N3594"></a>
  +                   <table border="1"><colgroup><col><col><col></colgroup><thead>
  +                           <tr><th>Name</th><th>Type</th><th>Default</th><th>Description</th></tr>
  +                                   </thead>
  +                                   <tbody>
  +                                       <tr><td><tt>select</tt></td><td>CDATA</td><td><i>none</i></td><td>
  +                                    An XPath expression, designed to match a
  +                                    node in the XML body of the response.
  +                            </td></tr>
  +                            <tr><td><tt>cond</tt></td><td><i>Enumeration:</i><table class="simplelist" border="0" summary="Simple list"><tr><td><tt>true</tt></td></tr><tr><td><tt>false</tt></td></tr></table></td><td><tt>true</tt></td><td>
  +                              When <tt>true</tt>,
  +                              the given XPath expression
  +                              must match within the response.
  +                              When <tt>false</tt>,
  +                              the given XPath expression
  +                              must not match within the response.
  +                           </td></tr>
  +
  +                            <tr><td><tt>value</tt></td><td>CDATA</td><td><i>none, optional</i></td><td>
  +                                    The value that the matched node should have, if any.
  +                           </td></tr>
  +
  +                              <tr><td><tt>label</tt></td><td>CDATA</td><td><i>none</i></td><td>
  +                              Label associated with this validation, which may
  +                              be used in programatically generated documentation
  +                              or reports. Optional.
  +      </td></tr></tbody></table>
  +      </div></div></div><div class="refsect1"><a name="N3637"></a><h2><a name="N3637"></a>Parents</h2><span class="simplelist"><tt><a href="#latka.ref.validate">validate</a></tt></span></div><div class="refsect1"><a name="N3646"></a><h2><a name="N3646"></a>Description</h2><p>
  +               A <tt>xpath</tt> validation passes if the HTTP(S) response body
  +               contains XML, and the specified XPath expression matches (or
  +               not, depending on <tt>cond</tt>)
  +               </p></div></div>
  +
  +
  +
  +               </div></div></body></html>
  
  
  
  1.10      +1 -0      jakarta-commons/latka/resource/latka.properties.internal
  
  Index: latka.properties.internal
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/latka/resource/latka.properties.internal,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- latka.properties.internal	24 Aug 2001 18:55:23 -0000	1.9
  +++ latka.properties.internal	7 Jan 2002 11:26:24 -0000	1.10
  @@ -5,6 +5,7 @@
   latka.validator.cookie=org.apache.commons.latka.validators.CookieHandler
   latka.validator.responseHeader=org.apache.commons.latka.validators.ResponseHeaderHandler
   latka.validator.goldenFile=org.apache.commons.latka.validators.GoldenFileHandler
  +latka.validator.xpath=org.apache.commons.latka.validators.XPathHandler
   
   latka.writeLog=true
   
  
  
  
  1.1                  jakarta-commons/latka/src/java/org/apache/commons/latka/validators/XPathHandler.java
  
  Index: XPathHandler.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 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", "Tomcat", 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/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */   
  
  package org.apache.commons.latka.validators;
  
  import org.apache.commons.latka.xml.ValidationHandler;
  
  import org.xml.sax.Attributes;
  import org.xml.sax.SAXException;
  
  /**
   * Handler for the {@link XPathValidator} class.
   *
   * @author <a href="mailto:jefft@apache.org">Jeff Turner</a>
   * @since 6 January, 2001
   */
  public class XPathHandler extends ValidationHandler {
  
    public void startElement(String uri, String localName,
                             String qName, Attributes atts)
    throws SAXException {
  
      log.debug(localName);
  
      XPathValidator validator =
        new XPathValidator(atts.getValue("label"));
      validator.setSelect(atts.getValue("select"));
      validator.setValue(atts.getValue("value"));
  
      String cond = atts.getValue("cond");
      if (cond != null) {
        validator.setCondition(Boolean.valueOf(cond).booleanValue());
      }
  
      validate(validator);
    }
  }
  
  
  
  1.1                  jakarta-commons/latka/src/java/org/apache/commons/latka/validators/XPathValidator.java
  
  Index: XPathValidator.java
  ===================================================================
  
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 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", "Tomcat", 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/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */   
  package org.apache.commons.latka.validators;
  
  import org.apache.commons.latka.Validator;
  import org.apache.commons.latka.ValidationException;
  
  import org.apache.commons.latka.http.Request;
  import org.apache.commons.latka.http.Response;
  
  import org.jdom.Document;
  import org.jdom.Element;
  import org.jdom.JDOMException;
  import org.jdom.input.SAXBuilder;
  import org.jaxen.jdom.XPath;
  import org.jaxen.JaxenException;
  
  /**
   * An XPath validator.
   *
   * <p>Use is of the form:</p>
   * <p>&lt;xpath select="..." [ value="..." ] [ cond="true | false" ] /&gt;</p>
   * <p>Where :</p>
   * <ul>
   *  <li><code>select</code> is an XPath expression, designed to match a node in
   *  the XML body of the response.</li>
   *  <li><code>value</code> is an option value which the string value of the
   *  selected node should match.</li>
   *  <li><code>cond</code> is an optional boolean value, indicating
   *  whether the test logic is to be inverted. Defaults to
   *  <code>true</code>.</li>
   * </ul>
   *
   * </p>
   * <p>
   * If the user has specified a {@link #setValue value}, then the XPath
   * expression is expected to evaluate to a text or attribute node (or other
   * textual 'leaf' nodes), in which case the selected value must match that
   * specified.
   * </p>
   * <p>
   * If no value is specified, then the XPath expression will be used to check for
   * the <em>existence</em> of a node.
   * </p>
   * <p>
   * If the XPath expression evaluates to a boolean condition (eg
   * &lt;xpath select="foo/bar='baz'"/&gt;), then the condition will be evaluated and will
   * result in the test passing or failing. Equivalently, an expression may be
   * specified, and <code>value</code> used to require a specific value (eg
   * &lt;xpath select="/foo/bar" value="baz"/&gt;).
   * </p>
   * <p>
   * Finally, setting <code>cond="false"</code> negates the sense of the
   * test, allowing one to test for the <em>nonexistence</em> or
   * <em>inequality</em> of nodes and values.
   * </p>
   *
   * @author <a href="mailto:jefft@apache.org">Jeff Turner</a>
   * @since 6 January, 2001
   */
  public class XPathValidator extends BaseValidator implements Validator {
  
    // General notes:
    // - It started out simple, honest.. =)
    // - We really need to separate out the negation logic into a separate <not>
    //   tag. It's silly having xpath, regexp and whathaveyou all doing their own
    //   negation tests..
    // - Need some unit tests, with a mock object for the Response.
  
    // --------------------------------------------------------------- Attributes
  
    protected String _select = null;
    protected boolean _cond = true;
    protected String _value = null;
  
    protected static final String TRUE_MESSAGE = "EXPECTED TO MATCH XPATH: ";
    protected static final String FALSE_MESSAGE = "DID NOT EXPECT TO MATCH XPATH: ";
  
    // ------------------------------------------------------------- Constructors
  
    public XPathValidator() {
      this(null,null,true,null);
    }
  
    public XPathValidator(String label) {
      this(label,null,true,null);
    }
  
    public XPathValidator(String label, String select, boolean cond, String value) {
      super(label);
      _select = select;
      _cond = cond;
      _value = value;
    }
  
    // ------------------------------------------------------------------ Public Methods
  
    public void setSelect(String select) {
      _select = select;
    }
  
    public void setCondition(boolean cond) {
      _cond = cond;
    }
  
    public void setValue(String value) {
      _value = value;
    }
  
    public void validate(Response response)
    throws ValidationException {
  
      XPath xpath = getXPath(_select); // compile the XPath expression
      Document doc = getDocument(response); // retrieve the XML Document to process
      Object selected = getSelectedNode(xpath, doc); // Apply the XPath to retrieve a node
  
  
      // Now the fun begins, where we see if our selected node meets the criteria.
      // There are three factors:
      // 
      // 1) What type of object did the XPath expression return?
      // 2) If _value is specified, ie if we're testing for _value_ or _existence_
      // 3) If _cond is true/false, ie do we WANT the value to match/node to exist?
  
  
      if (selected instanceof Boolean) {
        // Eg, we had an expression /foo = 'bar'
        _log.debug("Boolean XPath expression evaluated to "+selected);
        if (_value != null) {
          _log.warn("Ignoring unused value '"+_value+"'.");
        }
        boolean matched = ((Boolean)selected).booleanValue();
        if (_cond != matched) {
          fail("Boolean XPath '"+_select+"' didn't match.");
        }
      } else if (selected instanceof String) {
        _log.debug("XPath selected string '"+selected+"'.");
        if (_value != null) {
          boolean matched = selected.equals(_value);
          if (_cond != matched) {
            StringBuffer buf = new StringBuffer();
            if (_cond == true) {
              buf.append(TRUE_MESSAGE);
            } else {
              buf.append(FALSE_MESSAGE);
            }
            buf.append(_select);
            fail(buf.toString());
          }
        } else {
          // otherwise we only test if the node is meant to exist
          if (!_cond) {
            fail("XPath '"+_select+"' selected string '"+selected+
                "' when specified not to.");
          }
        }
      } else if (selected instanceof Element) {
        if (_log.isDebugEnabled()) {
          _log.debug("XPath matched element: ");
          _log.debug(printElement((Element)selected));
        }
        if (_value != null) {
          _log.warn("Ignoring unused value '"+_value+"'.");
        }
        if (!_cond) {
          fail("XPath '"+_select+"' selected element '"+selected+
              "' when specified not to.");
        }
      } else {
        // Otherwise Jaxen is returning something odd
        if (_value != null) {
          // Hope that .equals() does a sensible comparison
          boolean matched = selected.equals(_value);
          if (_cond != matched) {
            fail("XPath expression '"+_value+"' returned '"+selected+
                "' of unknown type "+selected.getClass().getName()+
                ". This did "+(_cond?"not ":"")+"match the specified value '"+_value+"'."
                );
          }
        } else {
          // only test if the node (whatever it is) is meant to exist
          if (!_cond) {
            fail("XPath '"+_select+"' selected node '"+selected+
              "' when specified not to.");
          }
          _log.warn("Selected unknown type "+selected.getClass().getName());
        }
      }
    }
  
    // ------------------------------------------------------------------ Private Methods
  
    /**
     * Creates a Jaxen <code>XPath</code> for a given XPath expression.
     * @param xpathExpr The XPath expression
     * @return A non-null Jaxen <code>XPath</code> object.
     * @throws ValidationException if <code>xpathExpr</code> was invalid.
     */
    private XPath getXPath(final String xpathExpr)
    throws ValidationException
    {
      XPath xpath = null;
      try {
        xpath = new XPath(xpathExpr);
      } catch (JaxenException e) {
        fail("Couldn't compile XPath xpathExpr "+xpathExpr+": "+e.toString());
      }
  
      if (xpath == null) { // this should never happen
        fail("Null compiled XPath object");
      }
  
      if (_log.isDebugEnabled()) {
        _log.debug("Using XPath expression: "+xpathExpr);
      }
      return xpath;
    }
  
    /**
     * Creates a <code>Document</code> from the Response.
     * @param response The (usu. HTTP) Reponse object presumably containing an XML
     * response body.
     * @return A non-null <code>Document</code> representing the response body.
     * @throws ValidationException if the Response object's body did not contain
     * well-formed XML.
     */
    private Document getDocument(Response response)
    throws ValidationException
    {
      Document doc = null;
      SAXBuilder builder = new SAXBuilder();
      try {
        doc = builder.build(response.getStream());
      } catch (JDOMException e) {
        fail(e.toString());
      }
      if (doc == null) { // this should never happen
        fail("Null document");
      }
      if (_log.isDebugEnabled()) {
        _log.debug("Processing doc: "+printDoc(doc));
      }
      return doc;
    }
  
    /**
     * Apply a compiled XPath expression to an XML Document, and return the
     * selected node. 
     * @param xpath The compiled Jaxen <code>XPath</code> object
     * @param doc The <code>Document</code> object containing the XML.
     * @return A non-null object returned from Jaxen. This may be:
     * <ul>
     *  <li>A String, if the expression selected an element with a text node child</li>
     *  <li>An <code>Element</code></li>
     *  <li>A <code>java.lang.Boolean</code>, if the XPath expression is a
     *  statement (eg /foo/bar='content')</li>
     *  <li>Anything else the Jaxen author deemed useful; ie don't assume anything</li>
     * </ul>
     */
    private Object getSelectedNode(XPath xpath, Document doc)
    throws ValidationException
    {
      Object selected = null;
      try {
        selected = xpath.selectSingleNode(doc);
      } catch (JaxenException e) {
        fail("XPath expression '"+_select+"' didn't match any node. "+e.toString());
      }
      if (selected == null) {
        fail("Couldn't find node '"+_select+"' in document");
      }
  
      return selected;
    }
  
    /**
     * Utility method for returning an XML rendition of a <code>Document</code>.
     * @param doc The Document to print
     * @return A String of XML representing the document.
     */
    private String printDoc(final Document doc) {
      java.io.StringWriter sw = new java.io.StringWriter();
      try {
        new org.jdom.output.XMLOutputter().output(doc, sw);
      } catch (java.io.IOException ioe) {
        _log.error("Could not print XML document.", ioe);
      }
      return sw.toString();
    }
  
    /**
     * Utility method for returning an XML rendition of a <code>Element</code>.
     * @param elem an <code>Element</code> to print.
     * @return A String of XML representing the element.
     */
    private String printElement(final Element elem) {
      java.io.StringWriter sw = new java.io.StringWriter();
      Element clone = (Element)((Element)elem).clone();
      org.jdom.output.XMLOutputter xmlOut = new org.jdom.output.XMLOutputter();
      try {
        xmlOut.output(new org.jdom.Document(clone), sw);
      } catch (java.io.IOException ioe) {
        _log.error("Could not print XML element.", ioe);
      }
      return sw.toString();
    }
  }
  
  
  

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


Mime
View raw message