cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From egl...@apache.org
Subject svn commit: r529583 [3/5] - in /incubator/cxf/trunk: rt/frontend/simple/src/main/java/org/apache/cxf/service/factory/ rt/transports/http/src/main/java/org/apache/cxf/transport/http/ rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/...
Date Tue, 17 Apr 2007 12:47:16 GMT
Added: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/MessageTrustDecider.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/MessageTrustDecider.java?view=auto&rev=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/MessageTrustDecider.java (added)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/MessageTrustDecider.java Tue Apr 17 05:47:13 2007
@@ -0,0 +1,123 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ 
+package org.apache.cxf.transport.http;
+
+import org.apache.cxf.message.Message;
+
+/**
+ * 
+ * The HTTPConduit calls upon this object to establish trust just before a 
+ * message within the HTTP Conduit is sent out. This object is based on
+ * the implementation of HTTP Conduit using java.net.URL and
+ * java.net.URLConnection implementations. 
+ * 
+ * The HttpURLConnection will be set up and connected, but no data
+ * yet sent (at least according to the JDK 1.5 default implemenation), 
+ * and in the case of an HttpsURLConnection (again with caveat on
+ * particular java.net.HttpsURLConnection implemenation), the TLS handshake 
+ * will be completed and certain TLS artifacts will be available.
+ * <p>
+ * Each MessageTrustDecider has a "logical" name that may be used in logging
+ * to help ensure the proper trust decision is being made for particular
+ * conduits.
+ */
+public abstract class MessageTrustDecider {
+    
+    /**
+     * This field contains the "logical" name of this Message Trust Decider.
+     * This field is not assigned to be final, since an extension may be
+     * Spring initialized as a bean, have an appropriate setLogicalName
+     * method, and set this field.
+     */
+    protected String logicalName;
+    
+    /**
+     * This default constructor sets the "logical" name of the trust
+     * decider to be its class name.
+     */
+    protected MessageTrustDecider() {
+        logicalName = this.getClass().getName();
+    }
+
+    /**
+     * This constructor is used to set the logical name of the 
+     * trust decider.
+     */
+    protected MessageTrustDecider(String name) {
+        logicalName = name;
+    }
+    
+    /**
+     * This method returns the logical name of this trust decider.
+     * The name of the trust decider may be used in logging or auditing
+     * to make sure that the proper trust decision is being implemented.
+     */
+    public String getLogicalName() {
+        return logicalName;
+    }
+    
+    /**
+     * This method is called when a Message is about to be sent out
+     * over an HTTPConduit. Its implementation must throw the specified
+     * exception if the URL connection cannot be trusted for the 
+     * message.
+     * <p>
+     * It is important to note that the Message structure at this point
+     * may not have any content, so any analysis of message content 
+     * may be impossible.
+     * <p>
+     * This method gets invoked after URL.setRequestProperties() is called
+     * on the URL for the selected protocol.
+     * <P>
+     * The HTTPConduit calls this message on every redirect, however, it is
+     * impossible to tell where it has been redirected from.
+     * 
+     * TODO: What are the exising Message Properties at the point of this call?
+     * 
+     * @param conduitName    This parameter contains the logical name 
+     *                       for the conduit that this trust decider
+     *                       is being called from.
+     *                       
+     * @param connectionInfo This parameter contains information about
+     *                       the URL Connection. It may be subclassed depending
+     *                       on the protocol used for the URL. For "https",
+     *                       this argument will be a HttpsURLConnectionInfo. 
+     *                       For "http", this argument will be 
+     *                       HttpURLConnectionInfo.
+     *                       
+     * @param message        This parameter contains the Message structure
+     *                       that governs where the message may be going.
+     * 
+     * @throws UntrustedURLConnectionIOException
+     *                     The trust decider throws this exception if 
+     *                     trust in the URLConnection cannot be established
+     *                     for the particular Message.
+     *                     
+     * @see HttpURLConnectionInfo
+     * @see HttpsURLConnectionInfo
+     */
+
+    public abstract void establishTrust(
+        String             conduitName,
+        URLConnectionInfo  connectionInfo,
+        Message            message
+    ) throws 
+        UntrustedURLConnectionIOException;
+}

Propchange: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/MessageTrustDecider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/URLConnectionInfo.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/URLConnectionInfo.java?view=auto&rev=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/URLConnectionInfo.java (added)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/URLConnectionInfo.java Tue Apr 17 05:47:13 2007
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ 
+package org.apache.cxf.transport.http;
+
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * This class is returned from the URLConnectionFactory to give
+ * information that is from the URLConnection that was created by that
+ * factory.
+ */
+public class URLConnectionInfo {
+    /**
+     * The URL the connection is associated with.
+     */
+    protected final URL theURL;
+    
+    /**
+     * This constructor is used to represent a URLConnection.
+     * 
+     * @param connection The URLConnection that this info object will represent.
+     */
+    public URLConnectionInfo(URLConnection connection) {
+        theURL = connection.getURL();
+    }
+    
+    /**
+     * This field returns the URL associated with the connection
+     * in question.
+     * 
+     * @return
+     */
+    public URL getURL() {
+        return theURL;
+    }
+}

Propchange: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/URLConnectionInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/UntrustedURLConnectionIOException.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/UntrustedURLConnectionIOException.java?view=auto&rev=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/UntrustedURLConnectionIOException.java (added)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/UntrustedURLConnectionIOException.java Tue Apr 17 05:47:13 2007
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ 
+
+package org.apache.cxf.transport.http;
+
+import java.io.IOException;
+
+/**
+ * This exception is thrown by the JSSETrustDecider when
+ * trust in the TLS cannot be established.
+ */
+public class UntrustedURLConnectionIOException extends IOException {
+
+    /**
+     * This field is for serialization.
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * This exception should mention a good reason of
+     * why this JSSE established connection is untrusted.
+     * @param message
+     */
+    public UntrustedURLConnectionIOException(String message) {
+        super(message);
+    }
+}

Propchange: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/UntrustedURLConnectionIOException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpBasicAuthSupplierBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpBasicAuthSupplierBeanDefinitionParser.java?view=auto&rev=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpBasicAuthSupplierBeanDefinitionParser.java (added)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpBasicAuthSupplierBeanDefinitionParser.java Tue Apr 17 05:47:13 2007
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.http.spring;
+
+
+import org.w3c.dom.Element;
+import org.apache.cxf.configuration.spring.AbstractBeanDefinitionParser;
+import org.apache.cxf.transport.http.HttpBasicAuthSupplier;
+
+public class HttpBasicAuthSupplierBeanDefinitionParser extends
+        AbstractBeanDefinitionParser {
+
+    @Override
+    protected String getJaxbPackage() {
+        return "org.apache.cxf.transports.http.configuration";
+    }
+    @Override
+    protected Class getBeanClass(Element arg0) {
+        return HttpBasicAuthSupplier.class;
+    }
+
+}

Propchange: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpBasicAuthSupplierBeanDefinitionParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpConduitBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpConduitBeanDefinitionParser.java?view=diff&rev=529583&r1=529582&r2=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpConduitBeanDefinitionParser.java (original)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/HttpConduitBeanDefinitionParser.java Tue Apr 17 05:47:13 2007
@@ -21,23 +21,130 @@
 import javax.xml.namespace.QName;
 
 import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
 import org.apache.cxf.configuration.spring.AbstractBeanDefinitionParser;
 import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.http.HttpBasicAuthSupplier;
+import org.apache.cxf.transport.http.MessageTrustDecider;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 
-public class HttpConduitBeanDefinitionParser extends AbstractBeanDefinitionParser {
+public class HttpConduitBeanDefinitionParser 
+    extends AbstractBeanDefinitionParser {
 
-    private static final String HTTP_NS = "http://cxf.apache.org/transports/http/configuration";
+    private static final String HTTP_NS =
+        "http://cxf.apache.org/transports/http/configuration";
 
     @Override
     public void doParse(Element element, BeanDefinitionBuilder bean) {
         bean.setAbstract(true);
-        mapElementToJaxbProperty(element, bean, new QName(HTTP_NS, "client"), "client");
-        mapElementToJaxbProperty(element, bean, new QName(HTTP_NS, "proxyAuthorization"), 
-                                 "proxyAuthorization");
-        mapElementToJaxbProperty(element, bean, new QName(HTTP_NS, "authorization"), "authorization");
-        mapElementToJaxbProperty(element, bean, new QName(HTTP_NS, "sslClient"), "sslClient");
+        mapElementToJaxbProperty(element, bean, 
+                new QName(HTTP_NS, "client"), "client");
+        mapElementToJaxbProperty(element, bean, 
+                new QName(HTTP_NS, "proxyAuthorization"), "proxyAuthorization");
+        mapElementToJaxbProperty(element, bean, 
+                new QName(HTTP_NS, "authorization"), "authorization");
+        mapElementToJaxbProperty(element, bean, 
+                new QName(HTTP_NS, "sslClient"), "sslClient");
+        
+        mapSpecificElements(element, bean);
+    }
+
+    /**
+     * This method specifically maps the "trustDecider" and "basicAuthSupplier"
+     * elements to properties on the HttpConduit.
+     * 
+     * @param parent This should represent "conduit".
+     * @param bean   The bean parser.
+     */
+    private void mapSpecificElements(
+        Element               parent, 
+        BeanDefinitionBuilder bean
+    ) {
+        NodeList nl = parent.getChildNodes();
+        for (int i = 0; i < nl.getLength(); i++) {
+            Node n = nl.item(i);
+            // Schema should require that no more than one each of these exist.
+            if (n.getNodeType() == Node.ELEMENT_NODE 
+                && n.getLocalName().equals("trustDecider")
+                && n.getNamespaceURI().equals(HTTP_NS)) {
+                mapElement((Element)n, bean, MessageTrustDecider.class);
+            }
+            if (n.getNodeType() == Node.ELEMENT_NODE 
+                && n.getLocalName().equals("basicAuthSupplier")
+                && n.getNamespaceURI().equals(HTTP_NS)) {
+                mapElement((Element)n, bean, HttpBasicAuthSupplier.class);
+            }
+        }
+
+    }
+    
+    /**
+     * This method finds the class or bean associated with the named element
+     * and sets the bean property that is associated with the same name as
+     * the element.
+     * <p>
+     * The element has either a "class" attribute or "bean" attribute, but 
+     * not both.
+     * 
+     * @param element      The element.
+     * @param bean         The Bean Definition Parser.
+     * @param elementClass The Class a bean or class is supposed to be.
+     */
+    protected void mapElement(
+        Element               element, 
+        BeanDefinitionBuilder bean,
+        Class                 elementClass
+    ) {
+        String elementName = element.getLocalName();
+    
+        String classProperty = element.getAttribute("class");
+        if (classProperty != null && !classProperty.equals("")) {
+            try {
+                Object obj = 
+                    ClassLoaderUtils.loadClass(
+                            classProperty, getClass()).newInstance();
+                if (!elementClass.isInstance(obj)) {
+                    throw new IllegalArgumentException(
+                        "Element '" + elementName + "' must be of type " 
+                        + elementClass.getName() + ".");
+                }
+                bean.addPropertyValue(elementName, obj);
+            } catch (IllegalAccessException ex) {
+                throw new IllegalArgumentException(
+                    "Element '" + elementName + "' could not load " 
+                    + classProperty
+                    + " - " + ex);
+            } catch (ClassNotFoundException ex) {
+                throw new IllegalArgumentException(
+                    "Element '" + elementName + "' could not load " 
+                    + classProperty
+                    + " - " + ex);
+            } catch (InstantiationException ex) {
+                throw new IllegalArgumentException(
+                    "Element '" + elementName + "' could not load " 
+                    + classProperty
+                    + " - " + ex);
+            }
+        }
+        String beanref = element.getAttribute("bean");
+        if (beanref != null && !beanref.equals("")) {
+            System.out.print("Bean property is " + beanref);
+            if (classProperty != null && !classProperty.equals("")) {
+                throw new IllegalArgumentException(
+                        "Element '" + elementName + "' cannot have both "
+                        + "\"bean\" and \"class\" attributes.");
+                                
+            }
+            bean.addPropertyReference(elementName, beanref);
+        } else if (classProperty == null || classProperty.equals("")) {
+            throw new IllegalArgumentException(
+                    "Element '" + elementName 
+                    + "' requires at least one of the "
+                    + "\"bean\" or \"class\" attributes.");
+        }
     }
     
     @Override

Added: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/MessageTrustDeciderBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/MessageTrustDeciderBeanDefinitionParser.java?view=auto&rev=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/MessageTrustDeciderBeanDefinitionParser.java (added)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/MessageTrustDeciderBeanDefinitionParser.java Tue Apr 17 05:47:13 2007
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.http.spring;
+
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.configuration.spring.AbstractBeanDefinitionParser;
+import org.apache.cxf.transport.http.MessageTrustDecider;
+
+public class MessageTrustDeciderBeanDefinitionParser extends
+        AbstractBeanDefinitionParser {
+
+    @Override
+    protected String getJaxbPackage() {
+        return "org.apache.cxf.transports.http.configuration";
+    }
+    
+    @Override
+    protected Class getBeanClass(Element arg0) {
+        return MessageTrustDecider.class;
+    }
+
+}

Propchange: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/MessageTrustDeciderBeanDefinitionParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/NamespaceHandler.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/NamespaceHandler.java?view=diff&rev=529583&r1=529582&r2=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/NamespaceHandler.java (original)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/spring/NamespaceHandler.java Tue Apr 17 05:47:13 2007
@@ -22,7 +22,13 @@
 
 public class NamespaceHandler extends NamespaceHandlerSupport {
     public void init() {
-        registerBeanDefinitionParser("conduit", new HttpConduitBeanDefinitionParser());        
-        registerBeanDefinitionParser("destination", new HttpDestinationBeanDefinitionParser());        
+        registerBeanDefinitionParser("conduit", 
+                new HttpConduitBeanDefinitionParser());        
+        registerBeanDefinitionParser("trustDecider", 
+                new MessageTrustDeciderBeanDefinitionParser());        
+        registerBeanDefinitionParser("basicAuthSupplier", 
+                new HttpBasicAuthSupplierBeanDefinitionParser()); 
+        registerBeanDefinitionParser("destination", 
+                new HttpDestinationBeanDefinitionParser());        
     }
 }

Modified: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/HttpsURLConnectionFactory.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/HttpsURLConnectionFactory.java?view=diff&rev=529583&r1=529582&r2=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/HttpsURLConnectionFactory.java (original)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/HttpsURLConnectionFactory.java Tue Apr 17 05:47:13 2007
@@ -20,61 +20,134 @@
 package org.apache.cxf.transport.https;
 
 import java.io.IOException;
+import java.net.HttpURLConnection;
 import java.net.Proxy;
 import java.net.URL;
-import java.net.URLConnection;
 import java.util.logging.Handler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
 
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.configuration.security.SSLClientPolicy;
-import org.apache.cxf.transport.http.URLConnectionFactory;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.http.HttpURLConnectionFactory;
+import org.apache.cxf.transport.http.HttpURLConnectionInfo;
 
+/**
+ * This HttpsURLConnectionFactory implements the HttpURLConnectionFactory
+ * for using the given SSL Policy to configure TLS connections for "https:"
+ * URLs.
+ * 
+ */
+public final class HttpsURLConnectionFactory 
+    implements HttpURLConnectionFactory {
+    
+    /**
+     * This constant holds the URL Protocol Identifier for HTTPS
+     */
+    public static final String HTTPS_URL_PROTOCOL_ID = "https";
 
-public final class HttpsURLConnectionFactory implements URLConnectionFactory {
     private static final long serialVersionUID = 1L;
     private static final Logger LOG =
         LogUtils.getL7dLogger(HttpsURLConnectionFactory.class);
     
+    /*
+     *  For development and testing only
+     */
     private static final String[] UNSUPPORTED =
     {"SessionCaching", "SessionCacheKey", "MaxChainLength",
      "CertValidator", "ProxyHost", "ProxyPort"};
     
+    /*
+     *  For development and testing only
+     */
     private static final String[] DERIVATIVE = {"CiphersuiteFilters"};
     
+    /**
+     * This field holds the conduit to which this connection factory
+     * is a slave.
+     */
+    HTTPConduit conduit;
+    
+    /**
+     * This field contains the TLS configuration for URLs created
+     * by this factory.
+     */
     SSLClientPolicy sslPolicy;
     
+   
     /**
-     * Constructor.
+     * This constructor initialized the factory with the configured SSL Client
+     * Side Policy for the HTTPConduit for which this factory is used.
      * 
-     * @param policy the applicable SSLClientPolicy (guaranteed non-null)
+     * @param policy The SSL Client Side Policy. This parameter is guaranteed 
+     *               to be non-null.
      */
     public HttpsURLConnectionFactory(SSLClientPolicy policy) {
-        sslPolicy = policy;
+        sslPolicy        = policy;
     }
     
     /**
-     * Create a URLConnection, proxified if neccessary.
+     * Create a HttpURLConnection, proxified if neccessary.
+     * 
      * 
-     * @param proxy non-null if connection should be proxified
-     * @param url the target URL
-     * @return an appropriate URLConnection
+     * @param proxy This parameter is non-null if connection should be proxied.
+     * @param url   The target URL. This parameter must be an https url.
+     * 
+     * @return The HttpsURLConnection for the given URL.
+     * @throws IOException This exception is thrown if 
+     *         the "url" is not "https" or other IOException
+     *         is thrown. 
+     *                     
      */
-    public URLConnection createConnection(Proxy proxy, URL url)
+    public HttpURLConnection createConnection(Proxy proxy, URL url)
         throws IOException {
-        URLConnection connection = proxy != null 
-                                   ? url.openConnection(proxy)
-                                   : url.openConnection();
-        if (connection instanceof HttpsURLConnection) {
-            decorate((HttpsURLConnection)connection);
+
+        if (!url.getProtocol().equals(HTTPS_URL_PROTOCOL_ID)) {
+            throw new IOException("Illegal Protocol " 
+                    + url.getProtocol() 
+                    + " for HTTPS URLConnection Factory.");
         }
+        
+        HttpsURLConnection connection =
+            (HttpsURLConnection) (proxy != null 
+                                   ? url.openConnection(proxy)
+                                   : url.openConnection());
+                                   
+        decorate(connection);
+        
         return connection;
     }
-    
+
+    /**
+     * This class is the default hostname verifier that the
+     * HttpsURLConnection implementation uses to verify that
+     * a hostname belongs to a particular verified key/certificate
+     * pair. 
+     * <p>
+     * The default is to make sure that "CN=<hostname>", which
+     * isn't always desired. The MessageTrustDecider is
+     * the point at which an application can place trust in the
+     * certificate and target URL. We use this default of always
+     * returning true, delegate the trust decision to the 
+     * MessageTrustDecider.
+     */
+    private class AlwaysTrueHostnameVerifier implements HostnameVerifier {
+
+        public boolean verify(
+            String      hostname,
+            SSLSession  sslSession
+        ) {
+            return true;
+        }
+
+    }
+
     /**
      * Decorate connection with applicable SSL settings.
      * 
@@ -90,20 +163,26 @@
         String keyPassword =
             SSLUtils.getKeyPassword(sslPolicy.getKeyPassword(), LOG);
         String keyStoreMgrFactoryAlgorithm =
-            SSLUtils.getKeystoreAlgorithm(sslPolicy.getKeystoreAlgorithm(),
-                                          LOG);
+            SSLUtils.getKeystoreAlgorithm(
+                    sslPolicy.getKeystoreAlgorithm(), LOG);
         String trustStoreMgrFactoryAlgorithm =
-            SSLUtils.getTrustStoreAlgorithm(sslPolicy.getTrustStoreAlgorithm(),
-                                            LOG);
+            SSLUtils.getTrustStoreAlgorithm(
+                    sslPolicy.getTrustStoreAlgorithm(), LOG);
         String trustStoreLocation =
             SSLUtils.getTrustStore(sslPolicy.getTrustStore(), LOG);
         String trustStoreType =
             SSLUtils.getTrustStoreType(sslPolicy.getTrustStoreType(), LOG);
         String secureSocketProtocol =
-            SSLUtils.getSecureSocketProtocol(sslPolicy.getSecureSocketProtocol(),
-                                             LOG);
+            SSLUtils.getSecureSocketProtocol(
+                    sslPolicy.getSecureSocketProtocol(), LOG);
+        
+        secureConnection.setHostnameVerifier(
+                    new AlwaysTrueHostnameVerifier());
         
         try {
+            // There is something special about the keystore being a pkcs12
+            // that governs the trust store. I don't know what that is.
+            
             boolean pkcs12 =
                 keyStoreType.equalsIgnoreCase(SSLUtils.PKCS12_TYPE);
             SSLContext ctx = SSLUtils.getSSLContext(
@@ -126,9 +205,14 @@
                                          SSLUtils.getSupportedCipherSuites(ctx),
                                          sslPolicy.getCiphersuiteFilters(),
                                          LOG, false);
+            
+            // The SSLSocketFactoryWrapper enables certain cipher suites
+            // from the policy.
             secureConnection.setSSLSocketFactory(
                 new SSLSocketFactoryWrapper(ctx.getSocketFactory(),
                                             cipherSuites));
+            
+           
         } catch (Exception e) {
             LogUtils.log(LOG, Level.SEVERE, "SSL_CONTEXT_INIT_FAILURE", e);
         }
@@ -152,6 +236,22 @@
     
     protected String[] getDerivative() {
         return DERIVATIVE;
+    }
+
+    /**
+     * This operation returns an HttpsURLConnectionInfo for the 
+     * given HttpsURLConnection. 
+     * 
+     * @param connection The HttpsURLConnection
+     * @return The HttpsURLConnectionInfo object for the given 
+     *         HttpsURLConnection.
+     * @throws IOException Normal IO Exceptions.
+     * @throws ClassCastException If "connection" is not an HttpsURLConnection.
+     */
+    public HttpURLConnectionInfo getConnectionInfo(
+            HttpURLConnection connection
+    ) throws IOException {  
+        return new HttpsURLConnectionInfo((HttpsURLConnection)connection);
     }
 }
 

Added: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/HttpsURLConnectionInfo.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/HttpsURLConnectionInfo.java?view=auto&rev=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/HttpsURLConnectionInfo.java (added)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/HttpsURLConnectionInfo.java Tue Apr 17 05:47:13 2007
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ 
+package org.apache.cxf.transport.https;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.security.cert.Certificate;
+
+import javax.net.ssl.HttpsURLConnection;
+
+import org.apache.cxf.transport.http.HttpURLConnectionInfo;
+
+/**
+ * This class holds information about the HttpsURLConnection. This
+ * class should be used when the getURL().getProtocol() is "https".
+ */
+public class HttpsURLConnectionInfo extends HttpURLConnectionInfo {
+
+    /**
+     * This field contains the cipherSuite enabled in the 
+     * HTTPS URLconnection.
+     */
+    protected final String enabledCipherSuite;
+    
+    /**
+     * This field contains the certificates that were used to
+     * authenticate the connection to the peer.
+     */
+    protected final Certificate[] localCertificates;
+    
+    /**
+     * This field contains the Principal that authenticated to the
+     * peer.
+     */
+    protected final Principal localPrincipal;
+    
+    /**
+     * This field contains the certificates the server presented
+     * to authenticate.
+     */
+    protected final Certificate[] serverCertificates;
+    
+    /**
+     * This field contains the Principal that represents the 
+     * authenticated peer.
+     */
+    protected final Principal peerPrincipal;
+    
+    /**
+     * This constructor is used to create the info object
+     * representing the this HttpsURLConnection.
+     */
+    HttpsURLConnectionInfo(HttpsURLConnection connection)
+        throws IOException {
+        super(connection);
+        
+        enabledCipherSuite = connection.getCipherSuite();
+        localCertificates  = connection.getLocalCertificates();
+        localPrincipal     = connection.getLocalPrincipal();
+        serverCertificates = connection.getServerCertificates();
+        peerPrincipal      = connection.getPeerPrincipal();
+    }
+
+    /**
+     * This method returns the cipher suite employed in this
+     * HttpsURLConnection.
+     */
+    public String getEnabledCipherSuite() {
+        return enabledCipherSuite;
+    }
+    
+    /**
+     * This method returns the certificates that were used to
+     * authenticate to the peer.
+     */
+    public Certificate[] getLocalCertificates() {
+        return localCertificates;
+    }
+    
+    /**
+     * This method returns the Princpal that authenticated to
+     * the peer.
+     */
+    public Principal getLocalPrincipal() {
+        return localPrincipal;
+    }
+    
+    /**
+     * This method returns the certificates presented by the
+     * peer for authentication.
+     */
+    public Certificate[] getServerCertificates() {
+        return serverCertificates;
+    }
+    
+    /**
+     * This method returns the Principal that represents the
+     * authenticated peer.
+     */
+    public Principal getPeerPrincipal() {
+        return peerPrincipal;
+    }
+}

Propchange: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/HttpsURLConnectionInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLSocketFactoryWrapper.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLSocketFactoryWrapper.java?view=diff&rev=529583&r1=529582&r2=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLSocketFactoryWrapper.java (original)
+++ incubator/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/https/SSLSocketFactoryWrapper.java Tue Apr 17 05:47:13 2007
@@ -23,6 +23,7 @@
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.UnknownHostException;
+
 import java.util.logging.Handler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -39,12 +40,14 @@
     private SSLSocketFactory sslSocketFactory;
     private String[] ciphers;
     
-    public SSLSocketFactoryWrapper(SSLSocketFactory sslSocketFactoryParam, String[] ciphersParam) {
+    public SSLSocketFactoryWrapper(
+        SSLSocketFactory sslSocketFactoryParam,
+        String[]         ciphersParam
+    ) {
         sslSocketFactory = sslSocketFactoryParam;
-        ciphers = ciphersParam;
+        ciphers          = ciphersParam;
     }
 
-    
     public String[] getDefaultCipherSuites() {
         return sslSocketFactory.getDefaultCipherSuites();
     }
@@ -52,7 +55,7 @@
     public String[] getSupportedCipherSuites() {
         return sslSocketFactory.getSupportedCipherSuites(); 
     }
-    
+        
     public Socket createSocket(Socket s, String host, int port, boolean autoClose)
         throws IOException, UnknownHostException  {
         return enableCipherSuites(sslSocketFactory.createSocket(s, host, port, autoClose),
@@ -83,6 +86,7 @@
     
     private Socket enableCipherSuites(Socket s, Object[] logParams) {
         SSLSocket socket = (SSLSocket)s;
+        
         if ((socket != null) && (ciphers != null)) {
             socket.setEnabledCipherSuites(ciphers);
         }
@@ -92,6 +96,7 @@
                          "PROBLEM_CREATING_OUTBOUND_REQUEST_SOCKET", 
                          logParams);
         }
+
         return socket;        
     }
     /*

Modified: incubator/cxf/trunk/rt/transports/http/src/main/resources/schemas/wsdl/http-conf.xsd
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/main/resources/schemas/wsdl/http-conf.xsd?view=diff&rev=529583&r1=529582&r2=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/main/resources/schemas/wsdl/http-conf.xsd (original)
+++ incubator/cxf/trunk/rt/transports/http/src/main/resources/schemas/wsdl/http-conf.xsd Tue Apr 17 05:47:13 2007
@@ -20,9 +20,12 @@
 
 <xs:schema targetNamespace="http://cxf.apache.org/transports/http/configuration" 
            xmlns:xs="http://www.w3.org/2001/XMLSchema" 
+           xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
            xmlns:http-conf="http://cxf.apache.org/transports/http/configuration" 
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
            xmlns:sec="http://cxf.apache.org/configuration/security"
+  		   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  		   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
            elementFormDefault="qualified" 
            attributeFormDefault="unqualified"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
@@ -30,7 +33,7 @@
 
     <xs:import namespace="http://schemas.xmlsoap.org/wsdl/" schemaLocation="../../../../../../../../common/schemas/src/main/resources/schemas/wsdl/wsdl.xsd"/>
     <xs:import namespace="http://cxf.apache.org/configuration/security" schemaLocation="../../../../../../../../common/schemas/src/main/resources/schemas/configuration/security.xsd"/>
-
+    
     <xs:element name="server" type="http-conf:HTTPServerPolicy"/>
     <xs:element name="authorization" type="sec:AuthorizationPolicy"/>
     <xs:element name="sslServer" type="sec:SSLServerPolicy"/>
@@ -41,6 +44,9 @@
     <xs:element name="proxyAuthorization" type="sec:AuthorizationPolicy"/>
     <xs:element name="sslClient" type="sec:SSLClientPolicy"/>
 
+    <xs:element name="trustDecider"           type="http-conf:ClassOrBeanType"/>
+    <xs:element name="basicAuthSupplier"      type="http-conf:ClassOrBeanType"/>
+    
     <xs:element name="conduit">
         <xs:complexType>
             <xs:sequence>
@@ -48,11 +54,20 @@
                 <xs:element ref="http-conf:authorization" minOccurs="0"/>
                 <xs:element ref="http-conf:proxyAuthorization" minOccurs="0"/>
                 <xs:element ref="http-conf:sslClient" minOccurs="0"/>
+                <xs:element ref="http-conf:basicAuthSupplier" 
+                			minOccurs="0" maxOccurs="1"/>
+                <xs:element ref="http-conf:trustDecider" 
+                			minOccurs="0" maxOccurs="1"/>
             </xs:sequence>
             <xs:attribute name="id" type="xs:string" use="required"/>
         </xs:complexType>
     </xs:element>
     
+    <xs:complexType name="ClassOrBeanType">
+       <xs:attribute name="class" type="xs:string"/>
+       <xs:attribute name="bean"  type="xs:string"/>
+    </xs:complexType>
+    
     <xs:element name="destination">
       <xs:complexType>        
         <xs:sequence>
@@ -205,6 +220,21 @@
                         <xs:documentation>
                         Whether to automatically follow up when the server issues a redirection reply.  
                         Default is No, so calling flow would handle this condition. 
+                        (name is not part of standard)
+                        </xs:documentation>
+                    </xs:annotation>      
+                </xs:attribute>
+
+                <xs:attribute name="MaxRetransmits" type="xs:int" use="optional" default="-1">
+                    <xs:annotation>
+                        <xs:documentation>
+                        This attribute governs the amount of retransmits that 
+                        are allowed for redirects along with retransmits for 
+                        authorization. Each redirect may cause another 
+                        retransmit for a UNAUTHORIZED response code, ie. 401. 
+                        Any negative number indicates unlimited retransmits,
+                        although, loop protection is provided. 
+                        The default is unlimited. 
                         (name is not part of standard)
                         </xs:documentation>
                     </xs:annotation>      

Modified: incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java?view=diff&rev=529583&r1=529582&r2=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java (original)
+++ incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java Tue Apr 17 05:47:13 2007
@@ -20,23 +20,17 @@
 package org.apache.cxf.transport.http;
 
 
-import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.HttpURLConnection;
-import java.net.Proxy;
 import java.net.URL;
-import java.net.URLConnection;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import javax.servlet.ServletInputStream;
-import javax.servlet.ServletOutputStream;
-
+import org.apache.cxf.Bus;
 import org.apache.cxf.bus.CXFBusImpl;
+import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.configuration.security.AuthorizationPolicy;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.message.Message;
@@ -59,43 +53,65 @@
 
 
 public class HTTPConduitTest extends Assert {
-    private static final String NOWHERE = "http://nada.nothing.nowhere.null/";
-    private static final String PAYLOAD = "message payload";
-    private EndpointReferenceType target;
-    private EndpointInfo endpointInfo;
-    private URLConnectionFactory connectionFactory;
-    private URLConnection connection;
-    private Proxy proxy;
     private Message inMessage;
-    private MessageObserver observer;
-    private ServletOutputStream os;
-    private ServletInputStream is;
     private IMocksControl control;
     
     @Before
     public void setUp() throws Exception {
-        control = EasyMock.createNiceControl();
     }
     
     @After
     public void tearDown() {
-        // avoid intermittent spurious failures on EasyMock detecting finalize
-        // calls by mocking up only class data members (no local variables)
-        // and explicitly making available for GC post-verify
-        finalVerify();
-        connectionFactory = null;
-        connection = null;
-        proxy = null;
-        inMessage = null;
-        observer = null;
-        os = null;
-        is = null;
     }
 
+    /**
+     * Generates a new message.
+     */
+    private Message getNewMessage() {
+        Message message = new MessageImpl();
+        Map<String, List<String>> headers = new HashMap<String, List<String>>();
+        List<String> contentTypes = new ArrayList<String>();
+        contentTypes.add("text/xml");
+        contentTypes.add("charset=utf8");
+        headers.put("content-type", contentTypes);
+        message.put(Message.PROTOCOL_HEADERS, headers);
+        return message;
+    }
+    
+    /**
+     * This test class is a Basic Auth Supplier with a 
+     * preemptive UserPass.
+     */
+    class BasicAuthSupplier extends HttpBasicAuthSupplier {
+        public UserPass getPreemptiveUserPass(
+                String conduitName, URL url, Message m) {
+            return createUserPass("Gandalf", "staff");
+        }
+        public UserPass getUserPassForRealm(
+                String conduitName, URL url, Message m, String r) {
+            return null;
+        }
+    }
+
+    /**
+     * This test verfies that the "getTarget() call returns the correct
+     * EndpointReferenceType for the given endpoint address.
+     */
     @Test
     public void testGetTarget() throws Exception {
-        HTTPConduit conduit = setUpConduit(false);
+        Bus bus = new CXFBusImpl();
+        EndpointInfo ei = new EndpointInfo();
+        ei.setAddress("http://nowhere.com/bar/foo");
+        HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+        conduit.finalizeConfig();
+        
+        EndpointReferenceType target = 
+            EndpointReferenceUtils.getEndpointReference(
+                    "http://nowhere.com/bar/foo");
+        
+        // Test call
         EndpointReferenceType ref = conduit.getTarget();
+        
         assertNotNull("unexpected null target", ref);
         assertEquals("unexpected target",
                      EndpointReferenceUtils.getAddress(ref),
@@ -105,294 +121,134 @@
                      "/bar/foo");
     }
     
+    /**
+     * Verfies one of the tenents of our interface -- the Conduit sets up
+     * an OutputStream on the message after a "prepare".
+     */
     @Test
-    public void testSend() throws Exception {
-        HTTPConduit conduit = setUpConduit(true, false, false);
-        Message message = new MessageImpl();
-        conduit.prepare(message);
-        verifySentMessage(conduit, message);
-    }
-    
-    @Test
-    public void testSendWithHeaders() throws Exception {
-        HTTPConduit conduit = setUpConduit(true, false, false);
-        Message message = new MessageImpl();
-        setUpHeaders(message);
-        conduit.prepare(message);
-        verifySentMessage(conduit, message, true);
-    }
-    
-    @Test
-    public void testSendHttpConnection() throws Exception {
-        HTTPConduit conduit = setUpConduit(true, true, false);
-        Message message = new MessageImpl();
+    public void testConduitOutputStream() throws Exception {
+        Bus bus = new CXFBusImpl();
+        EndpointInfo ei = new EndpointInfo();
+        ei.setAddress("http://nowhere.com/bar/foo");
+        HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+        conduit.finalizeConfig();
+
+        Message message = getNewMessage();
+        
+        // Test call
         conduit.prepare(message);
-        verifySentMessage(conduit, message);
+        
+        assertNotNull("Conduit should always set output stream.", 
+                        message.getContent(OutputStream.class));
     }
 
+    /**
+     * This test verifies the precidence of Authorization Information.
+     * Setting authorization information on the Message takes precidence
+     * over a Basic Auth Supplier with preemptive UserPass, and that 
+     * followed by setting it directly on the Conduit.
+     */
     @Test
-    public void testSendHttpConnectionAutoRedirect() throws Exception {
-        HTTPConduit conduit = setUpConduit(true, true, true);
-        Message message = new MessageImpl();
+    public void testAuthPolicyPrecidence() throws Exception {
+        Bus bus = new CXFBusImpl();
+        EndpointInfo ei = new EndpointInfo();
+        ei.setAddress("http://nowhere.com/bar/foo");
+        HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+        conduit.finalizeConfig();
+    
+        conduit.getAuthorization().setUserName("Satan");
+        conduit.getAuthorization().setPassword("hell");
+        Message message = getNewMessage();
+        
+        // Test call
         conduit.prepare(message);
-        verifySentMessage(conduit, message);
-    }
-    
-    @Test
-    public void testSendDecoupled() throws Exception {
-        HTTPConduit conduit = setUpConduit(true, false, false, true);
-        Message message = new MessageImpl();
+        
+        Map<String, List<String>> headers =
+            CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
+        
+        assertNotNull("Authorization Header should exist",
+                headers.get("Authorization"));
+        
+        assertEquals("Unexpected Authorization Token", 
+                "Basic " + Base64Utility.encode("Satan:hell".getBytes()),
+                headers.get("Authorization").get(0));
+        
+        // Setting a Basic Auth User Pass should override
+        conduit.setBasicAuthSupplier(new BasicAuthSupplier());
+        message = getNewMessage();
+        
+        // Test Call
         conduit.prepare(message);
-        verifySentMessage(conduit, message, false, true);
-    }
-    
-    
-    private void setUpHeaders(Message message) {
-        Map<String, List<String>> headers = new HashMap<String, List<String>>();
-        List<String> contentTypes = new ArrayList<String>();
-        contentTypes.add("text/xml");
-        contentTypes.add("charset=utf8");
-        headers.put("content-type", contentTypes);
-        message.put(Message.PROTOCOL_HEADERS, headers);
         
-        AuthorizationPolicy authPolicy = new AuthorizationPolicy();
-        authPolicy.setUserName("BJ");
-        authPolicy.setPassword("value");
-        message.put(AuthorizationPolicy.class, authPolicy);        
-    }
-
-    private HTTPConduit setUpConduit(boolean send) throws Exception {
-        return setUpConduit(send, false, false);
-    }
-    
-    private HTTPConduit setUpConduit(boolean send,
-                                     boolean httpConnection,
-                                     boolean autoRedirect) throws Exception {
-        return setUpConduit(send, httpConnection, autoRedirect, false);
-    }
-    
-    private HTTPConduit setUpConduit(boolean send,
-                                     boolean httpConnection,
-                                     boolean autoRedirect,
-                                     boolean decoupled) throws Exception {
-        endpointInfo = new EndpointInfo();
-        endpointInfo.setAddress(NOWHERE + "bar/foo");
-        target = getEPR("bar/foo");
-        connectionFactory = control.createMock(URLConnectionFactory.class);
-        if (send) {
-            //proxy = control.createMock(Proxy.class);
-            proxy =  null;
-            connection =
-                control.createMock(httpConnection ? HttpURLConnection.class : URLConnection.class);
-            connectionFactory.createConnection(
-                                      EasyMock.eq(proxy), 
-                                      EasyMock.eq(new URL(NOWHERE + "bar/foo")));
-            EasyMock.expectLastCall().andReturn(connection);
-            connection.setDoOutput(true);
-            EasyMock.expectLastCall();
-            
-            if (httpConnection) {
-                ((HttpURLConnection)connection).setRequestMethod("POST");                
-            }
-            
-            connection.setConnectTimeout(303030);
-            EasyMock.expectLastCall();
-            connection.setReadTimeout(404040);
-            EasyMock.expectLastCall();
-            connection.setUseCaches(false);
-            EasyMock.expectLastCall();
-            
-            
-
-            if (httpConnection) {
-                ((HttpURLConnection)connection).setInstanceFollowRedirects(autoRedirect);
-                EasyMock.expectLastCall();                
-                if (!autoRedirect) {
-                    ((HttpURLConnection)connection).getRequestMethod();
-                    EasyMock.expectLastCall().andReturn("POST");
-                    ((HttpURLConnection)connection).setChunkedStreamingMode(2048);
-                    EasyMock.expectLastCall();                    
-                }
-            }         
-        }
+        headers =
+            CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
 
-        CXFBusImpl bus = new CXFBusImpl();
-        URL decoupledURL = null;
-        if (decoupled) {
-            decoupledURL = new URL(NOWHERE + "response");
-            DestinationFactoryManager mgr =
-                control.createMock(DestinationFactoryManager.class);
-            DestinationFactory factory =
-                control.createMock(DestinationFactory.class);
-            Destination destination =
-                control.createMock(Destination.class);
-
-            bus.setExtension(mgr, DestinationFactoryManager.class);
-            mgr.getDestinationFactoryForUri(decoupledURL.toString());
-            EasyMock.expectLastCall().andReturn(factory);
-            factory.getDestination(EasyMock.isA(EndpointInfo.class));
-            EasyMock.expectLastCall().andReturn(destination);
-            destination.setMessageObserver(EasyMock.isA(HTTPConduit.InterposedMessageObserver.class));
-        }
+        assertEquals("Unexpected Authorization Token", 
+                "Basic " + Base64Utility.encode("Gandalf:staff".getBytes()),
+                headers.get("Authorization").get(0));
         
-        control.replay();
+        // Setting authorization policy on the message should override all.
+        AuthorizationPolicy authPolicy = new AuthorizationPolicy();
+        authPolicy.setUserName("Hello");
+        authPolicy.setPassword("world");
+        message = getNewMessage();
+        message.put(AuthorizationPolicy.class, authPolicy);
         
-        HTTPConduit conduit = new HTTPConduit(bus, 
-                                              endpointInfo,
-                                              null,
-                                              connectionFactory);
-        conduit.retrieveConnectionFactory();
-
-        if (send) {
-            conduit.getClient().setConnectionTimeout(303030);
-            conduit.getClient().setReceiveTimeout(404040);
-            if (httpConnection) {
-                conduit.getClient().setAutoRedirect(autoRedirect);
-                if (!autoRedirect) {
-                    conduit.getClient().setAllowChunking(true);
-                } 
-            }
-        }
-
-        if (decoupled) {
-            conduit.getClient().setDecoupledEndpoint(decoupledURL.toString());
-            assertNotNull("expected back channel", conduit.getBackChannel());
-        } else {
-            assertNull("unexpected back channel", conduit.getBackChannel());
-        }
-
-        observer = new MessageObserver() {
-            public void onMessage(Message m) {
-                inMessage = m;
-            }
-        };
-        conduit.setMessageObserver(observer);
-        return conduit;
-    }
-    
-    private void verifySentMessage(HTTPConduit conduit, Message message)
-        throws IOException {
-        verifySentMessage(conduit, message, false);
-    }
-
-    private void verifySentMessage(HTTPConduit conduit,
-                                   Message message,
-                                   boolean expectHeaders)
-        throws IOException {
-        verifySentMessage(conduit, message, expectHeaders, false);
-    }
-    
-    private void verifySentMessage(HTTPConduit conduit,
-                                   Message message,
-                                   boolean expectHeaders,
-                                   boolean decoupled)
-        throws IOException {
-        control.verify();
-        control.reset();
-                
-        OutputStream wrappedOS = verifyRequestHeaders(message, expectHeaders);
-        
-        if (connection instanceof HttpURLConnection) {
-            ((HttpURLConnection)connection).getRequestMethod();
-            EasyMock.expectLastCall().andReturn("POST");
-        }
+        conduit.prepare(message);
         
+        headers =
+            CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
         
-        os = EasyMock.createMock(ServletOutputStream.class);
-        connection.getOutputStream();
-        EasyMock.expectLastCall().andReturn(os);
-        os.write(PAYLOAD.getBytes(), 0, PAYLOAD.length());
-        EasyMock.expectLastCall();
-        
-        os.flush();
-        EasyMock.expectLastCall();
-        os.flush();
-        EasyMock.expectLastCall();
-        os.close();
-        EasyMock.expectLastCall();
+        assertEquals("Unexpected Authorization Token", 
+                "Basic " + Base64Utility.encode("Hello:world".getBytes()),
+                headers.get("Authorization").get(0));
+    }
+
+    public void testDecoupledEndpoint() throws Exception {
+        control = EasyMock.createNiceControl();
         
-        verifyHandleResponse(decoupled);
+        Bus bus = new CXFBusImpl();
 
+        URL decoupledURL = new URL("http://nowhere.com/response");
+        DestinationFactoryManager mgr =
+            control.createMock(DestinationFactoryManager.class);
+        DestinationFactory factory =
+            control.createMock(DestinationFactory.class);
+        Destination destination =
+            control.createMock(Destination.class);
+
+        bus.setExtension(mgr, DestinationFactoryManager.class);
+        mgr.getDestinationFactoryForUri(decoupledURL.toString());
+        EasyMock.expectLastCall().andReturn(factory);
+        factory.getDestination(EasyMock.isA(EndpointInfo.class));
+        EasyMock.expectLastCall().andReturn(destination);
+        destination.setMessageObserver(
+                EasyMock.isA(HTTPConduit.InterposedMessageObserver.class));
+        
         control.replay();
         
-        wrappedOS.flush();
-        wrappedOS.flush();
-        wrappedOS.close();
-        
-        assertNotNull("expected in message", inMessage);
-        Map<?, ?> headerMap = (Map<?, ?>) inMessage.get(Message.PROTOCOL_HEADERS);
-        assertEquals("unexpected response headers", headerMap.size(), 0);
-        Integer expectedResponseCode = decoupled 
-                                       ? HttpURLConnection.HTTP_ACCEPTED
-                                       : HttpURLConnection.HTTP_OK;
-        assertEquals("unexpected response code",
-                     expectedResponseCode,
-                     inMessage.get(Message.RESPONSE_CODE));
-        assertTrue("unexpected content formats",
-                   inMessage.getContentFormats().contains(InputStream.class));
-        assertSame("unexpected content", is, inMessage.getContent(InputStream.class));
+        EndpointInfo ei = new EndpointInfo();
+        ei.setAddress("http://nowhere.com/bar/foo");
+        HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+        conduit.finalizeConfig();
         
-        if (decoupled) {
-            verifyDecoupledResponse(conduit);
-        }
+        // Test call
+        conduit.getClient().setDecoupledEndpoint(decoupledURL.toString());
         
-        conduit.close();
+        assertNotNull("expected back channel", conduit.getBackChannel());
         
-        finalVerify();
-    }
+        MessageObserver observer = new MessageObserver() {
+            public void onMessage(Message m) {
+                inMessage = m;
+            }
+        };
+        
+        // Test call
+        conduit.setMessageObserver(observer);
 
-    private OutputStream verifyRequestHeaders(Message message, boolean expectHeaders)
-        throws IOException {
-        Map<String, List<String>> headers =
-            CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
-        assertNotNull("expected request headers set", headers);
-        assertTrue("expected output stream format",
-                   message.getContentFormats().contains(OutputStream.class));
-        OutputStream wrappedOS = message.getContent(OutputStream.class);
-        assertNotNull("expected output stream", wrappedOS);
-        
-        wrappedOS.write(PAYLOAD.getBytes());
-        
-        message.put(HTTPConduit.HTTP_CONNECTION, connection);
-        if (expectHeaders) {
-            connection.addRequestProperty(EasyMock.eq("Authorization"),
-                                          EasyMock.eq("Basic Qko6dmFsdWU="));            
-            EasyMock.expectLastCall();
-            connection.addRequestProperty(EasyMock.eq("content-type"),
-                                          EasyMock.eq("text/xml"));
-            EasyMock.expectLastCall();
-            connection.addRequestProperty(EasyMock.eq("content-type"),
-                                          EasyMock.eq("charset=utf8"));
-            EasyMock.expectLastCall();
-        }
-        return wrappedOS;
-    }
-    
-    private void verifyHandleResponse(boolean decoupled) throws IOException {
-        connection.getHeaderFields();
-        EasyMock.expectLastCall().andReturn(Collections.EMPTY_MAP);
-        int responseCode = decoupled 
-                           ? HttpURLConnection.HTTP_ACCEPTED
-                           : HttpURLConnection.HTTP_OK;
-        if (connection instanceof HttpURLConnection) {
-            ((HttpURLConnection)connection).getResponseCode();
-            EasyMock.expectLastCall().andReturn(responseCode);
-            ((HttpURLConnection)connection).getErrorStream();
-            EasyMock.expectLastCall().andReturn(null);
-        } else {
-            connection.getHeaderField(Message.RESPONSE_CODE);
-            String responseString = Integer.toString(responseCode);
-            EasyMock.expectLastCall().andReturn(responseString).times(2);
-        }
-        is = EasyMock.createMock(ServletInputStream.class);
-        connection.getInputStream();
-        EasyMock.expectLastCall().andReturn(is);
-    }
-    
-    private void verifyDecoupledResponse(HTTPConduit conduit)
-        throws IOException {
         Message incoming = new MessageImpl();
         conduit.getDecoupledObserver().onMessage(incoming);
+       
         assertSame("expected pass thru onMessage() notification",
                    inMessage,
                    incoming);
@@ -411,6 +267,12 @@
         assertEquals("unexpected Message.ASYNC_POST_RESPONSE_DISPATCH set",
                      false,
                      inMessage.containsKey(Message.ASYNC_POST_RESPONSE_DISPATCH));
+
+        // avoid intermittent spurious failures on EasyMock detecting finalize
+        // calls by mocking up only class data members (no local variables)
+        // and explicitly making available for GC post-verify
+        finalVerify();
+        inMessage = null;
     }
 
     private void finalVerify() {
@@ -420,7 +282,4 @@
         }
     }
     
-    static EndpointReferenceType getEPR(String s) {
-        return EndpointReferenceUtils.getEndpointReference(NOWHERE + s);
-    }
 }

Added: incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLConnectionTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLConnectionTest.java?view=auto&rev=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLConnectionTest.java (added)
+++ incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLConnectionTest.java Tue Apr 17 05:47:13 2007
@@ -0,0 +1,144 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.transport.http;
+
+import java.net.HttpURLConnection;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.HttpsURLConnection;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.bus.CXFBusImpl;
+import org.apache.cxf.configuration.security.SSLClientPolicy;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * This class "tests" the HTTPConduit that uses java.net.HttpURLConnection
+ * and java.net.HttpsURLConnection for its implementation. Should the
+ * implementation of HTTPConduit change (i.e. no longer use the URLConnections)
+ * this test will break.
+ */
+public class HTTPConduitURLConnectionTest extends Assert {
+    
+    @Before
+    public void setUp() throws Exception {
+    }
+    
+    @After
+    public void tearDown() {
+    }
+
+    /**
+     * Generates a new message.
+     */
+    private Message getNewMessage() {
+        Message message = new MessageImpl();
+        Map<String, List<String>> headers = new HashMap<String, List<String>>();
+        List<String> contentTypes = new ArrayList<String>();
+        contentTypes.add("text/xml");
+        contentTypes.add("charset=utf8");
+        headers.put("content-type", contentTypes);
+        message.put(Message.PROTOCOL_HEADERS, headers);
+        return message;
+    }
+
+
+    /**
+     * This test verifies that the "prepare" call places an HttpURLConnection on 
+     * the Message and that its URL matches the endpoint.
+     */
+    @Test
+    public void testConnectionURL() throws Exception {
+        Bus bus = new CXFBusImpl();
+        EndpointInfo ei = new EndpointInfo();
+        ei.setAddress("http://nowhere.com/bar/foo");
+        HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+        conduit.finalizeConfig();
+    
+        Message message = getNewMessage();
+        
+        conduit.prepare(message);
+        
+        HttpURLConnection con = 
+            (HttpURLConnection) message.get("http.connection");
+        assertEquals("Unexpected URL address",
+                con.getURL().toString(),
+                ei.getAddress());
+    }
+
+    /**
+     * This test verifies that URL used is overridden by having the 
+     * ENDPOINT_ADDRESS set on the Message.
+     */
+    @Test
+    public void testConnectionURLOverride() throws Exception {
+        Bus bus = new CXFBusImpl();
+        EndpointInfo ei = new EndpointInfo();
+        ei.setAddress("http://nowhere.null/bar/foo");
+        HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+        conduit.finalizeConfig();
+    
+        Message message = getNewMessage();
+        message.put(Message.ENDPOINT_ADDRESS, "http://somewhere.different/");
+        
+        // Test call
+        conduit.prepare(message);
+        
+        HttpURLConnection con = 
+            (HttpURLConnection) message.get("http.connection");
+        assertEquals("Unexpected URL address",
+                con.getURL().toString(),
+                "http://somewhere.different/");
+    }
+
+    /**
+     * This verifys that the underlying connection is an HttpsURLConnection.
+     */
+    @Test
+    public void testSslClientPolicy() throws Exception {
+        Bus bus = new CXFBusImpl();
+        EndpointInfo ei = new EndpointInfo();
+        ei.setAddress("https://secure.nowhere.null/" + "bar/foo");
+        HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+        conduit.finalizeConfig();
+    
+        Message message = getNewMessage();
+        // We need an SSL policy, or we can't use "https".
+        conduit.setSslClient(new SSLClientPolicy());
+        
+        // Test call
+        conduit.prepare(message);
+        
+        assertTrue("SSL Client Policy should generate an HttpsURLConnection",
+                HttpsURLConnection.class.isInstance(
+                        message.get("http.connection")));
+    }
+
+
+}

Propchange: incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLConnectionTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLEasyMockTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLEasyMockTest.java?view=auto&rev=529583
==============================================================================
--- incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLEasyMockTest.java (added)
+++ incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLEasyMockTest.java Tue Apr 17 05:47:13 2007
@@ -0,0 +1,422 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.transport.http;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.Proxy;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.bus.CXFBusImpl;
+import org.apache.cxf.configuration.security.AuthorizationPolicy;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.Destination;
+import org.apache.cxf.transport.DestinationFactory;
+import org.apache.cxf.transport.DestinationFactoryManager;
+import org.apache.cxf.transport.MessageObserver;
+import org.apache.cxf.ws.addressing.EndpointReferenceType;
+import org.easymock.classextension.EasyMock;
+import org.easymock.classextension.IMocksControl;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.apache.cxf.message.Message.DECOUPLED_CHANNEL_MESSAGE;
+
+/**
+ */
+public class HTTPConduitURLEasyMockTest extends Assert {
+
+    private static final String NOWHERE = "http://nada.nothing.nowhere.null/";
+    private static final String PAYLOAD = "message payload";
+    private IMocksControl control;
+    private EndpointInfo endpointInfo;
+    private HttpURLConnectionFactory connectionFactory;
+    private HttpURLConnection connection;
+    private Proxy proxy;
+    private Message inMessage;
+    private MessageObserver observer;
+    private ServletOutputStream os;
+    private ServletInputStream is;
+    
+    /**
+     * This is an extension to the HTTPConduit that replaces
+     * the dynamic assignment of the HttpURLConnectionFactory,
+     * and we just use the EasyMocked version for this test.
+     */
+    private class HTTPTestConduit extends HTTPConduit {
+        HTTPTestConduit(
+            Bus                      associatedBus, 
+            EndpointInfo             endpoint, 
+            EndpointReferenceType    epr,
+            HttpURLConnectionFactory testFactory
+        ) throws IOException {
+            super(associatedBus, endpoint, epr);
+            connectionFactory = testFactory;
+        }
+        @Override
+        protected void retrieveConnectionFactory() {
+            // do nothing. i.e do not change the connectionFactory field.
+        }
+    }
+    /**
+     * @throws java.lang.Exception
+     */
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    /**
+     * @throws java.lang.Exception
+     */
+    @After
+    public void tearDown() throws Exception {
+        // avoid intermittent spurious failures on EasyMock detecting finalize
+        // calls by mocking up only class data members (no local variables)
+        // and explicitly making available for GC post-verify
+        connectionFactory = null;
+        connection = null;
+        proxy = null;
+        inMessage = null;
+        observer = null;
+        os = null;
+        is = null;
+    }
+
+
+    @Test
+    public void testSend() throws Exception {
+        control = EasyMock.createNiceControl();
+        HTTPConduit conduit = setUpConduit(true, false, false);
+        Message message = new MessageImpl();
+        conduit.prepare(message);
+        verifySentMessage(conduit, message);
+        finalVerify();
+    }
+    
+    @Test
+    public void testSendWithHeaders() throws Exception {
+        control = EasyMock.createNiceControl();
+        HTTPConduit conduit = setUpConduit(true, false, false);
+        Message message = new MessageImpl();
+        setUpHeaders(message);
+        conduit.prepare(message);
+        verifySentMessage(conduit, message, true);
+        finalVerify();
+    }
+    
+    @Test
+    public void testSendHttpConnection() throws Exception {
+        control = EasyMock.createNiceControl();
+        HTTPConduit conduit = setUpConduit(true, false, false);
+        Message message = new MessageImpl();
+        conduit.prepare(message);
+        verifySentMessage(conduit, message);
+        finalVerify();
+    }
+
+    @Test
+    public void testSendHttpConnectionAutoRedirect() throws Exception {
+        control = EasyMock.createNiceControl();
+        HTTPConduit conduit = setUpConduit(true, true, false);
+        Message message = new MessageImpl();
+        conduit.prepare(message);
+        verifySentMessage(conduit, message);
+        finalVerify();
+    }
+    
+    @Test
+    public void testSendDecoupled() throws Exception {
+        control = EasyMock.createNiceControl();
+        HTTPConduit conduit = setUpConduit(true, false, true);
+        Message message = new MessageImpl();
+        conduit.prepare(message);
+        verifySentMessage(conduit, message, false, true);
+        finalVerify();
+    }
+    
+    
+    private void setUpHeaders(Message message) {
+        Map<String, List<String>> headers = new HashMap<String, List<String>>();
+        List<String> contentTypes = new ArrayList<String>();
+        contentTypes.add("text/xml");
+        contentTypes.add("charset=utf8");
+        headers.put("content-type", contentTypes);
+        message.put(Message.PROTOCOL_HEADERS, headers);
+        
+        AuthorizationPolicy authPolicy = new AuthorizationPolicy();
+        authPolicy.setUserName("BJ");
+        authPolicy.setPassword("value");
+        message.put(AuthorizationPolicy.class, authPolicy);        
+    }
+
+
+    private HTTPConduit setUpConduit(
+        boolean send,
+        boolean autoRedirect,
+        boolean decoupled
+    ) throws Exception {
+        endpointInfo = new EndpointInfo();
+        endpointInfo.setAddress(NOWHERE + "bar/foo");
+        connectionFactory = 
+            control.createMock(HttpURLConnectionFactory.class);
+        
+        if (send) {
+            //proxy = control.createMock(Proxy.class);
+            proxy =  null;
+            connection =
+                control.createMock(HttpURLConnection.class);
+            connectionFactory.createConnection(
+                                      EasyMock.eq(proxy), 
+                                      EasyMock.eq(new URL(NOWHERE + "bar/foo")));
+            
+            EasyMock.expectLastCall().andReturn(connection);
+            connection.setDoOutput(true);
+            EasyMock.expectLastCall();
+            
+            connection.setRequestMethod("POST");
+            EasyMock.expectLastCall();
+            
+            if (!autoRedirect) {
+                connection.getRequestMethod();
+                EasyMock.expectLastCall().andReturn("POST");
+                connection.setChunkedStreamingMode(2048);
+                EasyMock.expectLastCall();                    
+            }
+
+            connection.setConnectTimeout(303030);
+            EasyMock.expectLastCall();
+            connection.setReadTimeout(404040);
+            EasyMock.expectLastCall();
+            connection.setUseCaches(false);
+            EasyMock.expectLastCall();
+            
+        }
+
+        CXFBusImpl bus = new CXFBusImpl();
+        URL decoupledURL = null;
+        if (decoupled) {
+            decoupledURL = new URL(NOWHERE + "response");
+            DestinationFactoryManager mgr =
+                control.createMock(DestinationFactoryManager.class);
+            DestinationFactory factory =
+                control.createMock(DestinationFactory.class);
+            Destination destination =
+                control.createMock(Destination.class);
+
+            bus.setExtension(mgr, DestinationFactoryManager.class);
+            mgr.getDestinationFactoryForUri(decoupledURL.toString());
+            EasyMock.expectLastCall().andReturn(factory);
+            factory.getDestination(EasyMock.isA(EndpointInfo.class));
+            EasyMock.expectLastCall().andReturn(destination);
+            destination.setMessageObserver(EasyMock.isA(HTTPConduit.InterposedMessageObserver.class));
+        }
+        
+        control.replay();
+        
+        HTTPConduit conduit = new HTTPTestConduit(bus, 
+                                              endpointInfo,
+                                              null,
+                                              connectionFactory);
+        conduit.finalizeConfig();
+
+        if (send) {
+            conduit.getClient().setConnectionTimeout(303030);
+            conduit.getClient().setReceiveTimeout(404040);
+            conduit.getClient().setAutoRedirect(autoRedirect);
+            if (!autoRedirect) {
+                conduit.getClient().setAllowChunking(true);
+            }
+        }
+
+        if (decoupled) {
+            conduit.getClient().setDecoupledEndpoint(decoupledURL.toString());
+            assertNotNull("expected back channel", conduit.getBackChannel());
+        } else {
+            assertNull("unexpected back channel", conduit.getBackChannel());
+        }
+
+        observer = new MessageObserver() {
+            public void onMessage(Message m) {
+                inMessage = m;
+            }
+        };
+        conduit.setMessageObserver(observer);
+        return conduit;
+    }
+    
+
+    private void verifySentMessage(HTTPConduit conduit, Message message)
+        throws IOException {
+        verifySentMessage(conduit, message, false);
+    }
+
+    private void verifySentMessage(HTTPConduit conduit,
+                                   Message message,
+                                   boolean expectHeaders)
+        throws IOException {
+        verifySentMessage(conduit, message, expectHeaders, false);
+    }
+    
+    private void verifySentMessage(HTTPConduit conduit,
+                                   Message message,
+                                   boolean expectHeaders,
+                                   boolean decoupled)
+        throws IOException {
+        control.verify();
+        control.reset();
+                
+        OutputStream wrappedOS = verifyRequestHeaders(message, expectHeaders);
+        
+        connection.getRequestMethod();
+        EasyMock.expectLastCall().andReturn("POST");
+        
+        os = EasyMock.createMock(ServletOutputStream.class);
+        connection.getOutputStream();
+        EasyMock.expectLastCall().andReturn(os);
+        os.write(PAYLOAD.getBytes(), 0, PAYLOAD.length());
+        EasyMock.expectLastCall();
+        
+        os.flush();
+        EasyMock.expectLastCall();
+        os.flush();
+        EasyMock.expectLastCall();
+        os.close();
+        EasyMock.expectLastCall();
+        
+        verifyHandleResponse(decoupled);
+
+        control.replay();
+        
+        wrappedOS.flush();
+        wrappedOS.flush();
+        wrappedOS.close();
+        
+        assertNotNull("expected in message", inMessage);
+        Map<?, ?> headerMap = (Map<?, ?>) inMessage.get(Message.PROTOCOL_HEADERS);
+        assertEquals("unexpected response headers", headerMap.size(), 0);
+        Integer expectedResponseCode = decoupled 
+                                       ? HttpURLConnection.HTTP_ACCEPTED
+                                       : HttpURLConnection.HTTP_OK;
+        assertEquals("unexpected response code",
+                     expectedResponseCode,
+                     inMessage.get(Message.RESPONSE_CODE));
+        assertTrue("unexpected content formats",
+                   inMessage.getContentFormats().contains(InputStream.class));
+        assertSame("unexpected content", is, inMessage.getContent(InputStream.class));
+        
+        if (decoupled) {
+            verifyDecoupledResponse(conduit);
+        }
+        
+        conduit.close();
+        
+        finalVerify();
+    }
+
+    private OutputStream verifyRequestHeaders(Message message, boolean expectHeaders)
+        throws IOException {
+        Map<String, List<String>> headers =
+            CastUtils.cast((Map<?, ?>)message.get(Message.PROTOCOL_HEADERS));
+        assertNotNull("expected request headers set", headers);
+        assertTrue("expected output stream format",
+                   message.getContentFormats().contains(OutputStream.class));
+        OutputStream wrappedOS = message.getContent(OutputStream.class);
+        assertNotNull("expected output stream", wrappedOS);
+        
+        wrappedOS.write(PAYLOAD.getBytes());
+        
+        message.put(HTTPConduit.KEY_HTTP_CONNECTION, connection);
+        if (expectHeaders) {
+            connection.addRequestProperty(EasyMock.eq("Authorization"),
+                                          EasyMock.eq("Basic Qko6dmFsdWU="));            
+            EasyMock.expectLastCall();
+            connection.addRequestProperty(EasyMock.eq("content-type"),
+                                          EasyMock.eq("text/xml"));
+            EasyMock.expectLastCall();
+            connection.addRequestProperty(EasyMock.eq("content-type"),
+                                          EasyMock.eq("charset=utf8"));
+            EasyMock.expectLastCall();
+        }
+        return wrappedOS;
+    }
+    
+    private void verifyHandleResponse(boolean decoupled) throws IOException {
+        connection.getHeaderFields();
+        EasyMock.expectLastCall().andReturn(Collections.EMPTY_MAP);
+        int responseCode = decoupled 
+                           ? HttpURLConnection.HTTP_ACCEPTED
+                           : HttpURLConnection.HTTP_OK;
+        connection.getResponseCode();
+        EasyMock.expectLastCall().andReturn(responseCode).anyTimes();
+        connection.getErrorStream();
+        EasyMock.expectLastCall().andReturn(null);
+        is = EasyMock.createMock(ServletInputStream.class);
+        connection.getInputStream();
+        EasyMock.expectLastCall().andReturn(is);
+    }
+    
+    private void verifyDecoupledResponse(HTTPConduit conduit)
+        throws IOException {
+        Message incoming = new MessageImpl();
+        conduit.getDecoupledObserver().onMessage(incoming);
+        assertSame("expected pass thru onMessage() notification",
+                   inMessage,
+                   incoming);
+        assertEquals("unexpected response code",
+                     HttpURLConnection.HTTP_OK,
+                     inMessage.get(Message.RESPONSE_CODE));
+        assertEquals("expected DECOUPLED_CHANNEL_MESSAGE flag set",
+                     Boolean.TRUE,
+                     inMessage.get(DECOUPLED_CHANNEL_MESSAGE));
+        assertEquals("unexpected HTTP_REQUEST set",
+                     false,
+                     inMessage.containsKey(AbstractHTTPDestination.HTTP_REQUEST));
+        assertEquals("unexpected HTTP_RESPONSE set",
+                     false,
+                     inMessage.containsKey(AbstractHTTPDestination.HTTP_RESPONSE));
+        assertEquals("unexpected Message.ASYNC_POST_RESPONSE_DISPATCH set",
+                     false,
+                     inMessage.containsKey(Message.ASYNC_POST_RESPONSE_DISPATCH));
+    }
+
+    private void finalVerify() {
+        if (control != null) {
+            control.verify();
+            control = null;
+        }
+    }
+    
+}

Propchange: incubator/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLEasyMockTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message