You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by dk...@apache.org on 2012/07/25 22:48:50 UTC
svn commit: r1365733 [1/2] - in /cxf/trunk/rt/transports/http/src:
main/java/org/apache/cxf/transport/http/
main/java/org/apache/cxf/transport/http/auth/
test/java/org/apache/cxf/transport/http/
Author: dkulp
Date: Wed Jul 25 20:48:50 2012
New Revision: 1365733
URL: http://svn.apache.org/viewvc?rev=1365733&view=rev
Log:
Pull the HttpURLConnection stuff out of HTTPConduit and into a subclass
Should allow easier subclassing of HTTPConduit with new implementations
Added:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/URLConnectionHTTPConduit.java
Removed:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/TrustDecisionUtil.java
Modified:
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPTransportFactory.java
cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/HttpAuthHeader.java
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLConnectionTest.java
cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLEasyMockTest.java
Modified: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java?rev=1365733&r1=1365732&r2=1365733&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java (original)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java Wed Jul 25 20:48:50 2012
@@ -27,16 +27,12 @@ import java.io.OutputStream;
import java.net.HttpRetryException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
-import java.net.Proxy;
import java.net.URL;
-import java.net.URLConnection;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.concurrent.RejectedExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -45,7 +41,6 @@ import javax.xml.namespace.QName;
import org.apache.cxf.Bus;
import org.apache.cxf.common.injection.NoJSR250Annotations;
import org.apache.cxf.common.logging.LogUtils;
-import org.apache.cxf.common.util.SystemPropertyAction;
import org.apache.cxf.configuration.Configurable;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.configuration.security.AuthorizationPolicy;
@@ -65,7 +60,6 @@ import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageContentsList;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.message.MessageUtils;
-import org.apache.cxf.phase.PhaseInterceptorChain;
import org.apache.cxf.policy.PolicyDataEngine;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.transport.AbstractConduit;
@@ -80,15 +74,10 @@ import org.apache.cxf.transport.http.pol
import org.apache.cxf.transport.https.CertConstraints;
import org.apache.cxf.transport.https.CertConstraintsInterceptor;
import org.apache.cxf.transport.https.CertConstraintsJaxBUtils;
-import org.apache.cxf.transport.https.HttpsURLConnectionFactory;
+import org.apache.cxf.transport.https.HttpsURLConnectionInfo;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
-import org.apache.cxf.workqueue.AutomaticWorkQueue;
-import org.apache.cxf.workqueue.WorkQueueManager;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
-import static org.apache.cxf.message.Message.DECOUPLED_CHANNEL_MESSAGE;
-
-
/*
* HTTP Conduit implementation.
* <p>
@@ -145,10 +134,11 @@ import static org.apache.cxf.message.Mes
* configuration.
*/
@NoJSR250Annotations
-public class HTTPConduit
+public abstract class HTTPConduit
extends AbstractConduit
implements Configurable, Assertor, PropertyChangeListener {
+
/**
* This constant is the Message(Map) key for the HttpURLConnection that
* is used to get the response.
@@ -156,24 +146,11 @@ public class HTTPConduit
public static final String KEY_HTTP_CONNECTION = "http.connection";
/**
- * This constant is the Message(Map) key for a list of visited URLs that
- * is used in redirect loop protection.
- */
- private static final String KEY_VISITED_URLS = "VisitedURLs";
-
- /**
- * This constant is the Message(Map) key for a list of URLs that
- * is used in authorization loop protection.
- */
- private static final String KEY_AUTH_URLS = "AuthURLs";
-
- /**
* The Logger for this class.
*/
- private static final Logger LOG = LogUtils.getL7dLogger(HTTPConduit.class);
-
- private static boolean hasLoggedAsyncWarning;
+ protected static final Logger LOG = LogUtils.getL7dLogger(HTTPConduit.class);
+
/**
* This constant holds the suffix ".http-conduit" that is appended to the
* Endpoint Qname to give the configuration name of this conduit.
@@ -184,19 +161,21 @@ public class HTTPConduit
private static final String HTTP_PUT_METHOD = "PUT";
/**
- * This field holds the connection factory, which primarily is used to
- * factor out SSL specific code from this implementation.
- * <p>
- * This field is "protected" to facilitate some contrived UnitTesting so
- * that an extended class may alter its value with an EasyMock URLConnection
- * Factory.
+ * This constant is the Message(Map) key for a list of visited URLs that
+ * is used in redirect loop protection.
+ */
+ private static final String KEY_VISITED_URLS = "VisitedURLs";
+
+ /**
+ * This constant is the Message(Map) key for a list of URLs that
+ * is used in authorization loop protection.
*/
- protected HttpsURLConnectionFactory connectionFactory;
+ private static final String KEY_AUTH_URLS = "AuthURLs";
/**
* This field holds a reference to the CXF bus associated this conduit.
*/
- private final Bus bus;
+ protected final Bus bus;
/**
* This field is used for two reasons. First it provides the base name for
@@ -204,18 +183,18 @@ public class HTTPConduit
* address information, should it not be supplied in the Message Map, by the
* Message.ENDPOINT_ADDRESS property.
*/
- private final EndpointInfo endpointInfo;
+ protected final EndpointInfo endpointInfo;
/**
* This field holds the "default" URL for this particular conduit, which
* is created on demand.
*/
- private URL defaultEndpointURL;
- private String defaultEndpointURLString;
- private boolean fromEndpointReferenceType;
+ protected URL defaultEndpointURL;
+ protected String defaultEndpointURLString;
+ protected boolean fromEndpointReferenceType;
- private ProxyFactory proxyFactory;
+ protected ProxyFactory proxyFactory;
// Configurable values
@@ -224,48 +203,48 @@ public class HTTPConduit
* This field is injected via spring configuration based on the conduit
* name.
*/
- private HTTPClientPolicy clientSidePolicy;
+ protected HTTPClientPolicy clientSidePolicy;
/**
* This field holds the password authorization configuration.
* This field is injected via spring configuration based on the conduit
* name.
*/
- private AuthorizationPolicy authorizationPolicy;
+ protected AuthorizationPolicy authorizationPolicy;
/**
* This field holds the password authorization configuration for the
* configured proxy. This field is injected via spring configuration based
* on the conduit name.
*/
- private ProxyAuthorizationPolicy proxyAuthorizationPolicy;
+ protected ProxyAuthorizationPolicy proxyAuthorizationPolicy;
/**
* This field holds the configuration TLS configuration which
* is programmatically configured.
*/
- private TLSClientParameters tlsClientParameters;
+ protected TLSClientParameters tlsClientParameters;
/**
* This field contains the MessageTrustDecider.
*/
- private MessageTrustDecider trustDecider;
+ protected MessageTrustDecider trustDecider;
/**
* Implements the authentication handling when talking to a server. If it is not set
* it will be created from the authorizationPolicy.authType
*/
- private HttpAuthSupplier authSupplier;
+ protected HttpAuthSupplier authSupplier;
/**
* Implements the proxy authentication handling. If it is not set
* it will be created from the proxyAuthorizationPolicy.authType
*/
- private HttpAuthSupplier proxyAuthSupplier;
+ protected HttpAuthSupplier proxyAuthSupplier;
- private Cookies cookies;
+ protected Cookies cookies;
- private CertConstraints certConstraints;
+ protected CertConstraints certConstraints;
/**
* Constructor
@@ -300,10 +279,8 @@ public class HTTPConduit
fromEndpointReferenceType = true;
}
proxyFactory = new ProxyFactory();
- connectionFactory = new HttpsURLConnectionFactory();
cookies = new Cookies();
updateClientPolicy();
- CXFAuthenticator.addAuthenticator();
}
/**
@@ -416,7 +393,7 @@ public class HTTPConduit
* causes an injection of the Spring configuration properties
* of this Conduit.
*/
- protected void finalizeConfig() {
+ public void finalizeConfig() {
// See if not set by configuration, if there are defaults
// in order from the Endpoint, Service, or Bus.
@@ -441,11 +418,8 @@ public class HTTPConduit
return cookies.getSessionCookies();
}
- private HttpURLConnection createConnection(Message message, URL url) throws IOException {
- HTTPClientPolicy csPolicy = getClient(message);
- Proxy proxy = proxyFactory.createProxy(csPolicy , url);
- return connectionFactory.createConnection(tlsClientParameters, proxy, url);
- }
+
+ protected abstract void setupConnection(Message message, URL url, HTTPClientPolicy csPolicy) throws IOException;
/**
* Prepare to send an outbound HTTP message over this http conduit to a
@@ -478,25 +452,15 @@ public class HTTPConduit
boolean needToCacheRequest = false;
HTTPClientPolicy csPolicy = getClient(message);
- HttpURLConnection connection = createConnection(message, currentURL);
- connection.setDoOutput(true);
-
- int ctimeout = determineConnectionTimeout(message, csPolicy);
- connection.setConnectTimeout(ctimeout);
-
- int rtimeout = determineReceiveTimeout(message, csPolicy);
- connection.setReadTimeout(rtimeout);
-
- connection.setUseCaches(false);
- // We implement redirects in this conduit. We do not
- // rely on the underlying URLConnection implementation
- // because of trust issues.
- connection.setInstanceFollowRedirects(false);
+ setupConnection(message, currentURL, csPolicy);
// If the HTTP_REQUEST_METHOD is not set, the default is "POST".
String httpRequestMethod =
- (String)message.get(Message.HTTP_REQUEST_METHOD);
- connection.setRequestMethod((null != httpRequestMethod) ? httpRequestMethod : "POST");
+ (String)message.get(Message.HTTP_REQUEST_METHOD);
+ if (httpRequestMethod == null) {
+ httpRequestMethod = "POST";
+ message.put(Message.HTTP_REQUEST_METHOD, "POST");
+ }
boolean isChunking = false;
int chunkThreshold = 0;
@@ -528,16 +492,12 @@ public class HTTPConduit
// if chunking is enabled
// TODO : ensure chunking can be enabled for non-empty PUTs - if requested
if (csPolicy.isAllowChunking()
- && isChunkingSupported(message, connection.getRequestMethod())) {
+ && isChunkingSupported(message, httpRequestMethod)) {
//TODO: The chunking mode be configured or at least some
// documented client constant.
//use -1 and allow the URL connection to pick a default value
isChunking = true;
chunkThreshold = csPolicy.getChunkingThreshold();
- if (chunkThreshold <= 0) {
- chunkThreshold = 0;
- connection.setChunkedStreamingMode(-1);
- }
}
cookies.writeToMessageHeaders(message);
@@ -545,9 +505,7 @@ public class HTTPConduit
// The trust decision is relegated to after the "flushing" of the
// request headers.
- // We place the connection on the message to pick it up
- // in the WrappedOutputStream.
- message.put(KEY_HTTP_CONNECTION, connection);
+
if (certConstraints != null) {
message.put(CertConstraints.class.getName(), certConstraints);
@@ -557,7 +515,7 @@ public class HTTPConduit
setHeadersByAuthorizationPolicy(message, currentURL);
new Headers(message).setFromClientPolicy(getClient(message));
message.setContent(OutputStream.class,
- createOutputStream(message, connection,
+ createOutputStream(message,
needToCacheRequest,
isChunking,
chunkThreshold));
@@ -581,18 +539,11 @@ public class HTTPConduit
return false;
}
- protected OutputStream createOutputStream(Message message,
- HttpURLConnection connection,
- boolean needToCacheRequest,
- boolean isChunking,
- int chunkThreshold) {
- return new WrappedOutputStream(message, connection,
- needToCacheRequest,
- isChunking,
- chunkThreshold,
- getConduitName());
- }
-
+ protected abstract OutputStream createOutputStream(Message message,
+ boolean needToCacheRequest,
+ boolean isChunking,
+ int chunkThreshold) throws IOException;
+
private HttpAuthSupplier createAuthSupplier(String authType) {
if (HttpAuthHeader.AUTH_TYPE_NEGOTIATE.equals(authType)) {
return new SpnegoAuthSupplier();
@@ -603,7 +554,7 @@ public class HTTPConduit
}
}
- private static int determineReceiveTimeout(Message message,
+ protected static int determineReceiveTimeout(Message message,
HTTPClientPolicy csPolicy) {
long rtimeout = csPolicy.getReceiveTimeout();
if (message.get(Message.RECEIVE_TIMEOUT) != null) {
@@ -622,7 +573,7 @@ public class HTTPConduit
return (int)rtimeout;
}
- private static int determineConnectionTimeout(Message message,
+ protected static int determineConnectionTimeout(Message message,
HTTPClientPolicy csPolicy) {
long ctimeout = csPolicy.getConnectionTimeout();
if (message.get(Message.CONNECTION_TIMEOUT) != null) {
@@ -705,19 +656,7 @@ public class HTTPConduit
/**
* Close the conduit
*/
- public void close() {
- if (defaultEndpointURL != null) {
- try {
- URLConnection connect = defaultEndpointURL.openConnection();
- if (connect instanceof HttpURLConnection) {
- ((HttpURLConnection)connect).disconnect();
- }
- } catch (IOException ex) {
- //ignore
- }
- //defaultEndpointURL = null;
- }
-
+ public void close() {
if (clientSidePolicy != null) {
clientSidePolicy.removePropertyChangeListener(this);
}
@@ -726,7 +665,7 @@ public class HTTPConduit
/**
* @return the default target address
*/
- protected String getAddress() {
+ public String getAddress() {
if (defaultEndpointURL != null) {
return defaultEndpointURLString;
} else if (fromEndpointReferenceType) {
@@ -785,7 +724,7 @@ public class HTTPConduit
* @param message
* @param headers
*/
- private void setHeadersByAuthorizationPolicy(
+ protected void setHeadersByAuthorizationPolicy(
Message message,
URL url
) {
@@ -981,265 +920,6 @@ public class HTTPConduit
this.proxyAuthSupplier = proxyAuthSupplier;
}
- /**
- * This function processes any retransmits at the direction of redirections
- * or "unauthorized" responses.
- * <p>
- * If the request was not retransmitted, it returns the given connection.
- * If the request was retransmitted, it returns the new connection on
- * which the request was sent.
- *
- * @param connection The active URL connection.
- * @param message The outgoing message.
- * @param cachedStream The cached request.
- * @return
- * @throws IOException
- */
- private HttpURLConnection processRetransmit(
- final HttpURLConnection origConnection,
- Message message,
- CacheAndWriteOutputStream cachedStream
- ) throws IOException {
-
- int responseCode = origConnection.getResponseCode();
- if ((message != null) && (message.getExchange() != null)) {
- message.getExchange().put(Message.RESPONSE_CODE, responseCode);
- }
- HttpURLConnection connection = origConnection;
- // Process Redirects first.
- switch(responseCode) {
- case HttpURLConnection.HTTP_MOVED_PERM:
- case HttpURLConnection.HTTP_MOVED_TEMP:
- case HttpURLConnection.HTTP_SEE_OTHER:
- case 307:
- connection = redirectRetransmit(origConnection, message, cachedStream);
- break;
- case HttpURLConnection.HTTP_UNAUTHORIZED:
- connection = authorizationRetransmit(origConnection, message, cachedStream);
- break;
- default:
- break;
- }
- return connection;
- }
-
- /**
- * This method performs a redirection retransmit in response to
- * a 302 or 305 response code.
- *
- * @param connection The active URL connection
- * @param message The outbound message.
- * @param cachedStream The cached request.
- * @return This method returns the new HttpURLConnection if
- * redirected. If it cannot be redirected for some reason
- * the same connection is returned.
- *
- * @throws IOException
- */
- private HttpURLConnection redirectRetransmit(
- HttpURLConnection connection,
- Message message,
- CacheAndWriteOutputStream cachedStream
- ) throws IOException {
-
- // If we are not redirecting by policy, then we don't.
- if (!getClient(message).isAutoRedirect()) {
- return connection;
- }
- URL newURL = extractLocation(connection.getHeaderFields());
- detectRedirectLoop(getConduitName(), connection.getURL(), newURL, message);
- if (newURL != null) {
- new Headers(message).removeAuthorizationHeaders();
-
- // If user configured this Conduit with preemptive authorization
- // it is meant to make it to the end. (Too bad that information
- // went to every URL along the way, but that's what the user
- // wants!
- // TODO: Make this issue a security release note.
- setHeadersByAuthorizationPolicy(message, newURL);
- connection.disconnect();
- return retransmit(newURL, message, cachedStream);
- }
- return connection;
- }
-
- /**
- * This method performs a retransmit for authorization information.
- *
- * @param connection The currently active connection.
- * @param message The outbound message.
- * @param cachedStream The cached request.
- * @return A new connection if retransmitted. If not retransmitted
- * then this method returns the same connection.
- * @throws IOException
- */
- private HttpURLConnection authorizationRetransmit(
- HttpURLConnection connection,
- Message message,
- CacheAndWriteOutputStream cachedStream
- ) throws IOException {
- HttpAuthHeader authHeader = new HttpAuthHeader(connection.getHeaderField("WWW-Authenticate"));
- URL currentURL = connection.getURL();
- String realm = authHeader.getRealm();
- detectAuthorizationLoop(getConduitName(), message, currentURL, realm);
- AuthorizationPolicy effectiveAthPolicy = getEffectiveAuthPolicy(message);
- String authorizationToken =
- authSupplier.getAuthorization(
- effectiveAthPolicy, currentURL, message, authHeader.getFullHeader());
- if (authorizationToken == null) {
- // authentication not possible => we give up
- return connection;
- }
- try {
- //try and consume any content so that the connection might be reusable
- InputStream ins = connection.getErrorStream();
- if (ins == null) {
- ins = connection.getInputStream();
- }
- if (ins != null) {
- IOUtils.consume(ins);
- ins.close();
- }
- } catch (Throwable t) {
- //ignore
- }
- new Headers(message).setAuthorization(authorizationToken);
- cookies.writeToMessageHeaders(message);
- return retransmit(currentURL, message, cachedStream);
- }
-
- /**
- * This method retransmits the request.
- *
- * @param connection The currently active connection.
- * @param newURL The newURL to connection to.
- * @param message The outbound message.
- * @param stream The cached request.
- * @return This function returns a new connection if
- * retransmitted, otherwise it returns the given
- * connection.
- *
- * @throws IOException
- */
- private HttpURLConnection retransmit(
- URL newURL,
- Message message,
- CacheAndWriteOutputStream stream
- ) throws IOException {
- HTTPClientPolicy cp = getClient(message);
- HttpURLConnection connection = createConnection(message, newURL);
- connection.setDoOutput(true);
- // TODO: using Message context to decided HTTP send properties
- connection.setConnectTimeout((int)cp.getConnectionTimeout());
- connection.setReadTimeout((int)cp.getReceiveTimeout());
- connection.setUseCaches(false);
- connection.setInstanceFollowRedirects(false);
-
- // If the HTTP_REQUEST_METHOD is not set, the default is "POST".
- String httpRequestMethod = (String)message.get(Message.HTTP_REQUEST_METHOD);
- connection.setRequestMethod((null != httpRequestMethod) ? httpRequestMethod : "POST");
-
- message.put(KEY_HTTP_CONNECTION, connection);
-
- if (stream != null && stream.size() < Integer.MAX_VALUE) {
- connection.setFixedLengthStreamingMode((int)stream.size());
- }
-
- // Need to set the headers before the trust decision
- // because they are set before the connect().
- new Headers(message).setProtocolHeadersInConnection(connection);
-
- //
- // This point is where the trust decision is made because the
- // Sun implementation of URLConnection will not let us
- // set/addRequestProperty after a connect() call, and
- // makeTrustDecision needs to make a connect() call to
- // make sure the proper information is available.
- //
- TrustDecisionUtil.makeTrustDecision(trustDecider, message, connection, getConduitName());
-
- // If this is a GET method we must not touch the output
- // stream as this automagically turns the request into a POST.
- if (connection.getRequestMethod().equals("GET")) {
- return connection;
- }
-
- // Trust is okay, write the cached request
- OutputStream out = connection.getOutputStream();
- stream.writeCacheTo(out);
-
- if (LOG.isLoggable(Level.FINE)) {
- LOG.fine("Conduit \""
- + getConduitName()
- + "\" Retransmit message to: "
- + connection.getURL()
- + ": "
- + new String(stream.getBytes()));
- }
- return connection;
- }
-
- private static void detectAuthorizationLoop(String conduitName, Message message,
- URL currentURL, String realm) throws IOException {
- @SuppressWarnings("unchecked")
- Set<String> authURLs = (Set<String>) message.get(KEY_AUTH_URLS);
- if (authURLs == null) {
- authURLs = new HashSet<String>();
- message.put(KEY_AUTH_URLS, authURLs);
- }
- // If we have been here (URL & Realm) before for this particular message
- // retransmit, it means we have already supplied information
- // which must have been wrong, or we wouldn't be here again.
- // Otherwise, the server may be 401 looping us around the realms.
- if (authURLs.contains(currentURL.toString() + realm)) {
- String logMessage = "Authorization loop detected on Conduit \""
- + conduitName
- + "\" on URL \""
- + currentURL
- + "\" with realm \""
- + realm
- + "\"";
- if (LOG.isLoggable(Level.INFO)) {
- LOG.log(Level.INFO, logMessage);
- }
-
- throw new IOException(logMessage);
- }
- // Register that we have been here before we go.
- authURLs.add(currentURL.toString() + realm);
- }
-
- /**
- * Tracks the visited urls in the message header KEY_VISITED_URLS.
- * If a URL is to be visited twice an exception is thrown
- *
- * @param conduitName
- * @param lastURL
- * @param newURL
- * @param message
- * @throws IOException
- */
- private static void detectRedirectLoop(String conduitName,
- URL lastURL,
- URL newURL,
- Message message) throws IOException {
- @SuppressWarnings("unchecked")
- Set<String> visitedURLs = (Set<String>) message.get(KEY_VISITED_URLS);
- if (visitedURLs == null) {
- visitedURLs = new HashSet<String>();
- message.put(KEY_VISITED_URLS, visitedURLs);
- }
- visitedURLs.add(lastURL.toString());
- if (newURL != null && visitedURLs.contains(newURL.toString())) {
- // See if we are being redirected in a loop as best we can,
- // using string equality on URL.
- // We are in a redirect loop; -- bail
- String msg = "Redirect loop detected on Conduit '"
- + conduitName + "' on '" + newURL + "'";
- LOG.log(Level.INFO, msg);
- throw new IOException(msg);
- }
- }
/**
* This method extracts the value of the "Location" Http
@@ -1249,16 +929,14 @@ public class HTTPConduit
* @return The value of the "Location" header, null if non-existent.
* @throws MalformedURLException
*/
- private URL extractLocation(Map<String, List<String>> headers
- ) throws MalformedURLException {
-
+ protected String extractLocation(Map<String, List<String>> headers) throws MalformedURLException {
for (Map.Entry<String, List<String>> head : headers.entrySet()) {
if ("Location".equalsIgnoreCase(head.getKey())) {
List<String> locs = head.getValue();
if (locs != null && locs.size() > 0) {
String location = locs.get(0);
if (location != null) {
- return new URL(location);
+ return location;
} else {
return null;
}
@@ -1268,17 +946,73 @@ public class HTTPConduit
return null;
}
+
/**
- * Wrapper output stream responsible for flushing headers and handling
- * the incoming HTTP-level response (not necessarily the MEP response).
+ * Used to set appropriate message properties, exchange etc.
+ * as required for an incoming decoupled response (as opposed
+ * what's normally set by the Destination for an incoming
+ * request).
*/
- protected class WrappedOutputStream extends AbstractThresholdOutputStream {
-
+ protected class InterposedMessageObserver implements MessageObserver {
/**
- * This field contains the currently active connection.
+ * Called for an incoming message.
+ *
+ * @param inMessage
*/
- protected HttpURLConnection connection;
-
+ public void onMessage(Message inMessage) {
+ // disposable exchange, swapped with real Exchange on correlation
+ inMessage.setExchange(new ExchangeImpl());
+ inMessage.getExchange().put(Bus.class, bus);
+ inMessage.put(Message.DECOUPLED_CHANNEL_MESSAGE, Boolean.TRUE);
+ // REVISIT: how to get response headers?
+ //inMessage.put(Message.PROTOCOL_HEADERS, req.getXXX());
+ Headers.getSetProtocolHeaders(inMessage);
+ inMessage.put(Message.RESPONSE_CODE, HttpURLConnection.HTTP_OK);
+
+ // remove server-specific properties
+ inMessage.remove(AbstractHTTPDestination.HTTP_REQUEST);
+ inMessage.remove(AbstractHTTPDestination.HTTP_RESPONSE);
+ inMessage.remove(Message.ASYNC_POST_RESPONSE_DISPATCH);
+
+ //cache this inputstream since it's defer to use in case of async
+ try {
+ InputStream in = inMessage.getContent(InputStream.class);
+ if (in != null) {
+ CachedOutputStream cos = new CachedOutputStream();
+ IOUtils.copy(in, cos);
+ inMessage.setContent(InputStream.class, cos.getInputStream());
+ }
+ incomingObserver.onMessage(inMessage);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void assertMessage(Message message) {
+ PolicyDataEngine policyDataEngine = bus.getExtension(PolicyDataEngine.class);
+ policyDataEngine.assertMessage(message, getClient(), new ClientPolicyCalculator());
+ }
+
+ public boolean canAssert(QName type) {
+ return new ClientPolicyCalculator().equals(type);
+ }
+
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (evt.getSource() == clientSidePolicy
+ && "decoupledEndpoint".equals(evt.getPropertyName())) {
+ this.endpointInfo.setProperty("org.apache.cxf.ws.addressing.replyto",
+ evt.getNewValue());
+ }
+ }
+
+
+
+ /**
+ * Wrapper output stream responsible for flushing headers and handling
+ * the incoming HTTP-level response (not necessarily the MEP response).
+ */
+ protected abstract class WrappedOutputStream extends AbstractThresholdOutputStream {
/**
* This boolean is true if the request must be cached.
*/
@@ -1299,48 +1033,95 @@ public class HTTPConduit
protected Message outMessage;
protected String conduitName;
+
+ protected String url;
protected WrappedOutputStream(
Message outMessage,
- HttpURLConnection connection,
boolean possibleRetransmit,
boolean isChunking,
int chunkThreshold,
- String conduitName
+ String conduitName,
+ String url
) {
super(chunkThreshold);
this.outMessage = outMessage;
- this.connection = connection;
this.cachingForRetransmission = possibleRetransmit;
this.chunking = isChunking;
this.conduitName = conduitName;
+ this.url = url;
}
// This construction makes extending the HTTPConduit more easier
protected WrappedOutputStream(WrappedOutputStream wos) {
super(wos.threshold);
this.outMessage = wos.outMessage;
- this.connection = wos.connection;
this.cachingForRetransmission = wos.cachingForRetransmission;
this.chunking = wos.chunking;
this.conduitName = wos.conduitName;
+ this.url = wos.url;
}
-
@Override
public void thresholdNotReached() {
if (chunking) {
- connection.setFixedLengthStreamingMode(buffer.size());
+ setFixedLengthStreamingMode(buffer.size());
}
}
- @Override
- public void thresholdReached() {
- if (chunking) {
- connection.setChunkedStreamingMode(-1);
+ protected abstract void setupWrappedStream() throws IOException;
+ protected abstract void handleResponseAsync() throws IOException;
+ protected abstract void closeInputStream() throws IOException;
+ protected abstract InputStream getInputStream(int rc) throws IOException;
+ protected abstract void updateResponseHeaders(Message inMessage);
+ protected abstract boolean usingProxy();
+ protected abstract HttpsURLConnectionInfo getHttpsURLConnectionInfo() throws IOException;
+ protected abstract int getResponseCode() throws IOException;
+ protected abstract String getResponseMessage() throws IOException;
+ protected abstract void updateCookies();
+ protected abstract InputStream getPartialResponse(int responseCode) throws IOException;
+ protected abstract void setProtocolHeaders() throws IOException;
+ protected abstract void setFixedLengthStreamingMode(int i);
+ protected abstract void retransmitStream() throws IOException;
+ protected abstract void setupNewConnection(String newURL) throws IOException;
+
+ protected void retransmit(String newURL) throws IOException {
+ setupNewConnection(newURL);
+
+ if (cachedStream != null && cachedStream.size() < Integer.MAX_VALUE) {
+ setFixedLengthStreamingMode((int)cachedStream.size());
}
- }
+ setProtocolHeaders();
+
+ //
+ // This point is where the trust decision is made because the
+ // Sun implementation of URLConnection will not let us
+ // set/addRequestProperty after a connect() call, and
+ // makeTrustDecision needs to make a connect() call to
+ // make sure the proper information is available.
+ //
+ makeTrustDecision();
+ // If this is a GET method we must not touch the output
+ // stream as this automagically turns the request into a POST.
+ if (getMethod().equals("GET")) {
+ return;
+ }
+
+ // Trust is okay, write the cached request
+ retransmitStream();
+
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Conduit \""
+ + getConduitName()
+ + "\" Retransmit message to: "
+ + newURL
+ + ": "
+ + new String(cachedStream.getBytes()));
+ }
+ }
+
+
/**
* Perform any actions required on stream flush (freeze headers,
* reset output stream ... etc.)
@@ -1359,22 +1140,16 @@ public class HTTPConduit
throw e;
}
}
-
- if (LOG.isLoggable(Level.FINE)) {
- LOG.fine("Sending "
- + connection.getRequestMethod()
- + " Message with Headers to "
- + connection.getURL()
- + " Conduit :"
- + conduitName
- + "\n");
- }
}
+ protected String getMethod() {
+ return (String)outMessage.get(Message.HTTP_REQUEST_METHOD);
+ }
+
protected void handleHeadersTrustCaching() throws IOException {
// Need to set the headers before the trust decision
// because they are set before the connect().
- new Headers(outMessage).setProtocolHeadersInConnection(connection);
+ setProtocolHeaders();
//
// This point is where the trust decision is made because the
@@ -1383,33 +1158,26 @@ public class HTTPConduit
// makeTrustDecision needs to make a connect() call to
// make sure the proper information is available.
//
- TrustDecisionUtil.makeTrustDecision(trustDecider, outMessage, connection, conduitName);
+ makeTrustDecision();
// Trust is okay, set up for writing the request.
// If this is a GET method we must not touch the output
// stream as this automatically turns the request into a POST.
// Nor it should be done in case of DELETE/HEAD/OPTIONS
- // - strangely, empty PUTs work ok
- if (!"POST".equals(connection.getRequestMethod())
- && !"PUT".equals(connection.getRequestMethod())) {
+ // - strangely, empty PUTs work ok
+ String method = getMethod();
+ if (!"POST".equals(method)
+ && !"PUT".equals(method)) {
return;
}
if (outMessage.get("org.apache.cxf.post.empty") != null) {
return;
}
- // If we need to cache for retransmission, store data in a
- // CacheAndWriteOutputStream. Otherwise write directly to the output stream.
- if (cachingForRetransmission) {
- cachedStream =
- new CacheAndWriteOutputStream(connection.getOutputStream());
- wrappedStream = cachedStream;
- } else {
- wrappedStream = connection.getOutputStream();
- }
-
+ setupWrappedStream();
}
+
/**
* Perform any actions required on stream closure (handle response etc.)
@@ -1441,24 +1209,24 @@ public class HTTPConduit
}
}
} catch (HttpRetryException e) {
- handleHttpRetryException(e, connection);
+ handleHttpRetryException(e);
} catch (IOException e) {
- String url = connection.getURL().toString();
String origMessage = e.getMessage();
if (origMessage != null && origMessage.contains(url)) {
throw e;
}
throw mapException(e.getClass().getSimpleName()
- + " invoking " + connection.getURL() + ": "
+ + " invoking " + url + ": "
+ e.getMessage(), e,
IOException.class);
} catch (RuntimeException e) {
throw mapException(e.getClass().getSimpleName()
- + " invoking " + connection.getURL() + ": "
+ + " invoking " + url + ": "
+ e.getMessage(), e,
RuntimeException.class);
}
}
+
private <T extends Exception> T mapException(String msg,
T ex, Class<T> cls) {
T ex2 = ex;
@@ -1481,29 +1249,115 @@ public class HTTPConduit
protected void handleRetransmits() throws IOException {
// If we have a cachedStream, we are caching the request.
if (cachedStream != null
- || ("GET".equals(connection.getRequestMethod()) && getClient().isAutoRedirect())) {
+ || ("GET".equals(getMethod()) && getClient().isAutoRedirect())) {
if (LOG.isLoggable(Level.FINE) && cachedStream != null) {
LOG.fine("Conduit \""
+ getConduitName()
+ "\" Transmit cached message to: "
- + connection.getURL()
+ + url
+ ": "
+ new String(cachedStream.getBytes()));
}
int maxRetransmits = getMaxRetransmits();
- cookies.readFromConnection(connection);
+ updateCookies();
int nretransmits = 0;
- HttpURLConnection oldcon = null;
- while (connection != oldcon && (maxRetransmits < 0 || nretransmits < maxRetransmits)) {
+ while ((maxRetransmits < 0 || nretransmits < maxRetransmits) && processRetransmit()) {
nretransmits++;
- oldcon = connection;
- connection = processRetransmit(connection, outMessage, cachedStream);
}
}
}
+ /**
+ * This function processes any retransmits at the direction of redirections
+ * or "unauthorized" responses.
+ *
+ * @return true if there was a retransmit
+ * @throws IOException
+ */
+ protected boolean processRetransmit() throws IOException {
+ int responseCode = getResponseCode();
+ if ((outMessage != null) && (outMessage.getExchange() != null)) {
+ outMessage.getExchange().put(Message.RESPONSE_CODE, responseCode);
+ }
+ // Process Redirects first.
+ switch(responseCode) {
+ case HttpURLConnection.HTTP_MOVED_PERM:
+ case HttpURLConnection.HTTP_MOVED_TEMP:
+ case HttpURLConnection.HTTP_SEE_OTHER:
+ case 307:
+ return redirectRetransmit();
+ case HttpURLConnection.HTTP_UNAUTHORIZED:
+ return authorizationRetransmit();
+ default:
+ break;
+ }
+ return false;
+ }
+ protected boolean redirectRetransmit() throws IOException {
+ // If we are not redirecting by policy, then we don't.
+ if (!getClient(outMessage).isAutoRedirect()) {
+ return false;
+ }
+ Message m = new MessageImpl();
+ updateResponseHeaders(m);
+ String newURL = extractLocation(Headers.getSetProtocolHeaders(m));
+
+ detectRedirectLoop(getConduitName(), url, newURL, outMessage);
+ if (newURL != null) {
+ new Headers(outMessage).removeAuthorizationHeaders();
+
+ // If user configured this Conduit with preemptive authorization
+ // it is meant to make it to the end. (Too bad that information
+ // went to every URL along the way, but that's what the user
+ // wants!
+ setHeadersByAuthorizationPolicy(outMessage, new URL(newURL));
+ retransmit(newURL);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * This method performs a retransmit for authorization information.
+ *
+ * @param connection The currently active connection.
+ * @param message The outbound message.
+ * @param cachedStream The cached request.
+ * @return A new connection if retransmitted. If not retransmitted
+ * then this method returns the same connection.
+ * @throws IOException
+ */
+ protected boolean authorizationRetransmit() throws IOException {
+ Message m = new MessageImpl();
+ updateResponseHeaders(m);
+ HttpAuthHeader authHeader = new HttpAuthHeader(Headers.getSetProtocolHeaders(m).get("WWW-Authenticate"));
+ URL currentURL = new URL(url);
+ String realm = authHeader.getRealm();
+ detectAuthorizationLoop(getConduitName(), outMessage, currentURL, realm);
+ AuthorizationPolicy effectiveAthPolicy = getEffectiveAuthPolicy(outMessage);
+ String authorizationToken =
+ authSupplier.getAuthorization(
+ effectiveAthPolicy, currentURL, outMessage, authHeader.getFullHeader());
+ if (authorizationToken == null) {
+ // authentication not possible => we give up
+ return false;
+ }
+
+ try {
+ closeInputStream();
+ } catch (Throwable t) {
+ //ignore
+ }
+ new Headers(outMessage).setAuthorization(authorizationToken);
+ cookies.writeToMessageHeaders(outMessage);
+ retransmit(url);
+ return true;
+ }
+
+
+
private int getMaxRetransmits() {
HTTPClientPolicy policy = getClient(outMessage);
@@ -1519,66 +1373,18 @@ public class HTTPConduit
* @throws IOException
*/
protected void handleResponse() throws IOException {
-
// Process retransmits until we fall out.
handleRetransmits();
-
+
if (outMessage == null
|| outMessage.getExchange() == null
|| outMessage.getExchange().isSynchronous()) {
handleResponseInternal();
} else {
- Runnable runnable = new Runnable() {
- public void run() {
- try {
- handleResponseInternal();
- } catch (Exception e) {
- ((PhaseInterceptorChain)outMessage.getInterceptorChain()).abort();
- ((PhaseInterceptorChain)outMessage.getInterceptorChain()).unwind(outMessage);
- outMessage.setContent(Exception.class, e);
- outMessage.getInterceptorChain().getFaultObserver().onMessage(outMessage);
- }
- }
- };
- HTTPClientPolicy policy = getClient(outMessage);
- try {
- Executor ex = outMessage.getExchange().get(Executor.class);
- if (ex == null) {
- WorkQueueManager mgr = outMessage.getExchange().get(Bus.class)
- .getExtension(WorkQueueManager.class);
- AutomaticWorkQueue qu = mgr.getNamedWorkQueue("http-conduit");
- if (qu == null) {
- qu = mgr.getAutomaticWorkQueue();
- }
- long timeout = 5000;
- if (policy != null && policy.isSetAsyncExecuteTimeout()) {
- timeout = policy.getAsyncExecuteTimeout();
- }
- if (timeout > 0) {
- qu.execute(runnable, timeout);
- } else {
- qu.execute(runnable);
- }
- } else {
- outMessage.getExchange().put(Executor.class.getName()
- + ".USING_SPECIFIED", Boolean.TRUE);
- ex.execute(runnable);
- }
- } catch (RejectedExecutionException rex) {
- if (policy != null && policy.isSetAsyncExecuteTimeoutRejection()
- && policy.isAsyncExecuteTimeoutRejection()) {
- throw rex;
- }
- if (!hasLoggedAsyncWarning) {
- LOG.warning("EXECUTOR_FULL_WARNING");
- hasLoggedAsyncWarning = true;
- }
- LOG.fine("EXECUTOR_FULL");
- handleResponseInternal();
- }
+ handleResponseAsync();
}
}
-
+
/**
* This predicate returns true iff the exchange indicates
* a oneway MEP.
@@ -1600,34 +1406,34 @@ public class HTTPConduit
protected void handleResponseInternal() throws IOException {
Exchange exchange = outMessage.getExchange();
- int responseCode = connection.getResponseCode();
+ int responseCode = getResponseCode();
if (responseCode == -1) {
LOG.warning("HTTP Response code appears to be corrupted");
}
if (exchange != null) {
exchange.put(Message.RESPONSE_CODE, responseCode);
}
-
- logResponseInfo(responseCode);
-
+
// This property should be set in case the exceptions should not be handled here
// For example jax rs uses this
boolean noExceptions = MessageUtils.isTrue(outMessage.getContextualProperty(
"org.apache.cxf.http.no_io_exceptions"));
if (responseCode >= 400 && responseCode != 500 && !noExceptions) {
- throw new HTTPException(responseCode, connection.getResponseMessage(),
- connection.getURL());
+ throw new HTTPException(responseCode, getResponseMessage(), new URL(url));
}
InputStream in = null;
// oneway or decoupled twoway calls may expect HTTP 202 with no content
if (isOneway(exchange)
|| HttpURLConnection.HTTP_ACCEPTED == responseCode) {
- in = ChunkedUtil.getPartialResponse(connection, responseCode);
- if ((in == null) || (!doProcessResponse(outMessage))) {
+ in = getPartialResponse(responseCode);
+ if ((in == null) || !doProcessResponse(outMessage)) {
// oneway operation or decoupled MEP without
// partial response
- connection.getInputStream().close();
+ closeInputStream();
+ if (isOneway(exchange) && responseCode > 300) {
+ throw new HTTPException(responseCode, getResponseMessage(), new URL(url));
+ }
ClientCallback cc = exchange.get(ClientCallback.class);
if (null != cc) {
//REVISIT move the decoupled destination property name into api
@@ -1654,11 +1460,9 @@ public class HTTPConduit
Message inMessage = new MessageImpl();
inMessage.setExchange(exchange);
- new Headers(inMessage).readFromConnection(connection);
+ updateResponseHeaders(inMessage);
inMessage.put(Message.RESPONSE_CODE, responseCode);
- String ct = connection.getContentType();
- inMessage.put(Message.CONTENT_TYPE, ct);
- String charset = HttpHeaderHelper.findCharset(ct);
+ String charset = HttpHeaderHelper.findCharset((String)inMessage.get(Message.CONTENT_TYPE));
String normalizedEncoding = HttpHeaderHelper.mapCharset(charset);
if (normalizedEncoding == null) {
String m = new org.apache.cxf.common.i18n.Message("INVALID_ENCODING_MSG",
@@ -1667,21 +1471,8 @@ public class HTTPConduit
throw new IOException(m);
}
inMessage.put(Message.ENCODING, normalizedEncoding);
- cookies.readFromConnection(connection);
if (in == null) {
- if (responseCode >= HttpURLConnection.HTTP_BAD_REQUEST) {
- in = connection.getErrorStream();
- if (in == null) {
- try {
- // just in case - but this will most likely cause an exception
- in = connection.getInputStream();
- } catch (IOException ex) {
- // ignore
- }
- }
- } else {
- in = connection.getInputStream();
- }
+ in = getInputStream(responseCode);
}
if (in == null) {
// Create an empty stream to avoid NullPointerExceptions
@@ -1694,131 +1485,175 @@ public class HTTPConduit
}
-
- private void logResponseInfo(int responseCode) {
- if (LOG.isLoggable(Level.FINE)) {
- LOG.fine("Response Code: " + responseCode + " Conduit: " + conduitName);
- LOG.fine("Content length: " + connection.getContentLength());
- Map<String, List<String>> headerFields = connection.getHeaderFields();
- if (null != headerFields) {
- String newLine = SystemPropertyAction.getProperty("line.separator");
- StringBuilder buf = new StringBuilder();
- buf.append("Header fields: " + newLine);
- for (String headerKey : headerFields.keySet()) {
- buf.append(" " + headerKey + ": " + headerFields.get(headerKey) + newLine);
+
+ protected void handleHttpRetryException(HttpRetryException e) throws IOException {
+ String msg = "HTTP response '" + e.responseCode() + ": "
+ + getResponseMessage() + "' invoking " + url;
+ switch (e.responseCode()) {
+ case HttpURLConnection.HTTP_MOVED_PERM: // 301
+ case HttpURLConnection.HTTP_MOVED_TEMP: // 302
+ case HttpURLConnection.HTTP_SEE_OTHER: // 303
+ case 307:
+ msg += " that returned location header '" + e.getLocation() + "'";
+ break;
+ case HttpURLConnection.HTTP_UNAUTHORIZED: // 401
+ if (authorizationPolicy == null || authorizationPolicy.getUserName() == null) {
+ msg += " with NO authorization username configured in conduit " + getConduitName();
+ } else {
+ msg += " with authorization username '" + authorizationPolicy.getUserName() + "'";
+ }
+ break;
+ case HttpURLConnection.HTTP_PROXY_AUTH: // 407
+ if (proxyAuthorizationPolicy == null || proxyAuthorizationPolicy.getUserName() == null) {
+ msg += " with NO proxy authorization configured in conduit " + getConduitName();
+ } else {
+ msg += " with proxy authorization username '"
+ + proxyAuthorizationPolicy.getUserName() + "'";
+ }
+ if (clientSidePolicy == null || clientSidePolicy.getProxyServer() == null) {
+ if (usingProxy()) {
+ msg += " using a proxy even if NONE is configured in CXF conduit "
+ + getConduitName()
+ + " (maybe one is configured by java.net.ProxySelector)";
+ } else {
+ msg += " but NO proxy was used by the connection (none configured in cxf "
+ + "conduit and none selected by java.net.ProxySelector)";
}
- LOG.fine(buf.toString());
+ } else {
+ msg += " using " + clientSidePolicy.getProxyServerType() + " proxy "
+ + clientSidePolicy.getProxyServer() + ":"
+ + clientSidePolicy.getProxyServerPort();
}
+ break;
+ default:
+ // No other type of HttpRetryException should be thrown
+ break;
}
+ throw new IOException(msg, e);
}
- }
-
- /**
- * Used to set appropriate message properties, exchange etc.
- * as required for an incoming decoupled response (as opposed
- * what's normally set by the Destination for an incoming
- * request).
- */
- protected class InterposedMessageObserver implements MessageObserver {
/**
- * Called for an incoming message.
+ * This call must take place before anything is written to the
+ * URLConnection. The URLConnection.connect() will be called in order
+ * to get the connection information.
*
- * @param inMessage
+ * This method is invoked just after setURLRequestHeaders() from the
+ * WrappedOutputStream before it writes data to the URLConnection.
+ *
+ * If trust cannot be established the Trust Decider implemenation
+ * throws an IOException.
+ *
+ * @param message The message being sent.
+ * @throws IOException This exception is thrown if trust cannot be
+ * established by the configured MessageTrustDecider.
+ * @see MessageTrustDecider
*/
- public void onMessage(Message inMessage) {
- // disposable exchange, swapped with real Exchange on correlation
- inMessage.setExchange(new ExchangeImpl());
- inMessage.getExchange().put(Bus.class, bus);
- inMessage.put(DECOUPLED_CHANNEL_MESSAGE, Boolean.TRUE);
- // REVISIT: how to get response headers?
- //inMessage.put(Message.PROTOCOL_HEADERS, req.getXXX());
- Headers.getSetProtocolHeaders(inMessage);
- inMessage.put(Message.RESPONSE_CODE, HttpURLConnection.HTTP_OK);
-
- // remove server-specific properties
- inMessage.remove(AbstractHTTPDestination.HTTP_REQUEST);
- inMessage.remove(AbstractHTTPDestination.HTTP_RESPONSE);
- inMessage.remove(Message.ASYNC_POST_RESPONSE_DISPATCH);
-
- //cache this inputstream since it's defer to use in case of async
- try {
- InputStream in = inMessage.getContent(InputStream.class);
- if (in != null) {
- CachedOutputStream cos = new CachedOutputStream();
- IOUtils.copy(in, cos);
- inMessage.setContent(InputStream.class, cos.getInputStream());
+ protected void makeTrustDecision() throws IOException {
+
+ MessageTrustDecider decider2 = outMessage.get(MessageTrustDecider.class);
+ if (trustDecider != null || decider2 != null) {
+ try {
+ // We must connect or we will not get the credentials.
+ // The call is (said to be) ingored internally if
+ // already connected.
+ HttpsURLConnectionInfo info = getHttpsURLConnectionInfo();
+ if (trustDecider != null) {
+ trustDecider.establishTrust(
+ conduitName,
+ info,
+ outMessage);
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.log(Level.FINE, "Trust Decider "
+ + trustDecider.getLogicalName()
+ + " considers Conduit "
+ + conduitName
+ + " trusted.");
+ }
+ }
+ if (decider2 != null) {
+ decider2.establishTrust(conduitName,
+ info,
+ outMessage);
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.log(Level.FINE, "Trust Decider "
+ + decider2.getLogicalName()
+ + " considers Conduit "
+ + conduitName
+ + " trusted.");
+ }
+ }
+ } catch (UntrustedURLConnectionIOException untrustedEx) {
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.log(Level.FINE, "Trust Decider "
+ + trustDecider.getLogicalName()
+ + " considers Conduit "
+ + conduitName
+ + " untrusted.", untrustedEx);
+ }
+ throw untrustedEx;
+ }
+ } else {
+ // This case, when there is no trust decider, a trust
+ // decision should be a matter of policy.
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.log(Level.FINE, "No Trust Decider for Conduit '"
+ + conduitName
+ + "'. An afirmative Trust Decision is assumed.");
}
- incomingObserver.onMessage(inMessage);
- } catch (IOException e) {
- e.printStackTrace();
}
}
}
-
- public void assertMessage(Message message) {
- PolicyDataEngine policyDataEngine = bus.getExtension(PolicyDataEngine.class);
- policyDataEngine.assertMessage(message, getClient(), new ClientPolicyCalculator());
- }
-
- public boolean canAssert(QName type) {
- return new ClientPolicyCalculator().equals(type);
- }
- public void propertyChange(PropertyChangeEvent evt) {
- if (evt.getSource() == clientSidePolicy
- && "decoupledEndpoint".equals(evt.getPropertyName())) {
- this.endpointInfo.setProperty("org.apache.cxf.ws.addressing.replyto",
- evt.getNewValue());
+ private static void detectRedirectLoop(String conduitName,
+ String lastURL,
+ String newURL,
+ Message message) throws IOException {
+ @SuppressWarnings("unchecked")
+ Set<String> visitedURLs = (Set<String>) message.get(KEY_VISITED_URLS);
+ if (visitedURLs == null) {
+ visitedURLs = new HashSet<String>();
+ message.put(KEY_VISITED_URLS, visitedURLs);
}
- }
-
- private void handleHttpRetryException(HttpRetryException e, HttpURLConnection connection)
- throws IOException {
- String msg = "HTTP response '" + e.responseCode() + ": "
- + connection.getResponseMessage() + "' invoking " + connection.getURL();
- switch (e.responseCode()) {
- case HttpURLConnection.HTTP_MOVED_PERM: // 301
- case HttpURLConnection.HTTP_MOVED_TEMP: // 302
- case HttpURLConnection.HTTP_SEE_OTHER: // 303
- case 307:
- msg += " that returned location header '" + e.getLocation() + "'";
- break;
- case HttpURLConnection.HTTP_UNAUTHORIZED: // 401
- if (authorizationPolicy == null || authorizationPolicy.getUserName() == null) {
- msg += " with NO authorization username configured in conduit " + getConduitName();
- } else {
- msg += " with authorization username '" + authorizationPolicy.getUserName() + "'";
- }
- break;
- case HttpURLConnection.HTTP_PROXY_AUTH: // 407
- if (proxyAuthorizationPolicy == null || proxyAuthorizationPolicy.getUserName() == null) {
- msg += " with NO proxy authorization configured in conduit " + getConduitName();
- } else {
- msg += " with proxy authorization username '"
- + proxyAuthorizationPolicy.getUserName() + "'";
+ visitedURLs.add(lastURL);
+ if (newURL != null && visitedURLs.contains(newURL)) {
+ // See if we are being redirected in a loop as best we can,
+ // using string equality on URL.
+ // We are in a redirect loop; -- bail
+ String msg = "Redirect loop detected on Conduit '"
+ + conduitName + "' on '" + newURL + "'";
+ LOG.log(Level.INFO, msg);
+ throw new IOException(msg);
+ }
+ }
+ private static void detectAuthorizationLoop(String conduitName, Message message,
+ URL currentURL, String realm) throws IOException {
+ @SuppressWarnings("unchecked")
+ Set<String> authURLs = (Set<String>) message.get(KEY_AUTH_URLS);
+ if (authURLs == null) {
+ authURLs = new HashSet<String>();
+ message.put(KEY_AUTH_URLS, authURLs);
+ }
+ // If we have been here (URL & Realm) before for this particular message
+ // retransmit, it means we have already supplied information
+ // which must have been wrong, or we wouldn't be here again.
+ // Otherwise, the server may be 401 looping us around the realms.
+ if (authURLs.contains(currentURL.toString() + realm)) {
+ String logMessage = "Authorization loop detected on Conduit \""
+ + conduitName
+ + "\" on URL \""
+ + currentURL
+ + "\" with realm \""
+ + realm
+ + "\"";
+ if (LOG.isLoggable(Level.INFO)) {
+ LOG.log(Level.INFO, logMessage);
}
- if (clientSidePolicy == null || clientSidePolicy.getProxyServer() == null) {
- if (connection.usingProxy()) {
- msg += " using a proxy even if NONE is configured in CXF conduit "
- + getConduitName()
- + " (maybe one is configured by java.net.ProxySelector)";
- } else {
- msg += " but NO proxy was used by the connection (none configured in cxf "
- + "conduit and none selected by java.net.ProxySelector)";
- }
- } else {
- msg += " using " + clientSidePolicy.getProxyServerType() + " proxy "
- + clientSidePolicy.getProxyServer() + ":"
- + clientSidePolicy.getProxyServerPort();
- }
- break;
- default:
- // No other type of HttpRetryException should be thrown
- break;
+
+ throw new IOException(logMessage);
}
- // pass cause with initCause() instead of constructor for jdk 1.5 compatibility
- throw (IOException) new IOException(msg).initCause(e);
+ // Register that we have been here before we go.
+ authURLs.add(currentURL.toString() + realm);
}
+
}
Modified: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPTransportFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPTransportFactory.java?rev=1365733&r1=1365732&r2=1365733&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPTransportFactory.java (original)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPTransportFactory.java Wed Jul 25 20:48:50 2012
@@ -247,7 +247,7 @@ public class HTTPTransportFactory
EndpointInfo endpointInfo,
EndpointReferenceType target
) throws IOException {
- HTTPConduit conduit = new HTTPConduit(bus, endpointInfo, target);
+ HTTPConduit conduit = new URLConnectionHTTPConduit(bus, endpointInfo, target);
// Spring configure the conduit.
String address = conduit.getAddress();
if (address != null && address.indexOf('?') != -1) {
Added: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/URLConnectionHTTPConduit.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/URLConnectionHTTPConduit.java?rev=1365733&view=auto
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/URLConnectionHTTPConduit.java (added)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/URLConnectionHTTPConduit.java Wed Jul 25 20:48:50 2012
@@ -0,0 +1,316 @@
+/**
+ * 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.net.URLConnection;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.logging.Level;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.io.CacheAndWriteOutputStream;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.PhaseInterceptorChain;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.https.HttpsURLConnectionFactory;
+import org.apache.cxf.transport.https.HttpsURLConnectionInfo;
+import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
+import org.apache.cxf.workqueue.AutomaticWorkQueue;
+import org.apache.cxf.workqueue.WorkQueueManager;
+import org.apache.cxf.ws.addressing.EndpointReferenceType;
+
+/**
+ *
+ */
+public class URLConnectionHTTPConduit extends HTTPConduit {
+ private static boolean hasLoggedAsyncWarning;
+
+ /**
+ * This field holds the connection factory, which primarily is used to
+ * factor out SSL specific code from this implementation.
+ * <p>
+ * This field is "protected" to facilitate some contrived UnitTesting so
+ * that an extended class may alter its value with an EasyMock URLConnection
+ * Factory.
+ */
+ protected HttpsURLConnectionFactory connectionFactory;
+
+
+ public URLConnectionHTTPConduit(Bus b, EndpointInfo ei) throws IOException {
+ super(b, ei);
+ connectionFactory = new HttpsURLConnectionFactory();
+ CXFAuthenticator.addAuthenticator();
+ }
+
+ public URLConnectionHTTPConduit(Bus b, EndpointInfo ei, EndpointReferenceType t) throws IOException {
+ super(b, ei, t);
+ connectionFactory = new HttpsURLConnectionFactory();
+ CXFAuthenticator.addAuthenticator();
+ }
+
+ /**
+ * Close the conduit
+ */
+ public void close() {
+ super.close();
+ if (defaultEndpointURL != null) {
+ try {
+ URLConnection connect = defaultEndpointURL.openConnection();
+ if (connect instanceof HttpURLConnection) {
+ ((HttpURLConnection)connect).disconnect();
+ }
+ } catch (IOException ex) {
+ //ignore
+ }
+ //defaultEndpointURL = null;
+ }
+ }
+
+ private HttpURLConnection createConnection(Message message, URL url, HTTPClientPolicy csPolicy) throws IOException {
+ Proxy proxy = proxyFactory.createProxy(csPolicy , url);
+ return connectionFactory.createConnection(tlsClientParameters, proxy, url);
+ }
+ protected void setupConnection(Message message, URL currentURL, HTTPClientPolicy csPolicy) throws IOException {
+ HttpURLConnection connection = createConnection(message, currentURL, csPolicy);
+ connection.setDoOutput(true);
+
+ int ctimeout = determineConnectionTimeout(message, csPolicy);
+ connection.setConnectTimeout(ctimeout);
+
+ int rtimeout = determineReceiveTimeout(message, csPolicy);
+ connection.setReadTimeout(rtimeout);
+
+ connection.setUseCaches(false);
+ // We implement redirects in this conduit. We do not
+ // rely on the underlying URLConnection implementation
+ // because of trust issues.
+ connection.setInstanceFollowRedirects(false);
+
+ // If the HTTP_REQUEST_METHOD is not set, the default is "POST".
+ String httpRequestMethod =
+ (String)message.get(Message.HTTP_REQUEST_METHOD);
+ if (httpRequestMethod == null) {
+ httpRequestMethod = "POST";
+ message.put(Message.HTTP_REQUEST_METHOD, "POST");
+ }
+ connection.setRequestMethod(httpRequestMethod);
+
+ // We place the connection on the message to pick it up
+ // in the WrappedOutputStream.
+ message.put(KEY_HTTP_CONNECTION, connection);
+ }
+
+
+ protected OutputStream createOutputStream(Message message,
+ boolean needToCacheRequest,
+ boolean isChunking,
+ int chunkThreshold) {
+ HttpURLConnection connection = (HttpURLConnection)message.get(KEY_HTTP_CONNECTION);
+
+ if (isChunking && chunkThreshold <= 0) {
+ chunkThreshold = 0;
+ connection.setChunkedStreamingMode(-1);
+ }
+ return new URLConnectionWrappedOutputStream(message, connection,
+ needToCacheRequest,
+ isChunking,
+ chunkThreshold,
+ getConduitName());
+ }
+
+ class URLConnectionWrappedOutputStream extends WrappedOutputStream {
+ HttpURLConnection connection;
+ public URLConnectionWrappedOutputStream(Message message, HttpURLConnection connection,
+ boolean needToCacheRequest, boolean isChunking,
+ int chunkThreshold, String conduitName) {
+ super(message, needToCacheRequest, isChunking,
+ chunkThreshold, conduitName,
+ connection.getURL().toString());
+ this.connection = connection;
+ }
+ // This construction makes extending the HTTPConduit more easier
+ protected URLConnectionWrappedOutputStream(URLConnectionWrappedOutputStream wos) {
+ super(wos);
+ this.connection = wos.connection;
+ }
+ protected void setupWrappedStream() throws IOException {
+ // If we need to cache for retransmission, store data in a
+ // CacheAndWriteOutputStream. Otherwise write directly to the output stream.
+ if (cachingForRetransmission) {
+ cachedStream =
+ new CacheAndWriteOutputStream(connection.getOutputStream());
+ wrappedStream = cachedStream;
+ } else {
+ wrappedStream = connection.getOutputStream();
+ }
+ }
+ @Override
+ public void thresholdReached() {
+ if (chunking) {
+ connection.setChunkedStreamingMode(-1);
+ }
+ }
+ @Override
+ protected void onFirstWrite() throws IOException {
+ super.onFirstWrite();
+ if (LOG.isLoggable(Level.FINE)) {
+ LOG.fine("Sending "
+ + connection.getRequestMethod()
+ + " Message with Headers to "
+ + url
+ + " Conduit :"
+ + conduitName
+ + "\n");
+ }
+ }
+ protected void setProtocolHeaders() throws IOException {
+ new Headers(outMessage).setProtocolHeadersInConnection(connection);
+ }
+
+ protected HttpsURLConnectionInfo getHttpsURLConnectionInfo() throws IOException {
+ connection.connect();
+ return new HttpsURLConnectionInfo(connection);
+ }
+ protected void updateCookies() {
+ cookies.readFromConnection(connection);
+ }
+ protected void updateResponseHeaders(Message inMessage) {
+ new Headers(inMessage).readFromConnection(connection);
+ inMessage.put(Message.CONTENT_TYPE, connection.getContentType());
+ cookies.readFromConnection(connection);
+ }
+ protected InputStream getInputStream(int responseCode) throws IOException {
+ InputStream in = null;
+ if (responseCode >= HttpURLConnection.HTTP_BAD_REQUEST) {
+ in = connection.getErrorStream();
+ if (in == null) {
+ try {
+ // just in case - but this will most likely cause an exception
+ in = connection.getInputStream();
+ } catch (IOException ex) {
+ // ignore
+ }
+ }
+ } else {
+ in = connection.getInputStream();
+ }
+ return in;
+ }
+
+
+ protected void closeInputStream() throws IOException {
+ //try and consume any content so that the connection might be reusable
+ InputStream ins = connection.getErrorStream();
+ if (ins == null) {
+ ins = connection.getInputStream();
+ }
+ if (ins != null) {
+ IOUtils.consume(ins);
+ ins.close();
+ }
+ }
+ protected void handleResponseAsync() throws IOException {
+ Runnable runnable = new Runnable() {
+ public void run() {
+ try {
+ handleResponseInternal();
+ } catch (Exception e) {
+ ((PhaseInterceptorChain)outMessage.getInterceptorChain()).abort();
+ ((PhaseInterceptorChain)outMessage.getInterceptorChain()).unwind(outMessage);
+ outMessage.setContent(Exception.class, e);
+ outMessage.getInterceptorChain().getFaultObserver().onMessage(outMessage);
+ }
+ }
+ };
+ HTTPClientPolicy policy = getClient(outMessage);
+ try {
+ Executor ex = outMessage.getExchange().get(Executor.class);
+ if (ex == null) {
+ WorkQueueManager mgr = outMessage.getExchange().get(Bus.class)
+ .getExtension(WorkQueueManager.class);
+ AutomaticWorkQueue qu = mgr.getNamedWorkQueue("http-conduit");
+ if (qu == null) {
+ qu = mgr.getAutomaticWorkQueue();
+ }
+ long timeout = 5000;
+ if (policy != null && policy.isSetAsyncExecuteTimeout()) {
+ timeout = policy.getAsyncExecuteTimeout();
+ }
+ if (timeout > 0) {
+ qu.execute(runnable, timeout);
+ } else {
+ qu.execute(runnable);
+ }
+ } else {
+ outMessage.getExchange().put(Executor.class.getName()
+ + ".USING_SPECIFIED", Boolean.TRUE);
+ ex.execute(runnable);
+ }
+ } catch (RejectedExecutionException rex) {
+ if (policy != null && policy.isSetAsyncExecuteTimeoutRejection()
+ && policy.isAsyncExecuteTimeoutRejection()) {
+ throw rex;
+ }
+ if (!hasLoggedAsyncWarning) {
+ LOG.warning("EXECUTOR_FULL_WARNING");
+ hasLoggedAsyncWarning = true;
+ }
+ LOG.fine("EXECUTOR_FULL");
+ handleResponseInternal();
+ }
+ }
+ protected int getResponseCode() throws IOException {
+ return connection.getResponseCode();
+ }
+ protected String getResponseMessage() throws IOException {
+ return connection.getResponseMessage();
+ }
+ protected InputStream getPartialResponse(int responseCode) throws IOException {
+ return ChunkedUtil.getPartialResponse(connection, responseCode);
+ }
+ protected boolean usingProxy() {
+ return connection.usingProxy();
+ }
+ protected void setFixedLengthStreamingMode(int i) {
+ connection.setFixedLengthStreamingMode(i);
+ }
+ protected void setupNewConnection(String newURL) throws IOException {
+ HTTPClientPolicy cp = getClient(outMessage);
+ URL nurl = new URL(newURL);
+ setupConnection(outMessage, nurl, cp);
+ url = newURL;
+ connection = (HttpURLConnection)outMessage.get(KEY_HTTP_CONNECTION);
+ }
+
+ @Override
+ protected void retransmitStream() throws IOException {
+ OutputStream out = connection.getOutputStream();
+ cachedStream.writeCacheTo(out);
+ }
+ }
+
+}
Modified: cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/HttpAuthHeader.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/HttpAuthHeader.java?rev=1365733&r1=1365732&r2=1365733&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/HttpAuthHeader.java (original)
+++ cxf/trunk/rt/transports/http/src/main/java/org/apache/cxf/transport/http/auth/HttpAuthHeader.java Wed Jul 25 20:48:50 2012
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
public final class HttpAuthHeader {
@@ -46,6 +47,26 @@ public final class HttpAuthHeader {
}
this.params = parseHeader();
}
+ public HttpAuthHeader(List<String> params) {
+ boolean first = true;
+ for (String s : params) {
+ if (!first) {
+ fullHeader += ", " + s;
+ } else {
+ first = false;
+ fullHeader = s;
+ }
+ }
+ int spacePos = this.fullHeader.indexOf(' ');
+ if (spacePos == -1) {
+ this.authType = this.fullHeader;
+ this.fullContent = "";
+ } else {
+ this.authType = this.fullHeader.substring(0, spacePos);
+ this.fullContent = this.fullHeader.substring(spacePos + 1);
+ }
+ this.params = parseHeader();
+ }
public HttpAuthHeader(String authType, Map<String, String> params) {
this.authType = authType;
Modified: cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java?rev=1365733&r1=1365732&r2=1365733&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java (original)
+++ cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitTest.java Wed Jul 25 20:48:50 2012
@@ -90,7 +90,7 @@ public class HTTPConduitTest extends Ass
Bus bus = new CXFBusImpl();
EndpointInfo ei = new EndpointInfo();
ei.setAddress("http://nowhere.com/bar/foo");
- HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+ HTTPConduit conduit = new URLConnectionHTTPConduit(bus, ei, null);
conduit.finalizeConfig();
EndpointReferenceType target =
@@ -126,7 +126,7 @@ public class HTTPConduitTest extends Ass
Bus bus = new CXFBusImpl();
EndpointInfo ei = new EndpointInfo();
ei.setAddress("http://nowhere.com/bar/foo");
- HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+ HTTPConduit conduit = new URLConnectionHTTPConduit(bus, ei, null);
conduit.finalizeConfig();
Message message = getNewMessage();
@@ -147,7 +147,7 @@ public class HTTPConduitTest extends Ass
ap.setUserName("testUser");
ei.addExtensor(ap);
ei.setAddress("http://nowhere.com/bar/foo");
- HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+ HTTPConduit conduit = new URLConnectionHTTPConduit(bus, ei, null);
conduit.finalizeConfig();
Message message = getNewMessage();
@@ -176,7 +176,7 @@ public class HTTPConduitTest extends Ass
Bus bus = new CXFBusImpl();
EndpointInfo ei = new EndpointInfo();
ei.setAddress("http://nowhere.com/bar/foo");
- HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+ HTTPConduit conduit = new URLConnectionHTTPConduit(bus, ei, null);
conduit.finalizeConfig();
conduit.getAuthorization().setUserName("Satan");
Modified: cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLConnectionTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLConnectionTest.java?rev=1365733&r1=1365732&r2=1365733&view=diff
==============================================================================
--- cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLConnectionTest.java (original)
+++ cxf/trunk/rt/transports/http/src/test/java/org/apache/cxf/transport/http/HTTPConduitURLConnectionTest.java Wed Jul 25 20:48:50 2012
@@ -78,7 +78,7 @@ public class HTTPConduitURLConnectionTes
Bus bus = new CXFBusImpl();
EndpointInfo ei = new EndpointInfo();
ei.setAddress("http://nowhere.com/bar/foo");
- HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+ HTTPConduit conduit = new URLConnectionHTTPConduit(bus, ei, null);
conduit.finalizeConfig();
Message message = getNewMessage();
@@ -101,7 +101,7 @@ public class HTTPConduitURLConnectionTes
Bus bus = new CXFBusImpl();
EndpointInfo ei = new EndpointInfo();
ei.setAddress("http://nowhere.null/bar/foo");
- HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+ HTTPConduit conduit = new URLConnectionHTTPConduit(bus, ei, null);
conduit.finalizeConfig();
Message message = getNewMessage();
@@ -155,7 +155,7 @@ public class HTTPConduitURLConnectionTes
Bus bus = new CXFBusImpl();
EndpointInfo ei = new EndpointInfo();
ei.setAddress("https://secure.nowhere.null/" + "bar/foo");
- HTTPConduit conduit = new HTTPConduit(bus, ei, null);
+ HTTPConduit conduit = new URLConnectionHTTPConduit(bus, ei, null);
conduit.finalizeConfig();
Message message = getNewMessage();