You are viewing a plain text version of this content. The canonical link for it is here.
Posted to soap-dev@xml.apache.org by sn...@apache.org on 2002/10/04 21:50:20 UTC

cvs commit: xml-soap/java/src/org/apache/soap/util/net HTTPUtils.java SSLUtils.java

snichol     2002/10/04 12:50:20

  Modified:    java/docs changes.html intro.html
               java/src/org/apache/soap/transport/http
                        SOAPHTTPConnection.java
               java/src/org/apache/soap/util/net HTTPUtils.java
                        SSLUtils.java
  Added:       java/src/org/apache/soap/util MutableBoolean.java
  Log:
  Read HTTP[S] proxy information from system properties if not explicitly
  specified.
  
  Revision  Changes    Path
  1.47      +5 -1      xml-soap/java/docs/changes.html
  
  Index: changes.html
  ===================================================================
  RCS file: /home/cvs/xml-soap/java/docs/changes.html,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- changes.html	16 Sep 2002 15:26:25 -0000	1.46
  +++ changes.html	4 Oct 2002 19:50:19 -0000	1.47
  @@ -72,7 +72,9 @@
         <li>Add a document/literal serialization option.  This is intended for use
         by SOAP clients that need to communicate with services that use
         document/literal encoding.  Parameters will be serialized using document/literal
  -      style.  Return values must be mapped by parameter name (the existing
  +      style.  (No xsi:type is emitted; therefore, this does not work with
  +      schemas specifying xsd:anyType for a parameter.)
  +      Return values must be mapped by parameter name (the existing
         interop hack).</li>
         <li>Support gzip encoding for HTTP.  This is enabled through SOAPContext
         for clients and the deployment descriptor for services.</li>
  @@ -86,6 +88,8 @@
         for each compound type being deserialized.  Conversely, it can write a
         Map similary, providing an alternative to the default Apache SOAP serialization
         of Maps.</li>
  +      <li>Read HTTP[S] proxy information from system properties if not explicitly
  +      specified.</li>
       </ul>
     </li>
   </ul>
  
  
  
  1.13      +1 -0      xml-soap/java/docs/intro.html
  
  Index: intro.html
  ===================================================================
  RCS file: /home/cvs/xml-soap/java/docs/intro.html,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- intro.html	13 Sep 2002 14:11:41 -0000	1.12
  +++ intro.html	4 Oct 2002 19:50:19 -0000	1.13
  @@ -108,6 +108,7 @@
       <li>multi-dimensional arrays (5.4.2), arrays of arrays (5.4.2),
           partially transmitted arrays (5.4.2.1), sparse arrays (5.4.2.2)</li>
       <li>root attribute (5.6)</li>
  +    <li>input/output and output parameters</li>
   </ul>
   
   <p>The following limitations on
  
  
  
  1.27      +2 -15     xml-soap/java/src/org/apache/soap/transport/http/SOAPHTTPConnection.java
  
  Index: SOAPHTTPConnection.java
  ===================================================================
  RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/transport/http/SOAPHTTPConnection.java,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- SOAPHTTPConnection.java	5 Sep 2002 16:50:52 -0000	1.26
  +++ SOAPHTTPConnection.java	4 Oct 2002 19:50:19 -0000	1.27
  @@ -201,19 +201,6 @@
       return responseCopy;
     }
     
  -  private static String encodeAuth(String userName, String password)
  -    throws SOAPException
  -  {
  -    try
  -    {
  -      return Base64.encode((userName + ":" + password).getBytes("8859_1"));
  -    }
  -    catch (UnsupportedEncodingException e)
  -    {
  -      throw new SOAPException (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
  -    }
  -  }
  -
     /**
      * Indicate whether to maintain HTTP sessions.
      */
  @@ -373,13 +360,13 @@
         if (userName != null) {
           // add the Authorization header for Basic authentication
           headers.put (Constants.HEADER_AUTHORIZATION,
  -                     "Basic " + encodeAuth(userName, password));
  +                     "Basic " + HTTPUtils.encodeAuth(userName, password));
   
         }
         if (proxyUserName != null) {
           // add the Proxy-Authorization header for proxy authentication
           headers.put (Constants.HEADER_PROXY_AUTHORIZATION,
  -                    "Basic " + encodeAuth(proxyUserName, proxyPassword));
  +                    "Basic " + HTTPUtils.encodeAuth(proxyUserName, proxyPassword));
         }
   
         TransportMessage response;
  
  
  
  1.1                  xml-soap/java/src/org/apache/soap/util/MutableBoolean.java
  
  Index: MutableBoolean.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2000 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 acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "SOAP" 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 name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * 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 and was
   * originally based on software copyright (c) 2000, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.soap.util;
  
  /**
   * A boolean object that can have its value changed.
   *
   * @author Scott Nichol (snichol@computer.org)
   */
  public class MutableBoolean {
      private boolean value;
  
      public MutableBoolean(boolean value) {
          this.value = value;
      }
  
      public boolean getValue() {
          return value;
      }
  
      public void setValue(boolean value) {
          this.value = value;
      }
  
      public boolean equals(MutableBoolean mb) {
          return this.value == mb.value;
      }
  
      public String toString() {
          return value ? "true" : "false";
      }
  }
  
  
  
  1.32      +324 -48   xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java
  
  Index: HTTPUtils.java
  ===================================================================
  RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java,v
  retrieving revision 1.31
  retrieving revision 1.32
  diff -u -r1.31 -r1.32
  --- HTTPUtils.java	6 Sep 2002 17:02:59 -0000	1.31
  +++ HTTPUtils.java	4 Oct 2002 19:50:19 -0000	1.32
  @@ -57,18 +57,21 @@
   
   package org.apache.soap.util.net;
   
  -import java.net.*;
   import java.io.*;
  +import java.lang.reflect.*;
  +import java.net.*;
   import java.util.*;
   
  +import javax.mail.*;
  +import javax.mail.internet.*;
  +import javax.activation.*;
  +
   import org.apache.soap.*;
  +import org.apache.soap.encoding.soapenc.Base64;
   import org.apache.soap.rpc.*;
   import org.apache.soap.transport.*;
  +import org.apache.soap.util.MutableBoolean;
   import org.apache.soap.util.mime.*;
  -import javax.mail.*;
  -import javax.mail.internet.*;
  -import javax.activation.*;
  -import java.lang.reflect.*;
   
   /**
    * A bunch of utility stuff for doing HTTP things.
  @@ -80,6 +83,8 @@
    * @author Wouter Cloetens (wcloeten@raleigh.ibm.com)
    * @author Scott Nichol (snichol@computer.org)
    * @author Arek Wnukowski (apache@wnuko.demon.co.uk)
  + * @author Doug Davis (dug@us.ibm.com) (code lifted from Axis)
  + * @author Davanum Srinivas (dims@yahoo.com) (code lifted from Axis)
    */
   public class HTTPUtils {
     private static final String HTTP_VERSION = "1.0";
  @@ -89,47 +94,121 @@
     public  static final int    DEFAULT_OUTPUT_BUFFER_SIZE = 512;
   
     /**
  -   * This method either creates a socket or calls SSLUtils to
  +   * Encodes an HTTP Basic authentication username and password.
  +   */
  +  public static String encodeAuth(String userName, String password)
  +      throws SOAPException {
  +    try {
  +      return Base64.encode((userName + ":" + password).getBytes("8859_1"));
  +    } catch (UnsupportedEncodingException e) {
  +      throw new SOAPException (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
  +    }
  +  }
  +
  +  /**
  +   * This method calls SSLUtils to
      * create an SSLSocket.  It uses reflection to avoid a compile time
      * dependency on SSL.
      *
      * @author Chris Nelson
      */
  -  private static Socket buildSocket(URL url, int targetPort,
  -                                    String httpProxyHost, int httpProxyPort,
  -                                    Boolean tcpNoDelay)
  +  private static Socket getSecureSocket(String host, int port,
  +                                        String httpProxyHost, int httpProxyPort,
  +                                        Hashtable headers, Boolean tcpNoDelay)
           throws Exception {
  -      Socket s = null;
  -      String host = null;
  -      int port = targetPort;
  -      host = url.getHost();
  -
  -      if (url.getProtocol().equalsIgnoreCase("HTTPS")) {
  -          // Using reflection to avoid compile time dependencies
  -          Class SSLUtilsClass =
  -              Class.forName("org.apache.soap.util.net.SSLUtils");
  -          Class[] paramTypes = new Class[] {String.class, int.class, String.class, int.class};
  -          Method buildSSLSocket = SSLUtilsClass.getMethod(
  -              "buildSSLSocket", paramTypes);
  -          Object[] params = new Object[] {host, new Integer(port),
  -              httpProxyHost, new Integer(httpProxyPort)};
  -          s = (Socket)buildSSLSocket.invoke(null, params);
  -      } else {
  -          if (httpProxyHost != null) {
  -              host = httpProxyHost;
  -              port = httpProxyPort;
  -          }
  -          s = new Socket(host, port);
  +
  +    if (httpProxyHost == null) {
  +      String proxyHost = System.getProperty("https.proxyHost");
  +      String nonProxyHosts = System.getProperty("https.nonProxyHosts");
  +      boolean hostInNonProxyList = isHostInNonProxyList(host, nonProxyHosts);
  +      if (proxyHost != null && !hostInNonProxyList) {
  +        // use proxy from system values
  +        httpProxyHost = proxyHost;
  +        httpProxyPort = Integer.getInteger("https.proxyPort", HTTPS_DEFAULT_PORT).intValue();
  +        // TODO: build authentication string here instead of SSLUtils,
  +        //       but into headers, and pass headers to SSLUtils.
         }
  -      
  -      if (tcpNoDelay != null)
  -      {
  -        if (s != null) 
  -          s.setTcpNoDelay(tcpNoDelay.booleanValue());
  +    }
  +
  +    // Using reflection to avoid compile time dependencies
  +    Class SSLUtilsClass =
  +        Class.forName("org.apache.soap.util.net.SSLUtils");
  +    Class[] paramTypes = new Class[] {String.class, int.class,
  +                                      String.class, int.class,
  +                                      Boolean.class};
  +    Method buildSSLSocket = SSLUtilsClass.getMethod("buildSSLSocket", paramTypes);
  +    Object[] params = new Object[] {host, new Integer(port),
  +                                    httpProxyHost, new Integer(httpProxyPort),
  +                                    tcpNoDelay};
  +
  +    try {
  +      return (Socket) buildSSLSocket.invoke(null, params);
  +    } catch (Exception e) {
  +      StringBuffer msg = new StringBuffer(512);
  +      msg.append("Error SSL connecting to ").append(host).append(':').append(port);
  +      if (httpProxyHost != null)
  +        msg.append(" via ").append(httpProxyHost).append(':').append(httpProxyPort);
  +      msg.append(": ").append(e.toString());
  +      throw new SOAPException(Constants.FAULT_CODE_CLIENT, msg.toString(), e);
  +    }
  +  }
  +
  +  /**
  +   * This method either creates a socket.
  +   *
  +   * @author Chris Nelson
  +   */
  +  private static Socket getSocket(String host, int port,
  +                                  String httpProxyHost, int httpProxyPort,
  +                                  Hashtable headers, Boolean tcpNoDelay,
  +                                  MutableBoolean proxyUsed)
  +        throws Exception {
  +    Socket s = null;
  +
  +    if (httpProxyHost != null) {
  +      // user-specified values have precedence
  +      proxyUsed.setValue(true);
  +    } else {
  +      httpProxyHost = System.getProperty("http.proxyHost");
  +      if (httpProxyHost != null) {
  +        String nonProxyHosts = System.getProperty("http.nonProxyHosts");
  +        if (!isHostInNonProxyList(host, nonProxyHosts)) {
  +          // use proxy from system values
  +          httpProxyPort = Integer.getInteger("http.proxyPort", HTTP_DEFAULT_PORT).intValue();
  +          String proxyUserName = System.getProperty("http.proxyUser");
  +          if (proxyUserName != null) {
  +            String proxyPassword = System.getProperty("http.proxyPassword");
  +            headers.put(Constants.HEADER_PROXY_AUTHORIZATION,
  +                        "Basic " + encodeAuth(proxyUserName, proxyPassword));
  +          }
  +          proxyUsed.setValue(true);
  +        } else {
  +          proxyUsed.setValue(false);
  +        }
  +      } else {
  +        proxyUsed.setValue(false);
         }
  +    }
   
  -      return s;
  -   }
  +    try {
  +      if (proxyUsed.getValue())
  +        s = new Socket(httpProxyHost, httpProxyPort);
  +      else
  +        s = new Socket(host, port);
  +    } catch (Exception e) {
  +      StringBuffer msg = new StringBuffer(512);
  +      msg.append("Error connecting to ").append(host).append(':').append(port);
  +      if (proxyUsed.getValue())
  +        msg.append(" via ").append(httpProxyHost).append(':').append(httpProxyPort);
  +      msg.append(": ").append(e.toString());
  +      throw new SOAPException(Constants.FAULT_CODE_CLIENT, msg.toString(), e);
  +    }
  +    
  +    if (s != null && tcpNoDelay != null)
  +      s.setTcpNoDelay(tcpNoDelay.booleanValue());
  +
  +    return s;
  +  }
   
     /**
      * Obtain a header value from the table using a case insensitive search.
  @@ -276,19 +355,27 @@
                                         StringBuffer requestCopy,
                                         StringBuffer responseCopy)
         throws IOException, SOAPException {
  -      /* Open the connection */
  +
         OutputStream outStream = null;
         InputStream inStream = null;
         BufferedReader in = null;
  -      int port;
  -      Socket s;
  -      try {
  -          port = getPort(url);
  +      String host = url.getHost();
  +      int port = getPort(url);
  +      String protocol = url.getProtocol();
  +      Socket s = null;
  +      boolean proxyUsed = false;
   
  -          s = buildSocket(url, port, httpProxyHost, httpProxyPort, tcpNoDelay);
  -          if (url.getProtocol().equalsIgnoreCase("HTTPS")) {
  -             // Ignore proxy from now on. Buildsocket takes handles it
  -             httpProxyHost = null;
  +      /* Open the connection */
  +      try {
  +          if (protocol.equalsIgnoreCase("HTTPS")) {
  +              s = getSecureSocket(host, port, httpProxyHost, httpProxyPort,
  +                                  request.getHeaders(), tcpNoDelay);
  +          } else {
  +              MutableBoolean isProxyUsed = new MutableBoolean(proxyUsed);
  +              s = getSocket(host, port, httpProxyHost, httpProxyPort,
  +                                  request.getHeaders(), tcpNoDelay,
  +                                  isProxyUsed);
  +              proxyUsed = isProxyUsed.getValue();
             }
   
             if (timeout > 0)  // Should be redundant but not every JVM likes this
  @@ -298,6 +385,9 @@
             inStream = s.getInputStream ();
         }
         catch (Exception e) {
  +        if (e instanceof SOAPException)
  +          throw (SOAPException) e;
  +
           Throwable t = e;
   
           if (t instanceof InvocationTargetException) {
  @@ -309,14 +399,14 @@
         }
   
         /* Compute the Request URI */
  -      String URI = (httpProxyHost == null ? url.getFile() : url.toString());
  +      String URI = (!proxyUsed ? url.getFile() : url.toString());
         if (URI.length() == 0) URI = "/";
   
         /* Construct the HTTP header. */
         StringBuffer headerbuf = new StringBuffer(512);
         headerbuf.append(Constants.HEADER_POST).append(' ').append(URI)
             .append(" HTTP/").append(HTTP_VERSION).append("\r\n")
  -          .append(Constants.HEADER_HOST).append(": ").append(url.getHost())
  +          .append(Constants.HEADER_HOST).append(": ").append(host)
             .append(':').append(port)
             .append("\r\n")
             .append(Constants.HEADER_CONTENT_TYPE).append(": ")
  @@ -478,4 +568,190 @@
         s.close();
         return response;
     }
  +
  +    /**
  +     * Check if the specified host is in the list of non proxy hosts.
  +     *
  +     * @param host host name
  +     * @param nonProxyHosts string containing the list of non proxy hosts
  +     *
  +     * @return true/false
  +     */
  +    private static boolean isHostInNonProxyList(String host, String nonProxyHosts) {
  +        if ((nonProxyHosts == null) || (host == null)) {
  +            return false;
  +        }
  +        StringTokenizer tokenizer = new StringTokenizer(nonProxyHosts, "|");
  +
  +        while (tokenizer.hasMoreTokens()) {
  +            String pattern = tokenizer.nextToken();
  +
  +            if (match(pattern, host, false)) {
  +                return true;
  +            }
  +        }
  +        return false;
  +    }
  +
  +    /**
  +     * Matches a string against a pattern. The pattern contains two special
  +     * characters:
  +     * '*' which means zero or more characters,
  +     *
  +     * @param pattern the (non-null) pattern to match against
  +     * @param str     the (non-null) string that must be matched against the
  +     *                pattern
  +     * @param isCaseSensitive
  +     *
  +     * @return <code>true</code> when the string matches against the pattern,
  +     *         <code>false</code> otherwise.
  +     */
  +    private static boolean match(String pattern, String str,
  +                                 boolean isCaseSensitive) {
  +        char[] patArr = pattern.toCharArray();
  +        char[] strArr = str.toCharArray();
  +        int patIdxStart = 0;
  +        int patIdxEnd = patArr.length - 1;
  +        int strIdxStart = 0;
  +        int strIdxEnd = strArr.length - 1;
  +        char ch;
  +        boolean containsStar = false;
  +
  +        for (int i = 0; i < patArr.length; i++) {
  +            if (patArr[i] == '*') {
  +                containsStar = true;
  +                break;
  +            }
  +        }
  +        if (!containsStar) {
  +
  +            // No '*'s, so we make a shortcut
  +            if (patIdxEnd != strIdxEnd) {
  +                return false;        // Pattern and string do not have the same size
  +            }
  +            for (int i = 0; i <= patIdxEnd; i++) {
  +                ch = patArr[i];
  +                if (isCaseSensitive && (ch != strArr[i])) {
  +                    return false;    // Character mismatch
  +                }
  +                if (!isCaseSensitive
  +                        && (Character.toUpperCase(ch)
  +                        != Character.toUpperCase(strArr[i]))) {
  +                    return false;    // Character mismatch
  +                }
  +            }
  +            return true;             // String matches against pattern
  +        }
  +        if (patIdxEnd == 0) {
  +            return true;    // Pattern contains only '*', which matches anything
  +        }
  +
  +        // Process characters before first star
  +        while ((ch = patArr[patIdxStart]) != '*'
  +                && (strIdxStart <= strIdxEnd)) {
  +            if (isCaseSensitive && (ch != strArr[strIdxStart])) {
  +                return false;    // Character mismatch
  +            }
  +            if (!isCaseSensitive
  +                    && (Character.toUpperCase(ch)
  +                    != Character.toUpperCase(strArr[strIdxStart]))) {
  +                return false;    // Character mismatch
  +            }
  +            patIdxStart++;
  +            strIdxStart++;
  +        }
  +        if (strIdxStart > strIdxEnd) {
  +
  +            // All characters in the string are used. Check if only '*'s are
  +            // left in the pattern. If so, we succeeded. Otherwise failure.
  +            for (int i = patIdxStart; i <= patIdxEnd; i++) {
  +                if (patArr[i] != '*') {
  +                    return false;
  +                }
  +            }
  +            return true;
  +        }
  +
  +        // Process characters after last star
  +        while ((ch = patArr[patIdxEnd]) != '*' && (strIdxStart <= strIdxEnd)) {
  +            if (isCaseSensitive && (ch != strArr[strIdxEnd])) {
  +                return false;    // Character mismatch
  +            }
  +            if (!isCaseSensitive
  +                    && (Character.toUpperCase(ch)
  +                    != Character.toUpperCase(strArr[strIdxEnd]))) {
  +                return false;    // Character mismatch
  +            }
  +            patIdxEnd--;
  +            strIdxEnd--;
  +        }
  +        if (strIdxStart > strIdxEnd) {
  +
  +            // All characters in the string are used. Check if only '*'s are
  +            // left in the pattern. If so, we succeeded. Otherwise failure.
  +            for (int i = patIdxStart; i <= patIdxEnd; i++) {
  +                if (patArr[i] != '*') {
  +                    return false;
  +                }
  +            }
  +            return true;
  +        }
  +
  +        // process pattern between stars. padIdxStart and patIdxEnd point
  +        // always to a '*'.
  +        while ((patIdxStart != patIdxEnd) && (strIdxStart <= strIdxEnd)) {
  +            int patIdxTmp = -1;
  +
  +            for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
  +                if (patArr[i] == '*') {
  +                    patIdxTmp = i;
  +                    break;
  +                }
  +            }
  +            if (patIdxTmp == patIdxStart + 1) {
  +
  +                // Two stars next to each other, skip the first one.
  +                patIdxStart++;
  +                continue;
  +            }
  +
  +            // Find the pattern between padIdxStart & padIdxTmp in str between
  +            // strIdxStart & strIdxEnd
  +            int patLength = (patIdxTmp - patIdxStart - 1);
  +            int strLength = (strIdxEnd - strIdxStart + 1);
  +            int foundIdx = -1;
  +
  +            strLoop:
  +            for (int i = 0; i <= strLength - patLength; i++) {
  +                for (int j = 0; j < patLength; j++) {
  +                    ch = patArr[patIdxStart + j + 1];
  +                    if (isCaseSensitive
  +                            && (ch != strArr[strIdxStart + i + j])) {
  +                        continue strLoop;
  +                    }
  +                    if (!isCaseSensitive && (Character
  +                            .toUpperCase(ch) != Character
  +                            .toUpperCase(strArr[strIdxStart + i + j]))) {
  +                        continue strLoop;
  +                    }
  +                }
  +                foundIdx = strIdxStart + i;
  +                break;
  +            }
  +            if (foundIdx == -1) {
  +                return false;
  +            }
  +            patIdxStart = patIdxTmp;
  +            strIdxStart = foundIdx + patLength;
  +        }
  +
  +        // All characters in the string are used. Check if only '*'s are left
  +        // in the pattern. If so, we succeeded. Otherwise failure.
  +        for (int i = patIdxStart; i <= patIdxEnd; i++) {
  +            if (patArr[i] != '*') {
  +                return false;
  +            }
  +        }
  +        return true;
  +    }
   }
  
  
  
  1.7       +184 -164  xml-soap/java/src/org/apache/soap/util/net/SSLUtils.java
  
  Index: SSLUtils.java
  ===================================================================
  RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/util/net/SSLUtils.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- SSLUtils.java	1 Aug 2002 18:16:48 -0000	1.6
  +++ SSLUtils.java	4 Oct 2002 19:50:19 -0000	1.7
  @@ -64,173 +64,193 @@
   import java.security.*;
   
   /**
  - * A bunch of utility stuff for doing SSL things.
  + * A bunch of utility stuff for doing SSL things.  It is separate from
  + * HTTPUtils to avoid HTTPUtils from depending on SSL libraries at
  + * compile time (although everything in the class could be written to use
  + * reflection and accomplish the same thing.)
    *
    * @author Chris Nelson (cnelson@synchrony.net)
    * @author Phil Bohnenkamp (pbohnenkamp@centerpost.com)
  + * @author Scott Nichol (snichol@computer.org)
    */
   public class SSLUtils {
  -        static String tunnelHost;
  -        static int tunnelPort;
  -	
  -	/** This method builds an SSL socket, after auto-starting SSL */
  -	public static Socket buildSSLSocket(String host, int port, String httpProxyHost,
  -                                            int httpProxyPort)
  -		throws IOException, UnknownHostException
  -	{
  -           SSLSocket sslSocket =  null;
  -           SSLSocketFactory factory =
  -              (SSLSocketFactory)SSLSocketFactory.getDefault();
  -
  -           // Determine if a proxy should be used. Use system properties if set
  -           // Otherwise use http proxy. If neither is set, dont use a proxy
  -           tunnelHost = System.getProperty("https.proxyHost");
  -           tunnelPort = Integer.getInteger("https.proxyPort", 80).intValue();
  -
  -           if (tunnelHost==null) {
  -              // Try to use http proxy instead
  -              tunnelHost = httpProxyHost;
  -              tunnelPort = httpProxyPort;
  -           }
  -
  -           /*
  -           System.out.println("https proxyHost=" + tunnelHost +
  -                              " proxyPort=" + tunnelPort +
  -                              " host=" + host +
  -                              " port=" + port);
  -           */
  -
  -           /*                         
  -            * If a proxy has been set...
  -            * Set up a socket to do tunneling through the proxy.
  -            * Start it off as a regular socket, then layer SSL
  -            * over the top of it.
  -            */
  -           if (tunnelHost==null) {
  -              sslSocket = (SSLSocket)factory.createSocket(host, port);
  -           } else {
  -              Socket tunnel = new Socket(tunnelHost, tunnelPort);
  -              doTunnelHandshake(tunnel, host, port);
  -
  -              // Overlay tunnel socket with SSL
  -              sslSocket = (SSLSocket)factory.createSocket(tunnel, host, port, true);
  -           }
  -
  -           /*
  -            * Handshaking is started manually in this example because
  -            * PrintWriter catches all IOExceptions (including
  -            * SSLExceptions), sets an internal error flag, and then
  -            * returns without rethrowing the exception.
  -            *
  -            * Unfortunately, this means any error messages are lost,
  -            * which caused lots of confusion for others using this
  -            * code.  The only way to tell there was an error is to call
  -            * PrintWriter.checkError().
  -            */
  -           sslSocket.startHandshake();   
  -
  -           return  sslSocket;  
  -	    
  -	}
  -
  -        static private void doTunnelHandshake(Socket tunnel, String host, int port)
  -         throws IOException
  -        {
  -				 /*
  -				  * The proxy may need an authorization string. Check 
  -				  * standard https property.
  -				  */
  -     		 	 String proxyAuth = System.getProperty("https.proxyAuth");
  -     		 	 
  -				 String msg;
  -				 OutputStream out = tunnel.getOutputStream();
  -
  -        		 if (proxyAuth == null)
  -        		 {
  -        		 	// Autherization not required
  -        		 
  -             	msg = "CONNECT " + host + ":" + port + " HTTP/1.0\r\n"
  -	                          + "User-Agent: "
  -	                          + sun.net.www.protocol.http.HttpURLConnection.userAgent
  -	                          + "\r\n\r\n";
  -	          }
  -	          else
  -	          {
  -	          	// need to specify an authorization string in http header
  -	          	msg = "CONNECT " + host + ":" + port + " HTTP/1.0\r\n"
  - 							+ "Proxy-Authorization: " + proxyAuth + "\r\n"
  -	                  + "User-Agent: "
  -	                  + sun.net.www.protocol.http.HttpURLConnection.userAgent
  -	                  + "\r\n\r\n";
  -	          }
  -
  -             byte b[];
  -             try {
  -                 /*
  -                  * We really do want ASCII7 -- the http protocol doesn't change
  -                  * with locale.
  -                  */
  -                 b = msg.getBytes("ASCII7");
  -             } catch (UnsupportedEncodingException ignored) {
  -                 /*
  -                  * If ASCII7 isn't there, something serious is wrong, but
  -                  * Paranoia Is Good (tm)
  -                  */
  -                 b = msg.getBytes();
  -             }
  -             out.write(b);
  -             out.flush();
  -
  -             /*
  -              * We need to store the reply so we can create a detailed
  -              * error message to the user.
  -              */
  -             byte		reply[] = new byte[200];
  -             int		replyLen = 0;
  -             int		newlinesSeen = 0;
  -             boolean		headerDone = false;	/* Done on first newline */
  -
  -             InputStream	in = tunnel.getInputStream();
  -             boolean		error = false;
  -
  -             while (newlinesSeen < 2) {
  -                 int i = in.read();
  -                 if (i < 0) {
  -                     throw new IOException("Unexpected EOF from proxy");
  -                 }
  -                 if (i == '\n') {
  -                     headerDone = true;
  -                     ++newlinesSeen;
  -                 } else if (i != '\r') {
  -                     newlinesSeen = 0;
  -                     if (!headerDone && replyLen < reply.length) {
  -                         reply[replyLen++] = (byte) i;
  -                     }
  -                 }
  -             }
  -
  -             /*
  -              * Converting the byte array to a string is slightly wasteful
  -              * in the case where the connection was successful, but it's
  -              * insignificant compared to the network overhead.
  -              */
  -             String replyStr;
  -             try {
  -                 replyStr = new String(reply, 0, replyLen, "ASCII7");
  -             } catch (UnsupportedEncodingException ignored) {
  -                 replyStr = new String(reply, 0, replyLen);
  -             }
  -
  -             // Parse response, check for status code
  -             StringTokenizer st = new StringTokenizer(replyStr);
  -             st.nextToken(); // ignore version part
  -             if (!st.nextToken().startsWith("200")) {
  -                throw new IOException("Unable to tunnel through "
  -                        + tunnelHost + ":" + tunnelPort
  -                        + ".  Proxy returns \"" + replyStr + "\"");
  -             }
  -
  -             /* tunneling Handshake was successful! */
  -         }
  +    /**
  +     * Builds an SSL socket, after auto-starting SSL.
  +     *
  +     * @param host The host to which to connect.
  +     * @param port The port to which to connect.
  +     * @param tunnelHost The host to which to tunnel through.
  +     * @param tunnelPort The port to which to tunnel through.
  +     *
  +     * @return The socket.
  +     */
  +    public static Socket buildSSLSocket(String host, int port,
  +                                        String tunnelHost, int tunnelPort)
  +        throws IOException, UnknownHostException {
  +
  +        return buildSSLSocket(host, port,
  +                              tunnelHost, tunnelPort,
  +                              null);
  +    }
  +
  +    /**
  +     * Builds an SSL socket, after auto-starting SSL.
  +     *
  +     * @param host The host to which to connect.
  +     * @param port The port to which to connect.
  +     * @param tunnelHost The host to which to tunnel through.
  +     * @param tunnelPort The port to which to tunnel through.
  +     * @param tcpNoDelay Whether or not to disable Nagling.
  +     *
  +     * @return The socket.
  +     */
  +    public static Socket buildSSLSocket(String host, int port,
  +                                        String tunnelHost, int tunnelPort,
  +                                        Boolean tcpNoDelay)
  +        throws IOException, UnknownHostException {
  +
  +        SSLSocket sslSocket =  null;
  +        SSLSocketFactory factory =
  +            (SSLSocketFactory)SSLSocketFactory.getDefault();
  +
  +        if (tunnelHost == null) {
  +            sslSocket = (SSLSocket) factory.createSocket(host, port);
  +            if (sslSocket != null && tcpNoDelay != null)
  +                sslSocket.setTcpNoDelay(tcpNoDelay.booleanValue());
  +        } else {
  +            /*                         
  +             * If a proxy has been set...
  +             * Set up a socket to do tunneling through the proxy.
  +             * Start it off as a regular socket, then layer SSL
  +             * over the top of it.
  +             */
  +            Socket tunnel = doTunnelHandshake(tunnelHost, tunnelPort,
  +                                              host, port, tcpNoDelay);
  +
  +            // Overlay tunnel socket with SSL
  +            sslSocket = (SSLSocket) factory.createSocket(tunnel, host, port, true);
  +            if (sslSocket != null && tcpNoDelay != null)
  +                sslSocket.setTcpNoDelay(tcpNoDelay.booleanValue());
  +        }
  +
  +        /*
  +         * Handshaking is started manually in this example because
  +         * PrintWriter catches all IOExceptions (including
  +         * SSLExceptions), sets an internal error flag, and then
  +         * returns without rethrowing the exception.
  +         *
  +         * Unfortunately, this means any error messages are lost,
  +         * which caused lots of confusion for others using this
  +         * code.  The only way to tell there was an error is to call
  +         * PrintWriter.checkError().
  +         */
  +        sslSocket.startHandshake();   
  +
  +        return sslSocket;  
  +    }
  +
  +    static private Socket doTunnelHandshake(String tunnelHost, int tunnelPort,
  +                                            String host, int port,
  +                                            Boolean tcpNoDelay)
  +            throws IOException {
  +
  +        Socket tunnel = new Socket(tunnelHost, tunnelPort);
  +        if (tunnel != null && tcpNoDelay != null)
  +            tunnel.setTcpNoDelay(tcpNoDelay.booleanValue());
  +
  +        /*
  +         * The proxy may need an authorization string. Check 
  +         * standard https property.
  +         *
  +         * TODO: pass this as a parameter.
  +         */
  +        String proxyAuth = System.getProperty("https.proxyAuth");
  +                   
  +        String msg;
  +        OutputStream out = tunnel.getOutputStream();
  +
  +        if (proxyAuth == null) {
  +            // Authorization not required
  +
  +            msg = "CONNECT " + host + ":" + port + " HTTP/1.0\r\n"
  +                  + "User-Agent: "
  +                  + sun.net.www.protocol.http.HttpURLConnection.userAgent
  +                  + "\r\n\r\n";
  +        } else {
  +            // need to specify an authorization string in http header
  +            msg = "CONNECT " + host + ":" + port + " HTTP/1.0\r\n"
  +                  + "Proxy-Authorization: " + proxyAuth + "\r\n"
  +                  + "User-Agent: "
  +                  + sun.net.www.protocol.http.HttpURLConnection.userAgent
  +                  + "\r\n\r\n";
  +        }
  +
  +        byte b[];
  +        try {
  +            /*
  +             * We really do want ASCII7 -- the http protocol doesn't change
  +             * with locale.
  +             */
  +            b = msg.getBytes("ASCII7");
  +        } catch (UnsupportedEncodingException ignored) {
  +            /*
  +             * If ASCII7 isn't there, something serious is wrong, but
  +             * Paranoia Is Good (tm)
  +             */
  +            b = msg.getBytes();
  +        }
  +        out.write(b);
  +        out.flush();
  +
  +        /*
  +         * We need to store the reply so we can create a detailed
  +         * error message to the user.
  +         */
  +        byte reply[] = new byte[200];
  +        int replyLen = 0;
  +        int newlinesSeen = 0;
  +        boolean headerDone = false;    /* Done on first newline */
  +        InputStream in = tunnel.getInputStream();
  +        boolean error = false;
  +
  +        while (newlinesSeen < 2) {
  +            int i = in.read();
  +            if (i < 0) {
  +                throw new IOException("Unexpected EOF from proxy");
  +            }
  +            if (i == '\n') {
  +                headerDone = true;
  +                ++newlinesSeen;
  +            } else if (i != '\r') {
  +                newlinesSeen = 0;
  +                if (!headerDone && replyLen < reply.length) {
  +                    reply[replyLen++] = (byte) i;
  +                }
  +            }
  +        }
  +
  +        /*
  +         * Converting the byte array to a string is slightly wasteful
  +         * in the case where the connection was successful, but it's
  +         * insignificant compared to the network overhead.
  +         */
  +        String replyStr;
  +        try {
  +            replyStr = new String(reply, 0, replyLen, "ASCII7");
  +        } catch (UnsupportedEncodingException ignored) {
  +            replyStr = new String(reply, 0, replyLen);
  +        }
  +
  +        // Parse response, check for status code
  +        StringTokenizer st = new StringTokenizer(replyStr);
  +        st.nextToken(); // ignore version part
  +        if (!st.nextToken().startsWith("200")) {
  +            throw new IOException("Unable to tunnel through "
  +                                  + tunnelHost + ":" + tunnelPort
  +                                  + ".  Proxy returns \"" + replyStr + "\"");
  +        }
  +
  +        /* tunneling Handshake was successful! */
  +        return tunnel;
  +    }
   }
  -
  
  
  

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