You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cactus-dev@jakarta.apache.org by vm...@apache.org on 2003/02/22 21:24:17 UTC

cvs commit: jakarta-cactus/framework/src/java/j2ee13/org/apache/cactus/util FilterConfiguration.java

vmassol     2003/02/22 12:24:17

  Modified:    framework/src/java/share/org/apache/cactus/client/authentication
                        FormAuthentication.java
               framework/src/java/share/org/apache/cactus/configuration
                        Configuration.java BaseConfiguration.java
               framework/src/java/share/org/apache/cactus
                        AbstractWebServerTestCase.java WebRequest.java
               framework/src/java/j2ee13/org/apache/cactus/util
                        FilterConfiguration.java
  Added:       framework/src/java/share/org/apache/cactus/client/connector
                        ConnectionHelperFactory.java
                        JdkConnectionHelper.java DefaultHttpClient.java
                        AbstractConnectionHelper.java
                        AutoReadHttpURLConnection.java
                        ConnectionHelper.java
                        HttpClientConnectionHelper.java
  Removed:     framework/src/java/share/org/apache/cactus/client
                        AutoReadHttpURLConnection.java
                        DefaultHttpClient.java ConnectionHelper.java
                        ConnectionHelperFactory.java
                        HttpClientConnectionHelper.java
                        AbstractConnectionHelper.java
                        JdkConnectionHelper.java
  Log:
  Package refactoring (should not affect any cactus user)
  
  Revision  Changes    Path
  1.1                  jakarta-cactus/framework/src/java/share/org/apache/cactus/client/connector/ConnectionHelperFactory.java
  
  Index: ConnectionHelperFactory.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 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", "Cactus" and "Apache Software
   *    Foundation" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.cactus.client.connector;
  
  import java.lang.reflect.Constructor;
  
  import org.apache.cactus.configuration.Configuration;
  import org.apache.cactus.util.ChainedRuntimeException;
  
  /**
   * Factory that returns the <code>ConnectionHelper</code> specified in Cactus
   * configuration or the default one if none has been specified.
   *
   * @see Configuration
   *
   * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
   *
   * @version $Id: ConnectionHelperFactory.java,v 1.1 2003/02/22 20:24:15 vmassol Exp $
   */
  public class ConnectionHelperFactory
  {
      /**
       * @return a <code>ConnectionHelper</code> instance of the type specified
       *         in Cactus configuration or the default one
       *         (<code>JdkConnectionHelper</code>)
       * @param theUrl the URL to connect to as a String
       * @param theConfiguration the Cactus configuration
       */
      public static ConnectionHelper getConnectionHelper(String theUrl,
          Configuration theConfiguration)
      {
          // Load the corresponding class
          ConnectionHelper connectionHelper;
  
          try
          {
              Class connectionHelperClass = 
                  Class.forName(theConfiguration.getConnectionHelper());
              Constructor constructor = connectionHelperClass.getConstructor(
                  new Class[] {String.class});
  
              connectionHelper = (ConnectionHelper) constructor.newInstance(
                  new Object[] {theUrl});
          }
          catch (Exception e)
          {
              throw new ChainedRuntimeException("Failed to load the ["
                  + theConfiguration.getConnectionHelper()
                  + "] ConnectionHelper " + "class", e);
          }
  
          return connectionHelper;
      }
  }
  
  
  1.1                  jakarta-cactus/framework/src/java/share/org/apache/cactus/client/connector/JdkConnectionHelper.java
  
  Index: JdkConnectionHelper.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 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", "Cactus" and "Apache Software
   *    Foundation" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.cactus.client.connector;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.io.PrintWriter;
  
  import java.net.HttpURLConnection;
  import java.net.URL;
  import java.net.URLConnection;
  import java.net.URLEncoder;
  
  import java.util.Enumeration;
  
  import org.apache.cactus.WebRequest;
  import org.apache.cactus.client.authentication.AbstractAuthentication;
  import org.apache.cactus.util.ChainedRuntimeException;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  /**
   * Implementation of <code>ConnectionHelper</code> using the JDK
   * <code>HttpURLConnection</code> class.
   *
   * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
   * @author <a href="mailto:Jason.Robertson@acs-inc.com">Jason Robertson</a>
   *
   * @version $Id: JdkConnectionHelper.java,v 1.1 2003/02/22 20:24:15 vmassol Exp $
   */
  public class JdkConnectionHelper extends AbstractConnectionHelper
  {
      /**
       * The logger
       */
      private static final Log LOGGER = 
          LogFactory.getLog(JdkConnectionHelper.class);
  
      // Static initialisations
      static
      {
          // Do not follow redirects (because we are doing unit tests and
          // we need to be able to assert the returned headers, cookies, ...)
          HttpURLConnection.setFollowRedirects(false);
      }
  
      /**
       * The URL that will be used for the HTTP connection.
       */
      private String url;
  
      /**
       * @param theURL the URL that will be used for the HTTP connection.
       */
      public JdkConnectionHelper(String theURL)
      {
          this.url = theURL;
      }
  
      /**
       * @see ConnectionHelper#connect(WebRequest)
       */
      public HttpURLConnection connect(WebRequest theRequest) throws Throwable
      {
          URL url = new URL(this.url);
  
          // Add Authentication headers, if necessary. This is the first
          // step to allow authentication to add extra headers, HTTP parameters,
          // etc.
          AbstractAuthentication authentication = theRequest.getAuthentication();
  
          if (authentication != null)
          {
              authentication.configure(theRequest);
          }
  
  
          // Add the parameters that need to be passed as part of the URL
          url = addParametersGet(theRequest, url);
  
          HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  
          connection.setDoInput(true);
  
          // Choose the method that we will use to post data :
          // - If at least one parameter is to be sent in the request body, then
          //   we are doing a POST.
          // - If user data has been specified, then we are doing a POST
          if (theRequest.getParameterNamesPost().hasMoreElements()
              || (theRequest.getUserData() != null))
          {
              connection.setDoOutput(true);
          }
          else
          {
              connection.setDoOutput(false);
          }
  
          connection.setUseCaches(false);
  
          // Sets the content type
          connection.setRequestProperty("Content-type", 
              theRequest.getContentType());
  
          // Add the other header fields
          addHeaders(theRequest, connection);
  
          // Add the cookies
          String cookieString = getCookieString(theRequest, url);
  
          if (cookieString != null)
          {
              connection.setRequestProperty("Cookie", cookieString);
          }
  
          // Add the POST parameters if no user data has been specified (user data
          // overried post parameters)
          if (theRequest.getUserData() != null)
          {
              addUserData(theRequest, connection);
          }
          else
          {
              addParametersPost(theRequest, connection);
          }
  
  
          // Log content length
          LOGGER.debug("ContentLength = [" + connection.getContentLength() + "]");
  
  
          // Open the connection and get the result
          connection.connect();
  
          return connection;
      }
  
      /**
       * Add user data in the request body.
       *
       * @param theRequest the request containing all data to pass to the server
       *        redirector.
       * @param theConnection the HTTP connection
       * @exception IOException if we fail to read the user data
       */
      private void addUserData(WebRequest theRequest, URLConnection theConnection)
                        throws IOException
      {
          // If no user data, then exit
          if (theRequest.getUserData() == null)
          {
              return;
          }
  
          OutputStream out = getConnectionStream(theConnection);
          InputStream stream = theRequest.getUserData();
  
          byte[] buffer = new byte[2048];
          int length;
  
          while ((length = stream.read(buffer)) != -1)
          {
              out.write(buffer, 0, length);
          }
  
          out.close();
      }
  
      /**
       * Add the HTTP parameters that need to be passed in the request body.
       *
       * @param theRequest the request containing all data to pass to the server
       *        redirector.
       * @param theConnection the HTTP connection
       */
      private void addParametersPost(WebRequest theRequest, 
                                     URLConnection theConnection)
      {
          // If no parameters, then exit
          if (!theRequest.getParameterNamesPost().hasMoreElements())
          {
              return;
          }
  
          PrintWriter out = new PrintWriter(getConnectionStream(theConnection));
          StringBuffer queryString = new StringBuffer();
          Enumeration keys = theRequest.getParameterNamesPost();
  
          if (keys.hasMoreElements())
          {
              String key = (String) keys.nextElement();
              String[] values = theRequest.getParameterValuesPost(key);
  
              queryString.append(key);
              queryString.append('=');
              queryString.append(URLEncoder.encode(values[0]));
  
              for (int i = 1; i < values.length; i++)
              {
                  queryString.append('&');
                  queryString.append(key);
                  queryString.append('=');
                  queryString.append(URLEncoder.encode(values[i]));
              }
          }
  
          while (keys.hasMoreElements())
          {
              String key = (String) keys.nextElement();
              String[] values = theRequest.getParameterValuesPost(key);
  
              for (int i = 0; i < values.length; i++)
              {
                  queryString.append('&');
                  queryString.append(key);
                  queryString.append('=');
                  queryString.append(URLEncoder.encode(values[i]));
              }
          }
  
          out.print(queryString.toString());
          out.close();
      }
  
      /**
       * @param theConnection the HTTP connection
       * @return an output stream to write in the request body
       */
      private OutputStream getConnectionStream(URLConnection theConnection)
      {
          OutputStream out;
  
          try
          {
              out = theConnection.getOutputStream();
          }
          catch (IOException e)
          {
              // Cannot connect to server, try to explain why ...
              String reason = "Cannot connect to URL [" + theConnection.getURL()
                  + "]. Reason : [" + e.getMessage() + "]\r\n";
              reason += "Possible reasons :\r\n";
              reason += "\t- The server is not running,\r\n";
              reason += ("\t- The server redirector is not correctly mapped in " 
                  + "web.xml,\r\n");
              reason += "\t- Something else ... !";
  
              throw new ChainedRuntimeException(reason);
          }
  
          return out;
      }
  
      /**
       * Add the Headers to the request.
       *
       * @param theRequest the request containing all data to pass to the server
       *        redirector.
       * @param theConnection the HTTP connection
       */
      private void addHeaders(WebRequest theRequest, URLConnection theConnection)
      {
          Enumeration keys = theRequest.getHeaderNames();
  
          while (keys.hasMoreElements())
          {
              String key = (String) keys.nextElement();
              String[] values = theRequest.getHeaderValues(key);
  
              // As the URLConnection.setRequestProperty will overwrite any
              // property already set we have to regroup the multi valued
              // headers into a single header name entry.
              // Question: Is this an implementation bug ? It seems because
              // on the server side, I cannot use the request.getHeaders() (it
              // only returns a single header).
              StringBuffer fullHeaderValue = new StringBuffer(values[0]);
  
              for (int i = 1; i < values.length; i++)
              {
                  fullHeaderValue.append("," + values[i]);
              }
  
              theConnection.setRequestProperty(key, fullHeaderValue.toString());
          }
      }
  }
  
  
  1.1                  jakarta-cactus/framework/src/java/share/org/apache/cactus/client/connector/DefaultHttpClient.java
  
  Index: DefaultHttpClient.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 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", "Cactus" and "Apache Software
   *    Foundation" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.cactus.client.connector;
  
  import java.net.HttpURLConnection;
  
  import org.apache.cactus.HttpServiceDefinition;
  import org.apache.cactus.ServiceEnumeration;
  import org.apache.cactus.WebRequest;
  import org.apache.cactus.WebResponse;
  import org.apache.cactus.WebTestResult;
  import org.apache.cactus.client.AssertionFailedErrorWrapper;
  import org.apache.cactus.client.ParsingException;
  import org.apache.cactus.client.ServletExceptionWrapper;
  import org.apache.cactus.client.WebTestResultParser;
  import org.apache.cactus.configuration.WebConfiguration;
  import org.apache.cactus.util.ChainedRuntimeException;
  import org.apache.cactus.util.IoUtil;
  
  /**
   * Performs the steps necessary to run a test. It involves
   * opening a first HTTP connection to a server redirector, reading the output
   * stream and then opening a second HTTP connection to retrieve the test 
   * result.
   *
   * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
   * @author <a href="mailto:Jason.Robertson@acs-inc.com">Jason Robertson</a>
   *
   * @version $Id: DefaultHttpClient.java,v 1.1 2003/02/22 20:24:15 vmassol Exp $
   */
  public class DefaultHttpClient
  {
      /**
       * Cactus configuration.
       */
      protected WebConfiguration configuration;
      
      /**
       * Initialize the Http client.
       * 
       * @param theConfiguration the Cactus configuration
       */
      public DefaultHttpClient(WebConfiguration theConfiguration)
      {
          this.configuration = theConfiguration;
      }
  
      /**
       * Calls the test method indirectly by calling the Redirector servlet and
       * then open a second HTTP connection to retrieve the test results.
       *
       * @param theRequest the request containing all data to pass to the
       *        redirector servlet.
       *
       * @return the <code>HttpURLConnection</code> that contains the HTTP
       *         response when the test was called.
       *
       * @exception Throwable if an error occured in the test method or in the
       *            redirector servlet.
       */
      public HttpURLConnection doTest(WebRequest theRequest) throws Throwable
      {
          // Open the first connection to the redirector to execute the test on
          // the server side
          HttpURLConnection connection = callRunTest(theRequest);
  
          // Open the second connection to get the test results
          WebTestResult result = null;
  
          try
          {
              result = callGetResult(theRequest);
          }
          catch (ParsingException e)
          {
              throw new ChainedRuntimeException("Failed to get the test "
                  + "results. This is probably due to an error that happened on "
                  + "the server side when trying to execute the tests. Here is "
                  + "what was returned by the server : ["
                  + new WebResponse(theRequest, connection).getText() + "]", e);
          }
  
          // Check if the returned result object returned contains an error or
          // not. If yes, we need to raise an exception so that the JUnit
          // framework can catch it
          if (result.hasException())
          {
              // Wrap the exception message and stack trace into a fake
              // exception class with overloaded <code>printStackTrace()</code>
              // methods so that when JUnit calls this method it will print the
              // stack trace that was set on the server side.
              // If the error was an AssertionFailedError then we use an instance
              // of AssertionFailedErrorWrapper (so that JUnit recognize it is
              // an AssertionFailedError exception and print it differently in
              // it's runner console). Otherwise we use an instance of
              // ServletExceptionWrapper.
              if (result.getExceptionClassName().equals(
                  "junit.framework.AssertionFailedError"))
              {
                  throw new AssertionFailedErrorWrapper(
                      result.getExceptionMessage(), 
                      result.getExceptionClassName(), 
                      result.getExceptionStackTrace());
              }
              else
              {
                  throw new ServletExceptionWrapper(
                      result.getExceptionMessage(), 
                      result.getExceptionClassName(), 
                      result.getExceptionStackTrace());
              }
          }
  
          return connection;
      }
  
      /**
       * Execute the test by calling the redirector.
       *
       * @param theRequest the request containing all data to pass to the
       *        redirector servlet.
       * @return the <code>HttpURLConnection</code> that contains the HTTP
       *         response when the test was called.
       *
       * @exception Throwable if an error occured in the test method or in the
       *            redirector servlet.
       */
      private HttpURLConnection callRunTest(WebRequest theRequest) 
          throws Throwable
      {
          // Specify the service to call on the redirector side
          theRequest.addParameter(HttpServiceDefinition.SERVICE_NAME_PARAM, 
              ServiceEnumeration.CALL_TEST_SERVICE.toString(), 
              WebRequest.GET_METHOD);
  
          // Open the first connection to the redirector to execute the test on
          // the server side
          ConnectionHelper helper = ConnectionHelperFactory.getConnectionHelper(
              this.configuration.getRedirectorURL(theRequest), 
              this.configuration);
  
          HttpURLConnection connection = helper.connect(theRequest);
  
          // Wrap the connection to ensure that all servlet output is read
          // before we ask for results
          connection = new AutoReadHttpURLConnection(connection);
  
          // Trigger the transfer of data
          connection.getInputStream();
  
          return connection;
      }
  
      /**
       * Get the test result from the redirector.
       *
       * @param theOriginalRequest the request that was used to run the test
       * @return the result that was returned by the redirector.
       *
       * @exception Throwable if an error occured in the test method or in the
       *            redirector servlet.
       */
      private WebTestResult callGetResult(WebRequest theOriginalRequest) 
          throws Throwable
      {
          WebRequest resultsRequest = new WebRequest(this.configuration);
  
          resultsRequest.addParameter(HttpServiceDefinition.SERVICE_NAME_PARAM, 
              ServiceEnumeration.GET_RESULTS_SERVICE.toString(), 
              WebRequest.GET_METHOD);
  
          // Use the same redirector as was used by the original request
          resultsRequest.setRedirectorName(
              theOriginalRequest.getRedirectorName());
           
          // Add authentication details
          if (theOriginalRequest.getAuthentication() != null)
          {
              resultsRequest.setAuthentication(
                  theOriginalRequest.getAuthentication());
          }
  
          // Open the second connection to get the test results
          ConnectionHelper helper = ConnectionHelperFactory.getConnectionHelper(
              this.configuration.getRedirectorURL(resultsRequest),
              this.configuration);
  
          HttpURLConnection resultConnection = helper.connect(resultsRequest);
  
          // Read the test result
          WebTestResultParser parser = new WebTestResultParser();
          WebTestResult result = parser.parse(
              IoUtil.getText(resultConnection.getInputStream(), "UTF-8"));
  
          return result;
      }
  }
  
  
  1.1                  jakarta-cactus/framework/src/java/share/org/apache/cactus/client/connector/AbstractConnectionHelper.java
  
  Index: AbstractConnectionHelper.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 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", "Cactus" and "Apache Software
   *    Foundation" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.cactus.client.connector;
  
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.net.URLEncoder;
  
  import java.util.Enumeration;
  import java.util.Vector;
  
  import org.apache.cactus.Cookie;
  import org.apache.cactus.WebRequest;
  import org.apache.cactus.client.ClientException;
  import org.apache.commons.httpclient.Header;
  
  /**
   * Common helper methods for implementing <code>ConnectionHelper</code>. These
   * methods are common to any implementation.
   *
   * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
   *
   * @version $Id: AbstractConnectionHelper.java,v 1.1 2003/02/22 20:24:15 vmassol Exp $
   */
  public abstract class AbstractConnectionHelper
      implements ConnectionHelper
  {
      /**
       * Add the HTTP parameters that need to be passed in the query string of
       * the URL.
       *
       * @param theRequest the request containing all data to pass to the server
       *        redirector.
       * @param theURL the URL used to connect to the server redirector.
       * @return the new URL
       * @exception MalformedURLException if the URL is malformed
       */
      protected URL addParametersGet(WebRequest theRequest, URL theURL)
          throws MalformedURLException
      {
          // If no parameters, then exit
          if (!theRequest.getParameterNamesGet().hasMoreElements())
          {
              return theURL;
          }
  
          StringBuffer queryString = new StringBuffer();
  
          Enumeration keys = theRequest.getParameterNamesGet();
  
          if (keys.hasMoreElements())
          {
              String key = (String) keys.nextElement();
              String[] values = theRequest.getParameterValuesGet(key);
  
              queryString.append(key);
              queryString.append('=');
              queryString.append(URLEncoder.encode(values[0]));
  
              for (int i = 1; i < values.length; i++)
              {
                  queryString.append('&');
                  queryString.append(key);
                  queryString.append('=');
                  queryString.append(URLEncoder.encode(values[i]));
              }
          }
  
          while (keys.hasMoreElements())
          {
              String key = (String) keys.nextElement();
              String[] values = theRequest.getParameterValuesGet(key);
  
              for (int i = 0; i < values.length; i++)
              {
                  queryString.append('&');
                  queryString.append(key);
                  queryString.append('=');
                  queryString.append(URLEncoder.encode(values[i]));
              }
          }
  
          String file = theURL.getFile();
  
          // Remove the trailing "/" if there is one
          if (file.endsWith("/"))
          {
              file = file.substring(0, file.length() - 1);
          }
  
          if (theURL.toString().indexOf("?") > 0)
          {
              file = file + "&" + queryString.toString();
          }
          else
          {
              file = file + "?" + queryString.toString();
          }
  
          return new URL(theURL.getProtocol(), theURL.getHost(), 
              theURL.getPort(), file);
      }
  
      /**
       * @return the cookie string which will be added as a HTTP "Cookie" header
       *         or null if no cookie has been set
       * @param theRequest the request containing all data to pass to the server
       *        redirector.
       * @param theUrl the URL to connect to
       * @throws ClientException if an error occurred when creating the cookie
       *         string
       */
      public String getCookieString(WebRequest theRequest, URL theUrl)
          throws ClientException
      {
          // If no Cookies, then exit
          Vector cookies = theRequest.getCookies();
  
          if (!cookies.isEmpty())
          {
              // transform the Cactus cookies into HttpClient cookies
              org.apache.commons.httpclient.Cookie[] httpclientCookies = 
                  new org.apache.commons.httpclient.Cookie[cookies.size()];
  
              for (int i = 0; i < cookies.size(); i++)
              {
                  Cookie cactusCookie = (Cookie) cookies.elementAt(i);
  
                  // If no domain has been specified, use a default one
                  String domain;
  
                  if (cactusCookie.getDomain() == null)
                  {
                      domain = Cookie.getCookieDomain(theRequest, 
                          theUrl.getHost());
                  }
                  else
                  {
                      domain = cactusCookie.getDomain();
                  }
  
                  // If not path has been specified , use a default one
                  String path;
  
                  if (cactusCookie.getPath() == null)
                  {
                      path = Cookie.getCookiePath(theRequest, theUrl.getFile());
                  }
                  else
                  {
                      path = cactusCookie.getPath();
                  }
  
                  httpclientCookies[i] = new org.apache.commons.httpclient.Cookie(
                      domain, cactusCookie.getName(), cactusCookie.getValue());
  
                  httpclientCookies[i].setComment(cactusCookie.getComment());
                  httpclientCookies[i].setExpiryDate(
                      cactusCookie.getExpiryDate());
                  httpclientCookies[i].setPath(path);
                  httpclientCookies[i].setSecure(cactusCookie.isSecure());
              }
  
              // and create the cookie header to send
              Header cookieHeader = createCookieHeader(
                  Cookie.getCookieDomain(theRequest, theUrl.getHost()), 
                  Cookie.getCookiePath(theRequest, theUrl.getFile()), 
                  httpclientCookies);
  
              return cookieHeader.getValue();
          }
  
          return null;
      }
  
      /**
       * Create a HttpClient {@link Header} for cookies that matches
       * the domain and path.
       * 
       * @param theDomain the cookie domain to match
       * @param thePath the cookie path to match
       * @param theCookies the list of potential cookies
       * @return the HttpClient {@link Header} containing the matching 
       *         cookies
       * @throws ClientException if no cookie was matching the domain
       *         and path
       */
      private Header createCookieHeader(String theDomain, String thePath,
          org.apache.commons.httpclient.Cookie[] theCookies)
          throws ClientException
      {
          Header cookieHeader =
              org.apache.commons.httpclient.Cookie.createCookieHeader(
              theDomain, thePath, theCookies);
  
          if (cookieHeader == null)
          {
              throw new ClientException("Failed to create Cookie header for ["
                  + "domain = [" + theDomain + ", path = [" + thePath
                  + ", cookies = [" + theCookies + "]]. Turn on HttpClient "
                  + "logging for more information about the error"); 
          }
          
          return cookieHeader;
      }
  }
  
  
  1.1                  jakarta-cactus/framework/src/java/share/org/apache/cactus/client/connector/AutoReadHttpURLConnection.java
  
  Index: AutoReadHttpURLConnection.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 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", "Cactus" and "Apache Software
   *    Foundation" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.cactus.client.connector;
  
  import java.io.BufferedReader;
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.OutputStream;
  
  import java.net.HttpURLConnection;
  import java.net.ProtocolException;
  import java.net.URL;
  
  import java.security.Permission;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  /**
   * Wrapper class for the real <code>HttpURLConnection</code> to the test servlet
   * that reads the complete input stream into an internal buffer on
   * the first call to getInputStream(). This is to ensure that the test servlet
   * is not blocked on i/o when the test caller asks for the results.
   * <p>
   * The wrapper returns the buffered input stream from getInputStream and
   * delegates the rest of the calls.
   * <p>
   * This class is final so we don't have to provide access to protected instance
   * variables and methods of the wrapped connection.
   *
   * @author <a href="mailto:Bob.Davison@reuters.com">Bob Davison</a>
   * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
   *
   * @version $Id: AutoReadHttpURLConnection.java,v 1.1 2003/02/22 20:24:15 vmassol Exp $
   */
  final class AutoReadHttpURLConnection extends HttpURLConnection
  {
      /**
       * The logger
       */
      private static final Log LOGGER = 
          LogFactory.getLog(AutoReadHttpURLConnection.class);
  
      /**
       * Default size of array for copying data.
       */
      private static final int DEFAULT_CHUNK_SIZE = 16384;
  
      /**
       * The wrapped connection.
       */
      private HttpURLConnection delegate;
  
      /**
       * The read input stream.
       */
      private InputStream streamBuffer;
  
      /**
       * Constructs a an <code>AutoReadHttpURLConnection</code> object from an
       * <code>HttpURLConnection</code>.
       *
       * @param theConnection the original connection to wrap
       */
      AutoReadHttpURLConnection(HttpURLConnection theConnection)
      {
          super(null);
          this.delegate = theConnection;
      }
  
      /**
       * Returns an input stream containing the fully read contents of
       * the wrapped connection's input stream
       *
       * @return the input stream
       * @exception IOException if an error occurs when reading the input stream
       */
      public synchronized InputStream getInputStream() throws IOException
      {
          // Catch IOException to log the content of the error stream
          try
          {
              if (this.streamBuffer == null)
              {
                  LOGGER.debug("Original connection = " + this.delegate);
  
                  InputStream is = this.delegate.getInputStream();
  
                  this.streamBuffer = getBufferedInputStream(is);
              }
          }
          catch (IOException e)
          {
              logErrorStream(this.delegate.getErrorStream());
              throw e;
          }
  
          return this.streamBuffer;
      }
  
      /**
       * Logs the HTTP error stream (used to get more information when we fail
       * to read from the HTTP URL connection).
       *
       * @param theErrorStream the error stream containing the error description
       * @exception IOException if an error occurs when reading the input stream
       */
      private void logErrorStream(InputStream theErrorStream) throws IOException
      {
          if (theErrorStream != null)
          {
              // Log content of error stream
              BufferedReader errorStream = 
                  new BufferedReader(new InputStreamReader(theErrorStream));
              String buffer;
  
              while ((buffer = errorStream.readLine()) != null)
              {
                  LOGGER.debug("ErrorStream [" + buffer + "]");
              }
          }
      }
  
      /**
       * Fully read the HTTP Connection response stream until there is no
       * more bytes to read.
       *
       * @param theInputStream the input stream to fully read
       * @return the data read as a buffered input stream
       * @exception IOException if an error occurs when reading the input stream
       */
      private InputStream getBufferedInputStream(InputStream theInputStream)
          throws IOException
      {
          ByteArrayOutputStream os = 
              new ByteArrayOutputStream(DEFAULT_CHUNK_SIZE);
  
          copy(theInputStream, os);
  
          ByteArrayInputStream bais = new ByteArrayInputStream(os.toByteArray());
  
          return bais;
      }
  
      /**
       * Copies the input stream passed as parameter to the output stream also
       * passed as parameter. The full stream is read until there is no more
       * bytes to read.
       *
       * @param theInputStream the input stream to read from
       * @param theOutputStream the output stream to write to
       * @exception IOException if an error occurs when reading the input stream
       */
      private void copy(InputStream theInputStream, OutputStream theOutputStream)
          throws IOException
      {
          // Only copy if there are data to copy ... The problem is that not
          // all servers return a content-length header. If there is no header
          // getContentLength() returns -1. It seems to work and it seems
          // that all servers that return no content-length header also do
          // not block on read() operations !
          LOGGER.debug("Content-Length : [" + this.delegate.getContentLength()
              + "]");
  
          if (this.delegate.getContentLength() != 0)
          {
              byte[] buf = new byte[DEFAULT_CHUNK_SIZE];
              int count;
  
              while (-1 != (count = theInputStream.read(buf)))
              {
                  // log read data
                  printReadLogs(count, buf);
                  theOutputStream.write(buf, 0, count);
              }
          }
      }
  
      /**
       * Format log data read from socket for pretty printing (replaces
       * asc char 10 by "\r", asc char 13 by "\n").
       *
       * @param theCount the number of bytes read in the buffer
       * @param theBuffer the buffer containing the data to print
       */
      private void printReadLogs(int theCount, byte[] theBuffer)
      {
          // Log portion of read data and replace asc 10 by \r and asc
          // 13 by /n
          StringBuffer prefix = new StringBuffer();
  
          for (int i = 0; i < theCount; i++)
          {
              if (theBuffer[i] == 10)
              {
                  prefix.append("\\r");
              }
              else if (theBuffer[i] == 13)
              {
                  prefix.append("\\n");
              }
              else
              {
                  prefix.append((char) theBuffer[i]);
              }
          }
  
          LOGGER.debug("Read [" + theCount + "]: [" + prefix + "]");
      }
  
      // Delegated methods
  
      /**
       * @see java.net.HttpURLConnection#connect()
       */
      public void connect() throws IOException
      {
          this.delegate.connect();
      }
  
      /**
       * @see java.net.HttpURLConnection#getAllowUserInteraction()
       */
      public boolean getAllowUserInteraction()
      {
          return this.delegate.getAllowUserInteraction();
      }
  
      /**
       * @see java.net.HttpURLConnection#getContent()
       */
      public Object getContent() throws IOException
      {
          return this.delegate.getContent();
      }
  
      /**
       * @see java.net.HttpURLConnection#getContentEncoding()
       */
      public String getContentEncoding()
      {
          return this.delegate.getContentEncoding();
      }
  
      /**
       * @see java.net.HttpURLConnection#getContentLength()
       */
      public int getContentLength()
      {
          return this.delegate.getContentLength();
      }
  
      /**
       * @see java.net.HttpURLConnection#getContentType()
       */
      public String getContentType()
      {
          return this.delegate.getContentType();
      }
  
      /**
       * @see java.net.HttpURLConnection#getDate()
       */
      public long getDate()
      {
          return this.delegate.getDate();
      }
  
      /**
       * @see java.net.HttpURLConnection#getDefaultUseCaches()
       */
      public boolean getDefaultUseCaches()
      {
          return this.delegate.getDefaultUseCaches();
      }
  
      /**
       * @see java.net.HttpURLConnection#getDoInput()
       */
      public boolean getDoInput()
      {
          return this.delegate.getDoInput();
      }
  
      /**
       * @see java.net.HttpURLConnection#getDoOutput()
       */
      public boolean getDoOutput()
      {
          return this.delegate.getDoOutput();
      }
  
      /**
       * @see java.net.HttpURLConnection#getExpiration()
       */
      public long getExpiration()
      {
          return this.delegate.getExpiration();
      }
  
      /**
       * @see java.net.HttpURLConnection#getHeaderField(int)
       */
      public String getHeaderField(int thePosition)
      {
          return this.delegate.getHeaderField(thePosition);
      }
  
      /**
       * @see java.net.HttpURLConnection#getHeaderField(String)
       */
      public String getHeaderField(String theName)
      {
          return this.delegate.getHeaderField(theName);
      }
  
      /**
       * @see java.net.HttpURLConnection#getHeaderFieldDate(String, long)
       */
      public long getHeaderFieldDate(String theName, long theDefaultValue)
      {
          return this.delegate.getHeaderFieldDate(theName, theDefaultValue);
      }
  
      /**
       * @see java.net.HttpURLConnection#getHeaderFieldInt(String, int)
       */
      public int getHeaderFieldInt(String theName, int theDefaultValue)
      {
          return this.delegate.getHeaderFieldInt(theName, theDefaultValue);
      }
  
      /**
       * @see java.net.HttpURLConnection#getHeaderFieldKey(int)
       */
      public String getHeaderFieldKey(int thePosition)
      {
          return this.delegate.getHeaderFieldKey(thePosition);
      }
  
      /**
       * @see java.net.HttpURLConnection#getIfModifiedSince()
       */
      public long getIfModifiedSince()
      {
          return this.delegate.getIfModifiedSince();
      }
  
      /**
       * @see java.net.HttpURLConnection#getLastModified()
       */
      public long getLastModified()
      {
          return this.delegate.getLastModified();
      }
  
      /**
       * @see java.net.HttpURLConnection#getOutputStream()
       */
      public OutputStream getOutputStream() throws IOException
      {
          return this.delegate.getOutputStream();
      }
  
      /**
       * @see java.net.HttpURLConnection#getPermission()
       */
      public Permission getPermission() throws IOException
      {
          return this.delegate.getPermission();
      }
  
      /**
       * @see java.net.HttpURLConnection#getRequestProperty(String)
       */
      public String getRequestProperty(String theKey)
      {
          return this.delegate.getRequestProperty(theKey);
      }
  
      /**
       * @see java.net.HttpURLConnection#getURL()
       */
      public URL getURL()
      {
          return this.delegate.getURL();
      }
  
      /**
       * @see java.net.HttpURLConnection#getUseCaches()
       */
      public boolean getUseCaches()
      {
          return this.delegate.getUseCaches();
      }
  
      /**
       * @see java.net.HttpURLConnection#setAllowUserInteraction(boolean)
       */
      public void setAllowUserInteraction(boolean hasInteraction)
      {
          this.delegate.setAllowUserInteraction(hasInteraction);
      }
  
      /**
       * @see java.net.HttpURLConnection#setDefaultUseCaches(boolean)
       */
      public void setDefaultUseCaches(boolean isUsingDefaultCache)
      {
          this.delegate.setDefaultUseCaches(isUsingDefaultCache);
      }
  
      /**
       * @see java.net.HttpURLConnection#setDoInput(boolean)
       */
      public void setDoInput(boolean isInput)
      {
          this.delegate.setDoInput(isInput);
      }
  
      /**
       * @see java.net.HttpURLConnection#setDoOutput(boolean)
       */
      public void setDoOutput(boolean isOutput)
      {
          this.delegate.setDoOutput(isOutput);
      }
  
      /**
       * @see java.net.HttpURLConnection#setIfModifiedSince(long)
       */
      public void setIfModifiedSince(long isModifiedSince)
      {
          this.delegate.setIfModifiedSince(isModifiedSince);
      }
  
      /**
       * @see java.net.HttpURLConnection#setRequestProperty(String, String)
       */
      public void setRequestProperty(String theKey, String theValue)
      {
          this.delegate.setRequestProperty(theKey, theValue);
      }
  
      /**
       * @see java.net.HttpURLConnection#setUseCaches(boolean)
       */
      public void setUseCaches(boolean isUsingCaches)
      {
          this.delegate.setUseCaches(isUsingCaches);
      }
  
      /**
       * @see java.net.HttpURLConnection#toString()
       */
      public String toString()
      {
          return this.delegate.toString();
      }
  
      /**
       * @see java.net.HttpURLConnection#disconnect()
       */
      public void disconnect()
      {
          this.delegate.disconnect();
      }
  
      /**
       * @see java.net.HttpURLConnection#getErrorStream()
       */
      public InputStream getErrorStream()
      {
          return this.delegate.getErrorStream();
      }
  
      /**
       * @see java.net.HttpURLConnection#getRequestMethod()
       */
      public String getRequestMethod()
      {
          return this.delegate.getRequestMethod();
      }
  
      /**
       * @see java.net.HttpURLConnection#getResponseCode()
       */
      public int getResponseCode() throws IOException
      {
          return this.delegate.getResponseCode();
      }
  
      /**
       * @see java.net.HttpURLConnection#getResponseMessage()
       */
      public String getResponseMessage() throws IOException
      {
          return this.delegate.getResponseMessage();
      }
  
      /**
       * @see java.net.HttpURLConnection#setRequestMethod(String)
       */
      public void setRequestMethod(String theMethod) throws ProtocolException
      {
          this.delegate.setRequestMethod(theMethod);
      }
  
      /**
       * @see java.net.HttpURLConnection#usingProxy()
       */
      public boolean usingProxy()
      {
          return this.delegate.usingProxy();
      }
  }
  
  
  1.1                  jakarta-cactus/framework/src/java/share/org/apache/cactus/client/connector/ConnectionHelper.java
  
  Index: ConnectionHelper.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 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", "Cactus" and "Apache Software
   *    Foundation" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.cactus.client.connector;
  
  import java.net.HttpURLConnection;
  
  import org.apache.cactus.WebRequest;
  
  /**
   * Helper class to open an HTTP connection to the server redirector and pass
   * to it HTTP parameters, Cookies and HTTP headers. It enables different
   * possible implementations of an HTTP connection (ex: using the JDK
   * <code>HttpURLConnection</code> or using Jakarta HttpClient).
   *
   * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
   *
   * @version $Id: ConnectionHelper.java,v 1.1 2003/02/22 20:24:15 vmassol Exp $
   */
  public interface ConnectionHelper
  {
      /**
       * Connects to the Cactus Redirector using HTTP.
       *
       * @param theRequest the request containing all data to pass to the
       *        server redirector.
       * @return the HTTP Connection used to connect to the redirector.
       * @exception Throwable if an unexpected error occured
       */
      HttpURLConnection connect(WebRequest theRequest) throws Throwable;
  }
  
  
  1.1                  jakarta-cactus/framework/src/java/share/org/apache/cactus/client/connector/HttpClientConnectionHelper.java
  
  Index: HttpClientConnectionHelper.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 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", "Cactus" and "Apache Software
   *    Foundation" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   */
  package org.apache.cactus.client.connector;
  
  import java.io.IOException;
  
  import java.net.HttpURLConnection;
  import java.net.URL;
  
  import java.util.Enumeration;
  
  import org.apache.cactus.WebRequest;
  import org.apache.cactus.client.authentication.AbstractAuthentication;
  import org.apache.cactus.util.UrlUtil;
  import org.apache.commons.httpclient.HostConfiguration;
  import org.apache.commons.httpclient.HttpClient;
  import org.apache.commons.httpclient.methods.GetMethod;
  import org.apache.commons.httpclient.methods.PostMethod;
  import org.apache.commons.httpclient.protocol.Protocol;
  
  /**
   * Implementation of <code>ConnectionHelper</code> using Jakarta Commons
   * HttpClient.
   *
   * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
   *
   * @version $Id: HttpClientConnectionHelper.java,v 1.1 2003/02/22 20:24:15 vmassol Exp $
   */
  public class HttpClientConnectionHelper extends AbstractConnectionHelper
  {
      /**
       * The <code>HttpMethod</code> used to connect to the HTTP server. It is
       * either a <code>GetMethod</code> or a <code>PostMethod</code>.
       */
      private GetMethod method;
  
      /**
       * The URL that will be used for the HTTP connection.
       */
      private String url;
  
      /**
       * @param theURL the URL that will be used for the HTTP connection.
       */
      public HttpClientConnectionHelper(String theURL)
      {
          this.url = theURL;
      }
  
      /**
       * @see ConnectionHelper#connect(WebRequest)
       */
      public HttpURLConnection connect(WebRequest theRequest) throws Throwable
      {
          URL url = new URL(this.url);
  
          // Add Authentication headers, if necessary. This is the first
          // step to allow authentication to add extra headers, HTTP parameters,
          // etc.
          AbstractAuthentication authentication = theRequest.getAuthentication();
  
          if (authentication != null)
          {
              authentication.configure(theRequest);
          }
  
          // Add the parameters that need to be passed as part of the URL
          url = addParametersGet(theRequest, url);
  
          // Choose the method that we will use to post data :
          // - If at least one parameter is to be sent in the request body, then
          //   we are doing a POST.
          // - If user data has been specified, then we are doing a POST
          if (theRequest.getParameterNamesPost().hasMoreElements()
              || (theRequest.getUserData() != null))
          {
              this.method = new PostMethod();
          }
          else
          {
              this.method = new GetMethod();
          }
  
          this.method.setUseDisk(false);
          this.method.setFollowRedirects(false);
          this.method.setPath(UrlUtil.getPath(url));
          this.method.setQueryString(UrlUtil.getQuery(url));
  
          // Sets the content type
          this.method.setRequestHeader("Content-type", 
              theRequest.getContentType());
  
          // Add the other header fields
          addHeaders(theRequest);
  
          // Add the cookies
          String cookieString = getCookieString(theRequest, url);
  
          if (cookieString != null)
          {
              this.method.addRequestHeader("Cookie", cookieString);
          }
  
          // Add the POST parameters if no user data has been specified (user data
          // overried post parameters)
          if (theRequest.getUserData() != null)
          {
              addUserData(theRequest);
          }
          else
          {
              addParametersPost(theRequest);
          }
  
          // Open the connection and get the result
          HttpClient client = new HttpClient();
          HostConfiguration hostConfiguration = new HostConfiguration();
          hostConfiguration.setHost(url.getHost(), url.getPort(),
              Protocol.getProtocol(url.getProtocol()));
          client.executeMethod(hostConfiguration, this.method);
  
          // Wrap the HttpClient method in a java.net.HttpURLConnection object
          return new org.apache.commons.httpclient.util.HttpURLConnection(
              this.method, url);
      }
      
      /**
       * Add the HTTP parameters that need to be passed in the request body.
       *
       * @param theRequest the request containing all data to pass to the server
       *        redirector.
       */
      private void addParametersPost(WebRequest theRequest)
      {
          // If no parameters, then exit
          if (!theRequest.getParameterNamesPost().hasMoreElements())
          {
              return;
          }
  
          Enumeration keys = theRequest.getParameterNamesPost();
          while (keys.hasMoreElements())
          {
              String key = (String) keys.nextElement();
              String[] values = theRequest.getParameterValuesPost(key);
  
              for (int i = 0; i < values.length; i++)
              {
                  ((PostMethod) this.method).addParameter(key, values[i]);
              }
          }
      }
  
      /**
       * Add the Headers to the request.
       *
       * @param theRequest the request containing all data to pass to the server
       *        redirector.
       */
      private void addHeaders(WebRequest theRequest)
      {
          Enumeration keys = theRequest.getHeaderNames();
  
          while (keys.hasMoreElements())
          {
              String key = (String) keys.nextElement();
              String[] values = theRequest.getHeaderValues(key);
  
              StringBuffer fullHeaderValue = new StringBuffer(values[0]);
  
              for (int i = 1; i < values.length; i++)
              {
                  fullHeaderValue.append("," + values[i]);
              }
  
              this.method.addRequestHeader(key, fullHeaderValue.toString());
          }
      }
  
      /**
       * Add user data in the request body.
       *
       * @param theRequest the request containing all data to pass to the server
       *        redirector.
       * @exception IOException if we fail to read the user data
       */
      private void addUserData(WebRequest theRequest) throws IOException
      {
          // If no user data, then exit
          if (theRequest.getUserData() == null)
          {
              return;
          }
  
          ((PostMethod) this.method).setRequestBody(theRequest.getUserData());
      }
  }
  
  
  
  1.9       +2 -2      jakarta-cactus/framework/src/java/share/org/apache/cactus/client/authentication/FormAuthentication.java
  
  Index: FormAuthentication.java
  ===================================================================
  RCS file: /home/cvs/jakarta-cactus/framework/src/java/share/org/apache/cactus/client/authentication/FormAuthentication.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- FormAuthentication.java	22 Feb 2003 11:31:49 -0000	1.8
  +++ FormAuthentication.java	22 Feb 2003 20:24:15 -0000	1.9
  @@ -61,8 +61,8 @@
   import java.net.URL;
   
   import org.apache.cactus.WebRequest;
  -import org.apache.cactus.client.ConnectionHelper;
  -import org.apache.cactus.client.ConnectionHelperFactory;
  +import org.apache.cactus.client.connector.ConnectionHelper;
  +import org.apache.cactus.client.connector.ConnectionHelperFactory;
   import org.apache.cactus.configuration.WebConfiguration;
   import org.apache.cactus.util.ChainedRuntimeException;
   import org.apache.commons.logging.Log;
  
  
  
  1.2       +3 -3      jakarta-cactus/framework/src/java/share/org/apache/cactus/configuration/Configuration.java
  
  Index: Configuration.java
  ===================================================================
  RCS file: /home/cvs/jakarta-cactus/framework/src/java/share/org/apache/cactus/configuration/Configuration.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Configuration.java	22 Feb 2003 11:31:49 -0000	1.1
  +++ Configuration.java	22 Feb 2003 20:24:15 -0000	1.2
  @@ -71,8 +71,8 @@
       String getContextURL();
   
       /**
  -     * @return the {@link org.apache.cactus.client.ConnectionHelper} classname
  -     *         to use for opening the HTTP connection
  +     * @return the {@link org.apache.cactus.client.connector.ConnectionHelper} 
  +     * classname to use for opening the HTTP connection
        */
       String getConnectionHelper();
   
  
  
  
  1.2       +6 -5      jakarta-cactus/framework/src/java/share/org/apache/cactus/configuration/BaseConfiguration.java
  
  Index: BaseConfiguration.java
  ===================================================================
  RCS file: /home/cvs/jakarta-cactus/framework/src/java/share/org/apache/cactus/configuration/BaseConfiguration.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- BaseConfiguration.java	22 Feb 2003 11:31:49 -0000	1.1
  +++ BaseConfiguration.java	22 Feb 2003 20:24:15 -0000	1.2
  @@ -64,7 +64,7 @@
   import java.util.PropertyResourceBundle;
   import java.util.ResourceBundle;
   
  -import org.apache.cactus.client.HttpClientConnectionHelper;
  +import org.apache.cactus.client.connector.HttpClientConnectionHelper;
   import org.apache.cactus.util.ChainedRuntimeException;
   import org.apache.cactus.util.ClassLoaderUtils;
   
  @@ -110,7 +110,8 @@
           "cactus.connectionHelper.classname";
   
       /**
  -     * Default {@link org.apache.cactus.client.ConnectionHelper} to use.
  +     * Default {@link org.apache.cactus.client.connector.ConnectionHelper} to 
  +     * use.
        */
       public static final String DEFAULT_CACTUS_CONNECTION_HELPER_CLASSNAME = 
           HttpClientConnectionHelper.class.getName();
  @@ -212,8 +213,8 @@
       }
   
       /**
  -     * @return the {@link org.apache.cactus.client.ConnectionHelper} classname
  -     *         to use for opening the HTTP connection
  +     * @return the {@link org.apache.cactus.client.connector.ConnectionHelper} 
  +     * classname to use for opening the HTTP connection
        */
       public String getConnectionHelper()
       {
  
  
  
  1.3       +2 -2      jakarta-cactus/framework/src/java/share/org/apache/cactus/AbstractWebServerTestCase.java
  
  Index: AbstractWebServerTestCase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-cactus/framework/src/java/share/org/apache/cactus/AbstractWebServerTestCase.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- AbstractWebServerTestCase.java	22 Feb 2003 11:31:49 -0000	1.2
  +++ AbstractWebServerTestCase.java	22 Feb 2003 20:24:16 -0000	1.3
  @@ -61,7 +61,7 @@
   import java.lang.reflect.Modifier;
   import java.net.HttpURLConnection;
   
  -import org.apache.cactus.client.DefaultHttpClient;
  +import org.apache.cactus.client.connector.DefaultHttpClient;
   import org.apache.cactus.configuration.WebConfiguration;
   import org.apache.commons.logging.LogFactory;
   
  
  
  
  1.15      +3 -3      jakarta-cactus/framework/src/java/share/org/apache/cactus/WebRequest.java
  
  Index: WebRequest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-cactus/framework/src/java/share/org/apache/cactus/WebRequest.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- WebRequest.java	22 Feb 2003 11:31:49 -0000	1.14
  +++ WebRequest.java	22 Feb 2003 20:24:16 -0000	1.15
  @@ -60,9 +60,9 @@
   import java.util.StringTokenizer;
   
   import org.apache.cactus.client.ClientException;
  -import org.apache.cactus.client.ConnectionHelper;
  -import org.apache.cactus.client.ConnectionHelperFactory;
   import org.apache.cactus.client.WebResponseObjectFactory;
  +import org.apache.cactus.client.connector.ConnectionHelper;
  +import org.apache.cactus.client.connector.ConnectionHelperFactory;
   import org.apache.cactus.configuration.WebConfiguration;
   import org.apache.cactus.util.ChainedRuntimeException;
   
  
  
  
  1.11      +2 -2      jakarta-cactus/framework/src/java/j2ee13/org/apache/cactus/util/FilterConfiguration.java
  
  Index: FilterConfiguration.java
  ===================================================================
  RCS file: /home/cvs/jakarta-cactus/framework/src/java/j2ee13/org/apache/cactus/util/FilterConfiguration.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- FilterConfiguration.java	3 Jan 2003 15:43:22 -0000	1.10
  +++ FilterConfiguration.java	22 Feb 2003 20:24:16 -0000	1.11
  @@ -74,7 +74,7 @@
           "cactus.filterRedirectorName";
   
       /**
  -     * @see WebConfiguration#getDefaultRedirectorName()
  +     * @see AbstractWebConfiguration#getDefaultRedirectorName()
        */
       public String getDefaultRedirectorName()
       {
  
  
  

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