You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by js...@apache.org on 2002/09/05 02:21:57 UTC

cvs commit: jakarta-commons/httpclient/src/test/org/apache/commons/httpclient TestStatusLine.java TestNoHost.java

jsdever     2002/09/04 17:21:57

  Modified:    httpclient/src/java/org/apache/commons/httpclient
                        HttpMethod.java HttpMethodBase.java
               httpclient/src/java/org/apache/commons/httpclient/util
                        HttpURLConnection.java
               httpclient/src/test/org/apache/commons/httpclient
                        TestNoHost.java
  Added:       httpclient/src/java/org/apache/commons/httpclient
                        StatusLine.java
               httpclient/src/test/org/apache/commons/httpclient
                        TestStatusLine.java
  Log:
  Status-Line encapsulation.
  
  Contributor: Jeff Dever
  
  Revision  Changes    Path
  1.17      +10 -4     jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethod.java
  
  Index: HttpMethod.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethod.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- HttpMethod.java	3 Sep 2002 01:36:26 -0000	1.16
  +++ HttpMethod.java	5 Sep 2002 00:21:56 -0000	1.17
  @@ -302,4 +302,10 @@
        * Use this method internally to add footers.
        */
       public void addResponseFooter(Header footer);
  +
  +    /** 
  +     * Return the Status-Line from the response.
  +     * @since 2.0
  +     */
  +    public String getStatusLine();
   }
  
  
  
  1.56      +38 -58    jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java
  
  Index: HttpMethodBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v
  retrieving revision 1.55
  retrieving revision 1.56
  diff -u -r1.55 -r1.56
  --- HttpMethodBase.java	3 Sep 2002 11:19:35 -0000	1.55
  +++ HttpMethodBase.java	5 Sep 2002 00:21:56 -0000	1.56
  @@ -183,6 +183,9 @@
       /** My request headers, if any. */
       private HashMap requestHeaders = new HashMap();
   
  +    /** The Status-Line from the response. */
  +    private StatusLine statusLine = null;
  +
       /** My response headers, if any. */
       private HashMap responseHeaders = new HashMap();
   
  @@ -201,9 +204,6 @@
       /** My query string, if any. */
       private String queryString = null;
   
  -    /** My response status text, if any. */
  -    private String statusText = null;
  -
       /** The response body, assuming it has not be intercepted by a sub-class. */
       private InputStream responseStream = null;
   
  @@ -231,8 +231,6 @@
        */
       private int maxRetries = 3;
   
  -    /** My response status code, if any. */
  -    private int statusCode = -1;
   
       //~ Constructors �����������������������������������������������������������
   
  @@ -446,9 +444,10 @@
        * Provide access to the status code.
        * 
        * @return the status code associated with the latest response.
  +     * @deprecated use getStatusLine().getStatusCode()
        */
       public int getStatusCode() {
  -        return statusCode;
  +        return statusLine.getStatusCode();
       }
   
       /**
  @@ -585,9 +584,10 @@
        * 
        * @return the status text (or "reason phrase") associated with the latest
        *         response.
  +     * @deprecated use getStatusLine.getReasonPhrase()
        */
       public String getStatusText() {
  -        return statusText;
  +        return statusLine.getReasonPhrase();
       }
   
       /**
  @@ -659,7 +659,7 @@
       private boolean shouldCloseConnection() {
           if (!http11) {
               if (getName().equals(ConnectMethod.NAME) && 
  -                    (statusCode == HttpStatus.SC_OK)) {
  +                    (statusLine.getStatusCode() == HttpStatus.SC_OK)) {
                   log.debug("Will leave connection open for tunneling");
                   return false;
               } else {
  @@ -741,6 +741,7 @@
               //if SC_CONTINUE write the request body
               writeRemainingRequestBody(state, conn);
   
  +            int statusCode = statusLine.getStatusCode();
               switch (statusCode) {
                   case HttpStatus.SC_UNAUTHORIZED:
                   case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
  @@ -886,8 +887,7 @@
           queryString = null;
           requestHeaders.clear();
           responseHeaders.clear();
  -        statusCode = -1;
  -        statusText = null;
  +        statusLine = null;
           used = false;
           http11 = true;
           bodySent = false;
  @@ -1425,7 +1425,8 @@
        * @param conn the {@link HttpConnection} to read the response from
        * @return InputStream to read the response body from
        */
  -    private InputStream _readResponseBody(HttpState state, HttpConnection conn) throws IOException {
  +    private InputStream _readResponseBody(HttpState state, HttpConnection conn) 
  +    throws IOException {
           log.trace("enter HttpMethodBase.readResponseBody(HttpState, HttpConnection)");
   
           responseBody = null; // is this desired?
  @@ -1447,7 +1448,8 @@
               if ("chunked".equalsIgnoreCase(transferEncodingHeader.getValue())) {
                   result = new ChunkedInputStream(is, this);
               }
  -        } else if(canResponseHaveBody(statusCode) && !getName().equals(ConnectMethod.NAME)){
  +        } else if(canResponseHaveBody(statusLine.getStatusCode()) 
  +                && !getName().equals(ConnectMethod.NAME)){
               result = is;
           }
           if (result == null) return null;
  @@ -1558,63 +1560,40 @@
        * @throws HttpRecoverableException when the status line is null and the
        *      request should be retried
        * 
  -     * @see #readResponse
  -     * @see #processStatusLine
  +     * @see StatusLine
        */
       protected void readStatusLine(HttpState state, HttpConnection conn)
       throws IOException, HttpRecoverableException, HttpException {
           log.trace(
               "enter HttpMethodBase.readStatusLine(HttpState, HttpConnection)");
   
  -        statusCode = -1;
  -        statusText = null;
  -
  -        String statusLine = conn.readLine();
  -
  -        while ((statusLine != null) && !statusLine.startsWith("HTTP/")) {
  -            statusLine = conn.readLine();
  +        //read out the HTTP status string
  +        String statusString = conn.readLine();
  +        while ((statusString != null) && !statusString.startsWith("HTTP/")) {
  +            statusString = conn.readLine();
           }
  -        if (statusLine == null) {
  -            // A null statusLine means the connection was lost before we got a
  +        if (statusString == null) {
  +            // A null statusString means the connection was lost before we got a
               // response.  Try again.
               throw new HttpRecoverableException("Error in parsing the status "
                   + " line from the response: unable to find line starting with"
                   + " \"HTTP/\"");
           }
   
  -        if ((!statusLine.startsWith("HTTP/1.1")
  -                && !statusLine.startsWith("HTTP/1.0"))) {
  -            throw new HttpException("Unrecognized server protocol :"
  -                                    + statusLine);
  -        }
  -
  -        http11 = statusLine.startsWith("HTTP/1.1");
  -
  -        int at = statusLine.indexOf(" ");
  -        if (at < 0) {
  -            throw new HttpException("Unable to parse the status line: "
  -                                    + statusLine);
  -        }
  -
  -        int to = statusLine.indexOf(" ", at + 1);
  -        if (to < 0) {
  -            to = statusLine.length();
  -        }
  +        //create the status line from the status string
  +        statusLine = new StatusLine(statusString);
   
  -        try {
  -            statusCode = Integer.parseInt(statusLine.substring(at + 1, to));
  -        } catch (NumberFormatException e) {
  -            throw new HttpException(
  -                "Unable to parse status code from status line: " + statusLine);
  +        //check for a valid HTTP-Version
  +        String httpVersion = statusLine.getHttpVersion();
  +        if (httpVersion.equals("HTTP/1.0")){
  +            http11 = false;
  +        } else if (httpVersion.equals("HTTP/1.1")){
  +            http11 = true;
  +        } else {
  +            throw new HttpException("Unrecognized server protocol: '"
  +                                    + httpVersion + "'");
           }
   
  -        try {
  -            if (to < statusLine.length()) {
  -                statusText = statusLine.substring(to + 1);
  -            }
  -        } catch (StringIndexOutOfBoundsException e) {
  -            throw new HttpException("Status text not specified: " + statusLine);
  -        }
       }
   
       // ------------------------------------------------------ Protected Methods
  @@ -1892,6 +1871,7 @@
           log.trace("enter HttpMethodBase.processAuthenticationResponse("
               + "HttpState, HttpConnection)");
   
  +        int statusCode = statusLine.getStatusCode();
           // handle authentication required
           Header wwwauth = null;
           Set realmsUsed = null;
  @@ -2046,7 +2026,7 @@
       throws HttpException, IOException {
           log.trace("enter writeRemainingRequestBody(HttpState, HttpConnection)");
   
  -        if (HttpStatus.SC_CONTINUE == statusCode) {
  +        if (HttpStatus.SC_CONTINUE == statusLine.getStatusCode()) {
               if (!bodySent) {
                   bodySent = writeRequestBody(state, connection);
               } else {
  
  
  
  1.1                  jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/StatusLine.java
  
  Index: StatusLine.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/StatusLine.java,v 1.1 2002/09/05 00:21:56 jsdever Exp $
   * $Revision: 1.1 $
   * $Date: 2002/09/05 00:21:56 $
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 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", "HttpClient", 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.httpclient;
  
  import org.apache.commons.logging.LogFactory;
  import org.apache.commons.logging.Log;
  
  /**
   * Represents a Status-Line as returned from a HTTP server.
   *
   * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a> states
   * the following regarding the Status-Line:
   * <pre>
   * 6.1 Status-Line
   *
   *  The first line of a Response message is the Status-Line, consisting
   *  of the protocol version followed by a numeric status code and its
   *  associated textual phrase, with each element separated by SP
   *  characters. No CR or LF is allowed except in the final CRLF sequence.
   *
   *      Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
   * </pre>
   * <p>
   * This class is immutable and is inherently thread safe.
   *
   * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
   * @version $Id: StatusLine.java,v 1.1 2002/09/05 00:21:56 jsdever Exp $
   * @since 2.0
   */
  public class StatusLine {
  
      // ----------------------------------------------------- Instance Variables
  
      /** The original Status-Line. */
      private final String statusLine;
  
      /** The HTTP-Version. */
      private final String httpVersion;
  
      /** The Status-Code. */
      private final int statusCode;
  
      /** The Reason-Phrase. */
      private final String reasonPhrase;
  
  
      // ----------------------------------------------------------- Constructors
  
      /**
       * Default constructor.
       *
       * @param statusLine the status line returned from the HTTP server
       * @throws HttpException if the status line is invalid
       */
      public StatusLine(String statusLine) 
      throws HttpException {
  
          //save the original Status-Line
          this.statusLine = new String(statusLine);
          int length = statusLine.length();
  
  
          //check validity of the Status-Line
          if (! statusLine.startsWith("HTTP/")) {
              throw new HttpException("Status-Line '" + statusLine + 
                      "' does not start with HTTP/");
          }
  
          //handle the HTTP-Version
          int at = statusLine.indexOf(" ");
          if (at <= 0) {
              throw new HttpException(
                      "Unable to parse HTTP-Version from the status line: '"
                      + statusLine + "'");
          }
          this.httpVersion = (statusLine.substring(0, at)).toUpperCase();
  
          //handle the Status-Code
          int to = statusLine.indexOf(" ", at + 1);
          if (to < 0) {
              to = length;
          }
          try {
              this.statusCode = Integer.parseInt(statusLine.substring(at+1, to));
          } catch (NumberFormatException e) {
              throw new HttpException(
                  "Unable to parse status code from status line: '" 
                  + statusLine + "'");
          }
  
          //handle the Reason-Phrase
          try {
              if (to < length) {
                  if (statusLine.endsWith("\n\r")) {
                      this.reasonPhrase = statusLine.substring(to+1, length-2);
                  } else {
                      this.reasonPhrase = statusLine.substring(to+1);
                  }
              } else {
                  this.reasonPhrase = "";
              }
          } catch (StringIndexOutOfBoundsException e) {
              throw new HttpException("Status text not specified: '" 
                      + statusLine + "'");
          }
      }
  
  
      // --------------------------------------------------------- Public Methods
  
      /**
       * @return the Status-Code
       */
      public final int getStatusCode() {
          return statusCode;
      }
  
      /**
       * @return the HTTP-Version
       */
      public final String getHttpVersion() {
          return httpVersion;
      }
  
      /**
       * @return the Reason-Phrase
       */
      public final String getReasonPhrase() {
          return reasonPhrase;
      }
  
      public final String toString() {
          return statusLine;
      }
  }
  
  
  
  1.6       +5 -12     jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/util/HttpURLConnection.java
  
  Index: HttpURLConnection.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/util/HttpURLConnection.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- HttpURLConnection.java	4 Sep 2002 00:58:26 -0000	1.5
  +++ HttpURLConnection.java	5 Sep 2002 00:21:57 -0000	1.6
  @@ -63,7 +63,6 @@
   package org.apache.commons.httpclient.util;
   
   import org.apache.commons.httpclient.HttpMethod;
  -import org.apache.commons.httpclient.HttpMethodBase;
   import org.apache.commons.httpclient.Header;
   
   import org.apache.commons.logging.LogFactory;
  @@ -273,13 +272,7 @@
           // return the status line. Hence the special case below ...
           
           if (position == 0) {
  -            if (((HttpMethodBase) this.method).isHttp11()) {
  -                return "HTTP/1.1 " + this.method.getStatusCode() 
  -                    + " " + this.method.getStatusText();
  -            } else {
  -                return "HTTP/1.0 " + this.method.getStatusCode() 
  -                    + " " + this.method.getStatusText();
  -            }
  +            return this.method.getStatusLine();
           }
   
           // Note: I hope the header fields are kept in the correct order when
  
  
  
  1.12      +5 -4      jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestNoHost.java
  
  Index: TestNoHost.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestNoHost.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- TestNoHost.java	2 Sep 2002 14:52:48 -0000	1.11
  +++ TestNoHost.java	5 Sep 2002 00:21:57 -0000	1.12
  @@ -98,6 +98,7 @@
           suite.addTest(TestResponseHeaders.suite());
           suite.addTest(TestRequestHeaders.suite());
           suite.addTest(TestStreams.suite());
  +        suite.addTest(TestStatusLine.suite());
           return suite;
       }
   
  
  
  
  1.1                  jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestStatusLine.java
  
  Index: TestStatusLine.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestStatusLine.java,v 1.1 2002/09/05 00:21:57 jsdever Exp $
   * $Revision: 1.1 $
   * $Date: 2002/09/05 00:21:57 $
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 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.httpclient;
  
  import junit.framework.*;
  
  /**
   * Simple tests for {@link StatusLine}.
   *
   * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
   * @version $Id: TestStatusLine.java,v 1.1 2002/09/05 00:21:57 jsdever Exp $
   */
  public class TestStatusLine extends TestCase {
  
      private StatusLine statusLine = null;
  
      // ------------------------------------------------------------ Constructor
      public TestStatusLine(String testName) {
          super(testName);
      }
  
      // ------------------------------------------------------------------- Main
      public static void main(String args[]) {
          String[] testCaseName = { TestStatusLine.class.getName() };
          junit.textui.TestRunner.main(testCaseName);
      }
  
      // ------------------------------------------------------- TestCase Methods
  
      public static Test suite() {
          return new TestSuite(TestStatusLine.class);
      }
  
      // ------------------------------------------------------ Protected Methods
  
  
      // ----------------------------------------------------------- Test Methods
  
      public void testSuccess() throws Exception {
          //typical status line
          statusLine = new StatusLine("HTTP/1.1 200 OK");
          assertEquals("HTTP/1.1 200 OK", statusLine.toString());
          assertEquals("HTTP/1.1", statusLine.getHttpVersion());
          assertEquals(200, statusLine.getStatusCode());
          assertEquals("OK", statusLine.getReasonPhrase());
  
          //status line with multi word reason phrase
          statusLine = new StatusLine("HTTP/1.1 404 Not Found");
          assertEquals(404, statusLine.getStatusCode());
          assertEquals("Not Found", statusLine.getReasonPhrase());
  
          //reason phrase can be anyting
          statusLine = new StatusLine("HTTP/1.1 404 Non Trouv�");
          assertEquals("Non Trouv�", statusLine.getReasonPhrase());
  
          //its ok to end with a \n\r
          statusLine = new StatusLine("HTTP/1.1 404 Not Found\n\r");
          assertEquals("Not Found", statusLine.getReasonPhrase());
  
          //this is valid according to the Status-Line BNF
          statusLine = new StatusLine("HTTP/1.1 200 ");
          assertEquals(200, statusLine.getStatusCode());
          assertEquals("", statusLine.getReasonPhrase());
  
          //this is not strictly valid, but is lienent
          statusLine = new StatusLine("HTTP/1.1 200");
          assertEquals(200, statusLine.getStatusCode());
          assertEquals("", statusLine.getReasonPhrase());
      }
  
      public void testFailure() throws Exception {
          try {
              statusLine = new StatusLine(null);
              fail();
          } catch (NullPointerException e) { /* expected */ }
  
          try {
              statusLine = new StatusLine("xxx 200 OK");
              fail();
          } catch (HttpException e) { /* expected */ }
  
          try {
              statusLine = new StatusLine("HTTP/1.1 xxx OK");
              fail();
          } catch (HttpException e) { /* expected */ }
  
  
      }
  
  }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>