hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r538647 - in /jakarta/httpcomponents/httpclient/trunk/src: java/org/apache/http/client/ java/org/apache/http/client/params/ java/org/apache/http/client/protocol/ java/org/apache/http/impl/client/ test/org/apache/http/client/
Date Wed, 16 May 2007 16:41:43 GMT
Author: olegk
Date: Wed May 16 09:41:42 2007
New Revision: 538647

URL: http://svn.apache.org/viewvc?view=rev&rev=538647
Log:
Initial port of the authentication code from Commons HttpClient 3.x

Added:
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/AuthenticationHandler.java   (with props)
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestProxyAuthentication.java   (with props)
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestTargetAuthentication.java   (with props)
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AuthState.java
      - copied, changed from r537751, jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/AuthState.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultAuthenticationHandler.java   (with props)
Modified:
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/HttpState.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/RedirectHandler.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/params/HttpClientParams.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/HttpClientContext.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AbstractHttpClient.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultHttpClient.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultRedirectHandler.java
    jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/client/TestHttpState.java

Added: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/AuthenticationHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/AuthenticationHandler.java?view=auto&rev=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/AuthenticationHandler.java (added)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/AuthenticationHandler.java Wed May 16 09:41:42 2007
@@ -0,0 +1,68 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.client;
+
+import java.util.Map;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ */
+public interface AuthenticationHandler {
+
+    boolean isTargetAuthenticationRequested(
+            HttpResponse response, 
+            HttpContext context);
+    
+    boolean isProxyAuthenticationRequested(
+            HttpResponse response, 
+            HttpContext context);
+    
+    Map getTargetChallenges(
+            HttpResponse response, 
+            HttpContext context) throws MalformedChallengeException;
+    
+    Map getProxyChallenges(
+            HttpResponse response, 
+            HttpContext context) throws MalformedChallengeException;
+
+    AuthScheme selectScheme(
+            Map challenges, 
+            HttpResponse response, 
+            HttpContext context) throws AuthenticationException;
+    
+}

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/AuthenticationHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/AuthenticationHandler.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/AuthenticationHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/HttpState.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/HttpState.java?view=diff&rev=538647&r1=538646&r2=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/HttpState.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/HttpState.java Wed May 16 09:41:42 2007
@@ -69,12 +69,6 @@
     private HashMap credMap = new HashMap();
 
     /**
-     * Map of {@link Credentials proxy credentials} by realm that this
-     * HTTP state contains
-     */
-    private HashMap proxyCred = new HashMap();
-
-    /**
      * Array of {@link Cookie cookies} that this HTTP state contains.
      */
     private ArrayList cookies = new ArrayList();
@@ -234,45 +228,6 @@
         return matchCredentials(this.credMap, authscope);
     }
 
-    /** 
-     * Sets the {@link Credentials proxy credentials} for the given authentication 
-     * realm. Any previous credentials for the given realm will be overwritten.
-     * 
-     * @param authscope the {@link AuthScope authentication scope}
-     * @param credentials the authentication {@link Credentials credentials} 
-     * for the given realm.
-     * 
-     * @see #getProxyCredentials(AuthScope)
-     * @see #setCredentials(AuthScope, Credentials) 
-     * 
-     * @since 3.0
-     */
-    public synchronized void setProxyCredentials(
-            final AuthScope authscope, 
-            final Credentials credentials) {
-        if (authscope == null) {
-            throw new IllegalArgumentException("Authentication scope may not be null");
-        }
-        proxyCred.put(authscope, credentials);
-    }
-
-    /**
-     * Get the {@link Credentials proxy credentials} for the given authentication scope.
-     *
-     * @param authscope the {@link AuthScope authentication scope}
-     * @return the credentials 
-     * 
-     * @see #setProxyCredentials(AuthScope, Credentials)
-     * 
-     * @since 3.0
-     */
-    public synchronized Credentials getProxyCredentials(final AuthScope authscope) {
-        if (authscope == null) {
-            throw new IllegalArgumentException("Authentication scope may not be null");
-        }
-        return matchCredentials(this.proxyCred, authscope);
-    }
-
     /**
      * Returns a string representation of this HTTP state.
      * 
@@ -282,7 +237,6 @@
      */
     public synchronized String toString() {
         StringBuffer buffer = new StringBuffer();
-        buffer.append(proxyCred);
         buffer.append(credMap);
         buffer.append(cookies);
         return buffer.toString();
@@ -296,13 +250,6 @@
     }
     
     /**
-     * Clears all proxy credentials.
-     */
-    public synchronized void clearProxyCredentials() {
-        this.proxyCred.clear();
-    }
-    
-    /**
      * Clears all cookies.
      */
     public synchronized void clearCookies() {
@@ -315,7 +262,6 @@
     public synchronized void clear() {
         clearCookies();
         clearCredentials();
-        clearProxyCredentials();
     }
     
 }

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/RedirectHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/RedirectHandler.java?view=diff&rev=538647&r1=538646&r2=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/RedirectHandler.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/RedirectHandler.java Wed May 16 09:41:42 2007
@@ -61,7 +61,7 @@
      * @return <code>true</code> if the request should be redirected, <code>false</code>
      * otherwise
      */
-    boolean isRedirectNeeded(HttpResponse response, HttpContext context);
+    boolean isRedirectRequested(HttpResponse response, HttpContext context);
     
     /**
      * Determines the location request is expected to be redirected to 

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/params/HttpClientParams.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/params/HttpClientParams.java?view=diff&rev=538647&r1=538646&r2=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/params/HttpClientParams.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/params/HttpClientParams.java Wed May 16 09:41:42 2007
@@ -113,6 +113,22 @@
     public static final String PREEMPTIVE_AUTHENTICATION = "http.protocol.authentication-preemptive";
 
     /**
+     * The key used to look up the list of IDs of supported {@link AuthScheme 
+     * authentication schemes} in their order of preference. The scheme IDs are 
+     * stored in a {@link java.util.Collection} as {@link java.lang.String}s. 
+     * 
+     * <p>
+     * If several schemes are returned in the <tt>WWW-Authenticate</tt> 
+     * or <tt>Proxy-Authenticate</tt> header, this parameter defines which
+     * {@link AuthScheme authentication schemes} takes precedence over others.
+     * The first item in the collection represents the most preferred 
+     * {@link AuthScheme authentication scheme}, the last item represents the ID 
+     * of the least preferred one.
+     * </p>
+     */
+    public static final String AUTH_SCHEME_PRIORITY = "http.protocol-auth-scheme-priority";
+
+    /**
      * Defines the name of the cookie specification to be used for HTTP state management.
      * <p>
      * This parameter expects a value of type {@link String}.
@@ -121,6 +137,14 @@
     public static final String COOKIE_POLICY = "http.protocol.cookie-policy";
     
     /**
+     * Defines the virtual host name.
+     * <p>
+     * This parameter expects a value of type {@link org.apache.http.HttpHost}. 
+     * </p>
+     */
+    public static final String VIRTUAL_HOST = "http.virtual-host"; 
+
+    /**
      * Defines the request headers to be sent per default with each request.
      * <p>
      * This parameter expects a value of type {@link java.util.Collection}. The 
@@ -133,7 +157,7 @@
      * Defines the default host. The default value will be used if the target host is
      * not explicitly specified in the request URI.
      * <p>
-     * This parameter expects a value of type {@link HttpHost}.
+     * This parameter expects a value of type {@link org.apache.http.HttpHost}.
      * </p>
      */
     public static final String DEFAULT_HOST = "http.default-host";
@@ -142,7 +166,7 @@
      * Defines the default proxy. The default value will be used if the proxy
      * information is not explicitly specified in the request route. 
      * <p>
-     * This parameter expects a value of type {@link HttpHost}.
+     * This parameter expects a value of type {@link org.apache.http.HttpHost}.
      * </p>
      */
     public static final String DEFAULT_PROXY = "http.default-proxy";
@@ -179,6 +203,34 @@
         params.setLongParameter(CONNECTION_MANAGER_TIMEOUT, timeout);
     }
 
+    public static boolean isRedirecting(final HttpParams params) {
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
+        return params.getBooleanParameter(HANDLE_REDIRECTS, true); 
+    }
+
+    public static void setRedirecting(final HttpParams params, boolean value) {
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
+        params.setBooleanParameter(HANDLE_REDIRECTS, value); 
+    }
+    
+    public static boolean isAuthenticating(final HttpParams params) {
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
+        return params.getBooleanParameter(HANDLE_AUTHENTICATION, true); 
+    }
+
+    public static void setAuthenticating(final HttpParams params, boolean value) {
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
+        params.setBooleanParameter(HANDLE_AUTHENTICATION, value); 
+    }
+    
     /**
      * Returns <tt>true</tt> if authentication should be attempted preemptively, 
      * <tt>false</tt> otherwise.

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/HttpClientContext.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/HttpClientContext.java?view=diff&rev=538647&r1=538646&r2=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/HttpClientContext.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/HttpClientContext.java Wed May 16 09:41:42 2007
@@ -42,6 +42,8 @@
     public static final String HTTP_STATE            = "http.state"; 
     public static final String COOKIE_SPEC           = "http.cookie-spec"; 
     public static final String COOKIE_ORIGIN         = "http.cookie-origin"; 
+    public static final String TARGET_AUTH_STATE     = "http.auth.target-scope"; 
+    public static final String PROXY_AUTH_STATE      = "http.auth.proxy-scope"; 
     
     public HttpClientContext(final HttpContext parentContext) {
         super(parentContext);

Added: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestProxyAuthentication.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestProxyAuthentication.java?view=auto&rev=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestProxyAuthentication.java (added)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestProxyAuthentication.java Wed May 16 09:41:42 2007
@@ -0,0 +1,104 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.client.protocol;
+
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.Credentials;
+import org.apache.http.impl.client.AuthState;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision$
+ * 
+ * @since 4.0
+ */
+public class RequestProxyAuthentication implements HttpRequestInterceptor {
+
+    private static final Log LOG = LogFactory.getLog(RequestProxyAuthentication.class);
+    
+    public RequestProxyAuthentication() {
+        super();
+    }
+    
+    public void process(final HttpRequest request, final HttpContext context) 
+            throws HttpException, IOException {
+        if (request == null) {
+            throw new IllegalArgumentException("HTTP request may not be null");
+        }
+        if (context == null) {
+            throw new IllegalArgumentException("HTTP context may not be null");
+        }
+
+        if (request.containsHeader(AUTH.PROXY_AUTH_RESP)) {
+            return;
+        }
+        
+        // Obtain authentication state
+        AuthState authState = (AuthState) context.getAttribute(
+                HttpClientContext.PROXY_AUTH_STATE);
+        if (authState == null) {
+            return;
+        }
+
+        AuthScheme authScheme = authState.getAuthScheme();
+        if (authScheme == null) {
+            return;
+        }
+        
+        Credentials creds = authState.getCredentials();
+        if (creds == null) {
+            LOG.debug("User credentials not available");
+            return;
+        }
+        if (authState.getAuthScope() != null || !authScheme.isConnectionBased()) {
+            try {
+                request.addHeader(authScheme.authenticate(creds, request));
+            } catch (AuthenticationException ex) {
+                if (LOG.isErrorEnabled()) {
+                    LOG.error("Proxy authentication error: " + ex.getMessage());
+                }
+            }
+        }
+    }
+    
+}

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestProxyAuthentication.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestProxyAuthentication.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestProxyAuthentication.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestTargetAuthentication.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestTargetAuthentication.java?view=auto&rev=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestTargetAuthentication.java (added)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestTargetAuthentication.java Wed May 16 09:41:42 2007
@@ -0,0 +1,105 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.client.protocol;
+
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.Credentials;
+import org.apache.http.impl.client.AuthState;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ *
+ * @version $Revision$
+ * 
+ * @since 4.0
+ */
+public class RequestTargetAuthentication implements HttpRequestInterceptor {
+
+    private static final Log LOG = LogFactory.getLog(RequestTargetAuthentication.class);
+    
+    public RequestTargetAuthentication() {
+        super();
+    }
+    
+    public void process(final HttpRequest request, final HttpContext context) 
+            throws HttpException, IOException {
+        if (request == null) {
+            throw new IllegalArgumentException("HTTP request may not be null");
+        }
+        if (context == null) {
+            throw new IllegalArgumentException("HTTP context may not be null");
+        }
+
+        if (request.containsHeader(AUTH.WWW_AUTH_RESP)) {
+            return;
+        }
+        
+        // Obtain authentication state
+        AuthState authState = (AuthState) context.getAttribute(
+                HttpClientContext.TARGET_AUTH_STATE);
+        if (authState == null) {
+            return;
+        }
+
+        AuthScheme authScheme = authState.getAuthScheme();
+        if (authScheme == null) {
+            return;
+        }
+        
+        Credentials creds = authState.getCredentials();
+        if (creds == null) {
+            LOG.debug("User credentials not available");
+            return;
+        }
+
+        if (authState.getAuthScope() != null || !authScheme.isConnectionBased()) {
+            try {
+                request.addHeader(authScheme.authenticate(creds, request));
+            } catch (AuthenticationException ex) {
+                if (LOG.isErrorEnabled()) {
+                    LOG.error("Authentication error: " + ex.getMessage());
+                }
+            }
+        }
+    }
+    
+}

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestTargetAuthentication.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestTargetAuthentication.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/client/protocol/RequestTargetAuthentication.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AbstractHttpClient.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AbstractHttpClient.java?view=diff&rev=538647&r1=538646&r2=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AbstractHttpClient.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AbstractHttpClient.java Wed May 16 09:41:42 2007
@@ -43,6 +43,7 @@
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpResponseInterceptor;
 import org.apache.http.auth.AuthSchemeRegistry;
+import org.apache.http.client.AuthenticationHandler;
 import org.apache.http.client.ClientRequestDirector;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.HttpRequestRetryHandler;
@@ -103,6 +104,9 @@
     /** The redirect handler. */
     private RedirectHandler redirectHandler;
 
+    /** The authentication handler. */
+    private AuthenticationHandler authHandler;
+
     /** The default HTTP state. */
     private HttpState defaultState;
 
@@ -147,6 +151,9 @@
     protected abstract RedirectHandler createRedirectHandler();
 
     
+    protected abstract AuthenticationHandler createAuthenticationHandler();
+
+    
     protected abstract HttpState createHttpState();
     
     
@@ -251,6 +258,19 @@
     }
 
 
+    public synchronized final AuthenticationHandler getAuthenticationHandler() {
+        if (authHandler == null) {
+            authHandler = createAuthenticationHandler();
+        }
+        return authHandler;
+    }
+
+
+    public synchronized void setAuthenticationHandler(final AuthenticationHandler authHandler) {
+        this.authHandler = authHandler;
+    }
+
+
     public synchronized final HttpState getState() {
         if (defaultState == null) {
             defaultState = createHttpState();
@@ -418,6 +438,8 @@
                     getHttpProcessor().copy(),
                     getHttpRequestRetryHandler(),
                     getRedirectHandler(),
+                    getAuthenticationHandler(),
+                    getState(),
                     getParams());
         }
 

Copied: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AuthState.java (from r537751, jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/AuthState.java)
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AuthState.java?view=diff&rev=538647&p1=jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/AuthState.java&r1=537751&p2=jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AuthState.java&r2=538647
==============================================================================
--- jakarta/commons/proper/httpclient/trunk/src/java/org/apache/commons/httpclient/auth/AuthState.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AuthState.java Wed May 16 09:41:42 2007
@@ -1,5 +1,5 @@
 /*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/auth/AuthState.java,v 1.3 2004/11/02 19:39:16 olegk Exp $
+ * $HeadURL$
  * $Revision$
  * $Date$
  *
@@ -28,7 +28,12 @@
  *
  */
 
-package org.apache.commons.httpclient.auth;
+package org.apache.http.impl.client;
+
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.util.CharArrayBuffer;
 
 /**
  * This class provides detailed information about the state of the
@@ -39,20 +44,15 @@
  */
 public class AuthState {
 
-    public static final String PREEMPTIVE_AUTH_SCHEME = "basic";
-    
     /** Actual authentication scheme */
     private AuthScheme authScheme = null;
 
-    /** Whether an authetication challenged has been received */
-    private boolean authRequested = false;
-
-    /** Whether the authetication challenge has been responsed to */
-    private boolean authAttempted = false;
-
-    /** Whether preemtive authentication is attempted */
-    private boolean preemptive  = false; 
-      
+    /** Actual authentication scope */
+    private AuthScope authScope = null;
+    
+    /** Credentials selected for authentication */
+    private Credentials credentials = null;
+    
     /**
      * Default constructor.
      * 
@@ -66,75 +66,11 @@
      */
     public void invalidate() {
         this.authScheme = null;
-        this.authRequested = false;
-        this.authAttempted = false;
-        this.preemptive = false;
-    }
-
-    /** 
-     * Tests whether authenication challenge has been received
-     *  
-     * @return <tt>true</tt> if authenication challenge has been received, 
-     *  <tt>false</tt> otherwise
-     */
-    public boolean isAuthRequested() {
-        return this.authRequested;
-    }
-        
-    /** 
-     * Sets authentication request status
-     *  
-     * @param challengeReceived <tt>true</tt> if authenication has been requested, 
-     *  <tt>false</tt> otherwise
-     */
-    public void setAuthRequested(boolean challengeReceived) {
-        this.authRequested = challengeReceived;
-    }
-    
-    /** 
-     * Tests whether authenication challenge has been responsed to
-     *  
-     * @return <tt>true</tt> if authenication challenge has been responsed to, 
-     *  <tt>false</tt> otherwise
-     */
-    public boolean isAuthAttempted() {
-        return this.authAttempted;
-    }
-        
-    /** 
-     * Sets authentication attempt status
-     *  
-     * @param challengeResponded <tt>true</tt> if authenication has been attempted, 
-     *  <tt>false</tt> otherwise
-     */
-    public void setAuthAttempted(boolean challengeResponded) {
-        this.authAttempted = challengeResponded;
-    }
-    
-    /**
-     * Preemptively assigns Basic authentication scheme.
-     */
-    public void setPreemptive() {
-        if (!this.preemptive) {
-            if (this.authScheme != null) {
-                throw new IllegalStateException("Authentication state already initialized");
-            }
-            this.authScheme = AuthPolicy.getAuthScheme(PREEMPTIVE_AUTH_SCHEME);
-            this.preemptive = true;
-        }
+        this.authScope = null;
+        this.credentials = null;
     }
 
     /**
-     * Tests if preemptive authentication is used.
-     * 
-     * @return <tt>true</tt> if using the default Basic {@link AuthScheme 
-     * authentication scheme}, <tt>false</tt> otherwise.
-     */
-    public boolean isPreemptive() {
-        return this.preemptive;
-    }
-    
-    /**
      * Assigns the given {@link AuthScheme authentication scheme}.
      * 
      * @param authScheme the {@link AuthScheme authentication scheme}
@@ -144,10 +80,6 @@
             invalidate();
             return;
         }
-        if (this.preemptive && !(this.authScheme.getClass().isInstance(authScheme))) {
-            this.preemptive = false;
-            this.authAttempted = false;
-        }
         this.authScheme = authScheme;
     }
 
@@ -157,37 +89,57 @@
      * @return {@link AuthScheme authentication scheme}
      */
     public AuthScheme getAuthScheme() {
-        return authScheme;
+        return this.authScheme;
     }
     
-    /**
-     * Returns the authentication realm.
+    
+    /** 
+     * Returns user {@link Credentials} selected for authentication if available
      * 
-     * @return the name of the authentication realm
+     * @return user credentials if available, <code>null</code otherwise
      */
-    public String getRealm() {
-        if (this.authScheme != null) {
-            return this.authScheme.getRealm();
-        } else {
-            return null;
-        }
+    public Credentials getCredentials() {
+        return this.credentials;
     }
+
     
+    /** 
+     * Sets user {@link Credentials} to be used for authentication
+     * 
+     * @param credentials User credentials
+     */
+    public void setCredentials(final Credentials credentials) {
+        this.credentials = credentials;
+    }
+
+
+    /** 
+     * Returns actual {@link AuthScope} if available
+     * 
+     * @return actual authentication scope if available, <code>null</code otherwise
+     */
+     public AuthScope getAuthScope() {
+        return this.authScope;
+     }
+
+     /** 
+      * Sets actual {@link AuthScope}.
+      * 
+      * @param authScope Authentication scope
+      */
+     public void setAuthScope(final AuthScope authScope) {
+        this.authScope = authScope;
+     }
+
+     
     public String toString() {
-        StringBuffer buffer = new StringBuffer();
-        buffer.append("Auth state: auth requested [");
-        buffer.append(this.authRequested);
-        buffer.append("]; auth attempted [");
-        buffer.append(this.authAttempted);
-        if (this.authScheme != null) {
-            buffer.append("]; auth scheme [");
-            buffer.append(this.authScheme.getSchemeName());
-            buffer.append("]; realm [");
-            buffer.append(this.authScheme.getRealm());            
-        }
-        buffer.append("] preemptive [");
-        buffer.append(this.preemptive);
+        CharArrayBuffer buffer = new CharArrayBuffer(64);
+        buffer.append("auth scope [");
+        buffer.append(this.authScope);
+        buffer.append("]; credentials set [");
+        buffer.append(this.credentials != null ? "true" : "false");
         buffer.append("]");
         return buffer.toString();
     }
+    
 }

Added: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultAuthenticationHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultAuthenticationHandler.java?view=auto&rev=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultAuthenticationHandler.java (added)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultAuthenticationHandler.java Wed May 16 09:41:42 2007
@@ -0,0 +1,201 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.client;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthSchemeRegistry;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.client.AuthenticationHandler;
+import org.apache.http.client.params.HttpClientParams;
+import org.apache.http.message.BufferedHeader;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HTTP;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.CharArrayBuffer;
+
+/**
+ * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
+ */
+public class DefaultAuthenticationHandler implements AuthenticationHandler {
+
+    private static final Log LOG = LogFactory.getLog(DefaultAuthenticationHandler.class);
+    
+    private static List DEFAULT_SCHEME_PRIORITY = Arrays.asList(new String[] {
+            "digest",
+            "basic"
+    });
+    
+    private final AuthSchemeRegistry registry;
+    
+    public DefaultAuthenticationHandler(final AuthSchemeRegistry registry) {
+        super();
+        if (registry == null) {
+            throw new IllegalArgumentException("AuthScheme registry may not be null");
+        }
+        this.registry = registry;
+    }
+    
+    public boolean isTargetAuthenticationRequested(
+            final HttpResponse response, 
+            final HttpContext context) {
+        if (response == null) {
+            throw new IllegalArgumentException("HTTP response may not be null");
+        }
+        int status = response.getStatusLine().getStatusCode();
+        return status == HttpStatus.SC_UNAUTHORIZED;
+    }
+
+    public boolean isProxyAuthenticationRequested(
+            final HttpResponse response, 
+            final HttpContext context) {
+        if (response == null) {
+            throw new IllegalArgumentException("HTTP response may not be null");
+        }
+        int status = response.getStatusLine().getStatusCode();
+        return status == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED;
+    }
+
+    protected Map parseChallenges(
+            final Header[] headers) throws MalformedChallengeException {
+        
+        Map map = new HashMap(headers.length);
+        for (int i = 0; i < headers.length; i++) {
+            Header header = headers[i];
+            CharArrayBuffer buffer;
+            int pos;
+            if (header instanceof BufferedHeader) {
+                buffer = ((BufferedHeader) header).getBuffer();
+                pos = ((BufferedHeader) header).getValuePos();
+            } else {
+                String s = header.getValue();
+                if (s == null) {
+                    throw new MalformedChallengeException("Header value is null");
+                }
+                buffer = new CharArrayBuffer(s.length());
+                buffer.append(s);
+                pos = 0;
+            }
+            while (pos < buffer.length() && HTTP.isWhitespace(buffer.charAt(pos))) {
+                pos++;
+            }
+            int beginIndex = pos;
+            while (pos < buffer.length() && !HTTP.isWhitespace(buffer.charAt(pos))) {
+                pos++;
+            }
+            int endIndex = pos;
+            String s = buffer.substring(beginIndex, endIndex);
+            map.put(s.toLowerCase(), header);
+        }
+        return map;
+    }
+    
+    public Map getTargetChallenges(
+            final HttpResponse response, 
+            final HttpContext context) throws MalformedChallengeException {
+        if (response == null) {
+            throw new IllegalArgumentException("HTTP response may not be null");
+        }
+        Header[] headers = response.getHeaders(AUTH.WWW_AUTH);
+        return parseChallenges(headers);
+    }
+
+    public Map getProxyChallenges(
+            final HttpResponse response, 
+            final HttpContext context) throws MalformedChallengeException {
+        if (response == null) {
+            throw new IllegalArgumentException("HTTP response may not be null");
+        }
+        Header[] headers = response.getHeaders(AUTH.PROXY_AUTH);
+        return parseChallenges(headers);
+    }
+
+    public AuthScheme selectScheme(
+            final Map challenges, 
+            final HttpResponse response,
+            final HttpContext context) throws AuthenticationException {
+        
+        HttpParams params = response.getParams();
+        Collection authPrefs = (Collection) params.getParameter(
+                HttpClientParams.AUTH_SCHEME_PRIORITY);
+        if (authPrefs == null || authPrefs.isEmpty()) {
+            authPrefs = DEFAULT_SCHEME_PRIORITY;    
+        }
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Supported authentication schemes in the order of preference: " 
+                + authPrefs);
+        }
+
+        AuthScheme authScheme = null;
+        for (Iterator it = authPrefs.iterator(); it.hasNext(); ) {
+            String id = (String) it.next();
+            Header challenge = (Header) challenges.get(id.toLowerCase()); 
+            if (challenge != null) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug(id + " authentication scheme selected");
+                }
+                try {
+                    authScheme = this.registry.getAuthScheme(id, params);
+                } catch (IllegalStateException e) {
+                    throw new AuthenticationException(e.getMessage());
+                }
+                break;
+            } else {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Challenge for " + id + " authentication scheme not available");
+                    // Try again
+                }
+            }
+        }
+        if (authScheme == null) {
+            // If none selected, something is wrong
+            throw new AuthenticationException(
+                "Unable to respond to any of these challenges: "
+                    + challenges);
+        }
+        return authScheme;
+    }
+
+}

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultAuthenticationHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultAuthenticationHandler.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultAuthenticationHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java?view=diff&rev=538647&r1=538646&r2=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java Wed May 16 09:41:42 2007
@@ -37,6 +37,7 @@
 import java.net.URISyntaxException;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -50,14 +51,22 @@
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpVersion;
 import org.apache.http.ProtocolException;
+import org.apache.http.auth.AuthScheme;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.client.AuthenticationHandler;
 import org.apache.http.client.ClientRequestDirector;
 import org.apache.http.client.HttpRequestRetryHandler;
+import org.apache.http.client.HttpState;
 import org.apache.http.client.RedirectException;
 import org.apache.http.client.RedirectHandler;
 import org.apache.http.client.RoutedRequest;
 import org.apache.http.client.methods.AbortableHttpRequest;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.params.HttpClientParams;
+import org.apache.http.client.protocol.HttpClientContext;
 import org.apache.http.conn.BasicManagedEntity;
 import org.apache.http.conn.ClientConnectionManager;
 import org.apache.http.conn.ConnectionPoolTimeoutException;
@@ -113,6 +122,12 @@
     /** The redirect handler. */
     protected final RedirectHandler redirectHandler;
     
+    /** The authentication handler. */
+    private final AuthenticationHandler authHandler;
+    
+    /** The HTTP state */
+    private final HttpState state;
+    
     /** The HTTP parameters. */
     protected final HttpParams params;
     
@@ -123,12 +138,18 @@
 
     private int maxRedirects;
     
+    private final AuthState targetAuthState;
+    
+    private final AuthState proxyAuthState;
+    
     public DefaultClientRequestDirector(
             final ClientConnectionManager conman,
             final ConnectionReuseStrategy reustrat,
             final HttpProcessor httpProcessor,
             final HttpRequestRetryHandler retryHandler,
             final RedirectHandler redirectHandler,
+            final AuthenticationHandler authHandler,
+            final HttpState state,
             final HttpParams params) {
 
         if (conman == null) {
@@ -146,6 +167,12 @@
         if (redirectHandler == null) {
             throw new IllegalArgumentException("Redirect handler may not be null");
         }
+        if (authHandler == null) {
+            throw new IllegalArgumentException("Authentication handler may not be null");
+        }
+        if (state == null) {
+            throw new IllegalArgumentException("HTTP state may not be null");
+        }
         if (params == null) {
             throw new IllegalArgumentException("HTTP parameters may not be null");
         }
@@ -154,6 +181,8 @@
         this.httpProcessor = httpProcessor;
         this.retryHandler  = retryHandler;
         this.redirectHandler = redirectHandler;
+        this.authHandler   = authHandler;
+        this.state         = state;
         this.params        = params;
         this.requestExec   = new HttpRequestExecutor(params);
 
@@ -161,9 +190,8 @@
         
         this.redirectCount = 0;
         this.maxRedirects = this.params.getIntParameter(HttpClientParams.MAX_REDIRECTS, 100);
-
-        //@@@ authentication?
-
+        this.targetAuthState = new AuthState();
+        this.proxyAuthState = new AuthState();
     } // constructor
 
 
@@ -254,12 +282,8 @@
         try {
             while (!done) {
 
-                RequestWrapper request = wrapRequest(roureq.getRequest());
                 HttpRoute route = roureq.getRoute();
 
-                // Re-write request URI if needed
-                rewriteRequestURI(request, route);
-                
                 if (managedConn == null || !managedConn.isOpen()) {
                     managedConn = allocateConnection(route);
                 }
@@ -273,31 +297,53 @@
                     break;
                 }
 
+                if (HttpConnectionParams.isStaleCheckingEnabled(params)) {
+                    // validate connection
+                    LOG.debug("Stale connection check");
+                    if (managedConn.isStale()) {
+                        LOG.debug("Stale connection detected");
+                        managedConn.close();
+                        continue;
+                    }
+                }
+
+                // Wrap the original request
+                RequestWrapper request = wrapRequest(roureq.getRequest());
+                
+                // Re-write request URI if needed
+                rewriteRequestURI(request, route);
+                
+                // Use virtual host if set
+                HttpHost target = (HttpHost) request.getParams().getParameter(
+                        HttpClientParams.VIRTUAL_HOST);
+                
+                if (target == null) {
+                    target = route.getTargetHost();
+                }
+
+                HttpHost proxy = route.getProxyHost();
+                
+                // Populate the execution context
                 context.setAttribute(HttpExecutionContext.HTTP_TARGET_HOST,
-                        roureq.getRoute().getTargetHost());
+                        target);
+                context.setAttribute(HttpExecutionContext.HTTP_PROXY_HOST,
+                        proxy);
                 context.setAttribute(HttpExecutionContext.HTTP_CONNECTION,
                         managedConn);
+                context.setAttribute(HttpClientContext.TARGET_AUTH_STATE,
+                        targetAuthState);
+                context.setAttribute(HttpClientContext.PROXY_AUTH_STATE,
+                        proxyAuthState);
                 
                 requestExec.preProcess(request, httpProcessor, context);
-                //@@@ handle authentication here or via interceptor?
                 
-                if (request instanceof AbortableHttpRequest) {
-                    ((AbortableHttpRequest) request).setReleaseTrigger(managedConn);
+                if (orig instanceof AbortableHttpRequest) {
+                    ((AbortableHttpRequest) orig).setReleaseTrigger(managedConn);
                 }
 
                 context.setAttribute(HttpExecutionContext.HTTP_REQUEST,
                         request);
 
-                if (HttpConnectionParams.isStaleCheckingEnabled(params)) {
-                    // validate connection
-                    LOG.debug("Stale connection check");
-                    if (managedConn.isStale()) {
-                        LOG.debug("Stale connection detected");
-                        managedConn.close();
-                        continue;
-                    }
-                }
-                
                 execCount++;
                 try {
                     if (LOG.isDebugEnabled()) {
@@ -330,6 +376,11 @@
                 if (followup == null) {
                     done = true;
                 } else {
+                    // Make sure the response body is fully consumed, if present
+                    HttpEntity entity = response.getEntity();
+                    if (entity != null) {
+                        entity.consumeContent();
+                    }
                     // check if we can use the same connection for the followup
                     if ((managedConn != null) &&
                         !followup.getRoute().equals(roureq.getRoute())) {
@@ -556,9 +607,14 @@
                                            HttpContext context)
         throws HttpException, IOException {
 
+        HttpRoute route = roureq.getRoute();
+        HttpHost target = route.getTargetHost();
+        HttpHost proxy = route.getProxyHost();
+        InetAddress localAddress = route.getLocalAddress();
+        
         HttpParams params = request.getParams();
-        if (params.getBooleanParameter(HttpClientParams.HANDLE_REDIRECTS, true) && 
-                this.redirectHandler.isRedirectNeeded(response, context)) {
+        if (HttpClientParams.isRedirecting(params) && 
+                this.redirectHandler.isRedirectRequested(response, context)) {
 
             if (redirectCount >= maxRedirects) {
                 throw new RedirectException("Maximum redirects ("
@@ -576,8 +632,6 @@
                 return null;
             }
 
-            HttpRoute oldRoute = roureq.getRoute();
-
             HttpHost newTarget = new HttpHost(
                     uri.getHost(), 
                     uri.getPort(),
@@ -586,9 +640,6 @@
             Scheme schm = connManager.getSchemeRegistry().
                 getScheme(newTarget.getSchemeName());
             
-            InetAddress localAddress = oldRoute.getLocalAddress();
-            HttpHost proxy = oldRoute.getProxyHost();
-            
             HttpRoute newRoute = new HttpRoute(
                     newTarget,
                     localAddress,
@@ -597,12 +648,6 @@
                     (proxy != null),
                     (proxy != null));
 
-            // Make sure redirect response body is fully consumed, if present
-            HttpEntity entity = response.getEntity();
-            if (entity != null) {
-                entity.consumeContent();
-            }
-            
             HttpGet redirect = new HttpGet(uri);
             
             if (LOG.isDebugEnabled()) {
@@ -611,6 +656,64 @@
             
             return new RoutedRequest.Impl(redirect, newRoute);
         }
+
+        if (HttpClientParams.isAuthenticating(params)) {
+
+            if (this.authHandler.isTargetAuthenticationRequested(response, context)) {
+
+                target = (HttpHost) context.getAttribute(HttpExecutionContext.HTTP_TARGET_HOST);
+                if (target == null) {
+                    target = route.getTargetHost();
+                }
+                
+                LOG.debug("Target requested authentication");
+                Map challenges = this.authHandler.getTargetChallenges(response, context); 
+                try {
+                    processChallenges(challenges, this.targetAuthState, response, context);
+                } catch (AuthenticationException ex) {
+                    if (LOG.isWarnEnabled()) {
+                        LOG.warn("Authentication error: " +  ex.getMessage());
+                        return null;
+                    }
+                }
+                updateAuthState(this.targetAuthState, target);
+                
+                if (this.targetAuthState.getCredentials() != null) {
+                    // Re-try the same request via the same route
+                    return roureq;
+                } else {
+                    return null;
+                }
+            } else {
+                // Reset target auth scope
+                this.targetAuthState.setAuthScope(null);
+            }
+            
+            if (this.authHandler.isProxyAuthenticationRequested(response, context)) {
+
+                LOG.debug("Proxy requested authentication");
+                Map challenges = this.authHandler.getProxyChallenges(response, context);
+                try {
+                    processChallenges(challenges, this.proxyAuthState, response, context);
+                } catch (AuthenticationException ex) {
+                    if (LOG.isWarnEnabled()) {
+                        LOG.warn("Authentication error: " +  ex.getMessage());
+                        return null;
+                    }
+                }
+                updateAuthState(this.proxyAuthState, proxy);
+                
+                if (this.proxyAuthState.getCredentials() != null) {
+                    // Re-try the same request via the same route
+                    return roureq;
+                } else {
+                    return null;
+                }
+            } else {
+                // Reset proxy auth scope
+                this.proxyAuthState.setAuthScope(null);
+            }
+        }
         return null;
     } // handleResponse
 
@@ -671,6 +774,63 @@
     } // cleanupConnection
 
 
+    private void processChallenges(
+            final Map challenges, 
+            final AuthState authState,
+            final HttpResponse response, 
+            final HttpContext context) 
+                throws MalformedChallengeException, AuthenticationException {
+        
+        AuthScheme authScheme = authState.getAuthScheme();
+        if (authScheme == null) {
+            // Authentication not attempted before
+            authScheme = this.authHandler.selectScheme(challenges, response, context);
+            authState.setAuthScheme(authScheme);
+        }
+        AuthScheme authscheme = authState.getAuthScheme();
+        String id = authscheme.getSchemeName();
+
+        Header challenge = (Header) challenges.get(id.toLowerCase());
+        if (challenge == null) {
+            throw new AuthenticationException(id + 
+                " authorization challenge expected, but not found");
+        }
+        authscheme.processChallenge(challenge);
+        LOG.debug("Authorization challenge processed");
+    }
+    
+    
+    private void updateAuthState(final AuthState authState, final HttpHost host) {
+        AuthScheme authScheme = authState.getAuthScheme();
+        AuthScope authScope = new AuthScope(
+                host.getHostName(),
+                host.getPort(),
+                authScheme.getRealm(), 
+                authScheme.getSchemeName());  
+        
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Authentication scope: " + authScope);
+        }
+        Credentials creds = authState.getCredentials();
+        if (creds == null) {
+            creds = this.state.getCredentials(authScope);
+            if (LOG.isDebugEnabled()) {
+                if (creds != null) {
+                    LOG.debug("Found credentials");
+                } else {
+                    LOG.debug("Credentials not found");
+                }
+            }
+        } else {
+            if (authScheme.isComplete()) {
+                LOG.debug("Authentication failed");
+                creds = null;
+            }
+        }
+        authState.setAuthScope(authScope);
+        authState.setCredentials(creds);
+    }
+    
     /**
      * Prepares the entity in the ultimate response being returned.
      * The default implementation here installs an entity with auto-release
@@ -702,5 +862,5 @@
         response.setEntity(new BasicManagedEntity(entity, managedConn, reuse));
     }
 
-
+    
 } // class DefaultClientRequestDirector

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultHttpClient.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultHttpClient.java?view=diff&rev=538647&r1=538646&r2=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultHttpClient.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultHttpClient.java Wed May 16 09:41:42 2007
@@ -37,6 +37,7 @@
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpVersion;
 import org.apache.http.auth.AuthSchemeRegistry;
+import org.apache.http.client.AuthenticationHandler;
 import org.apache.http.client.HttpRequestRetryHandler;
 import org.apache.http.client.HttpState;
 import org.apache.http.client.RedirectHandler;
@@ -46,6 +47,8 @@
 import org.apache.http.client.params.HttpClientParams;
 import org.apache.http.client.protocol.HttpClientContext;
 import org.apache.http.client.protocol.RequestAddCookies;
+import org.apache.http.client.protocol.RequestProxyAuthentication;
+import org.apache.http.client.protocol.RequestTargetAuthentication;
 import org.apache.http.client.protocol.ResponseProcessCookies;
 import org.apache.http.conn.ClientConnectionManager;
 import org.apache.http.conn.ClientConnectionManagerFactory;
@@ -203,6 +206,9 @@
         // HTTP state management interceptors
         httpproc.addInterceptor(new RequestAddCookies());
         httpproc.addInterceptor(new ResponseProcessCookies());
+        // HTTP authentication interceptors
+        httpproc.addInterceptor(new RequestTargetAuthentication());
+        httpproc.addInterceptor(new RequestProxyAuthentication());
         return httpproc;
     }
 
@@ -214,6 +220,11 @@
 
     protected RedirectHandler createRedirectHandler() {
         return new DefaultRedirectHandler();
+    }
+
+
+    protected AuthenticationHandler createAuthenticationHandler() {
+        return new DefaultAuthenticationHandler(getAuthSchemes());
     }
 
 

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultRedirectHandler.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultRedirectHandler.java?view=diff&rev=538647&r1=538646&r2=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultRedirectHandler.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultRedirectHandler.java Wed May 16 09:41:42 2007
@@ -70,7 +70,7 @@
         super();
     }
     
-    public boolean isRedirectNeeded(
+    public boolean isRedirectRequested(
             final HttpResponse response,
             final HttpContext context) {
         if (response == null) {

Modified: jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/client/TestHttpState.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/client/TestHttpState.java?view=diff&rev=538647&r1=538646&r2=538647
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/client/TestHttpState.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/test/org/apache/http/client/TestHttpState.java Wed May 16 09:41:42 2007
@@ -103,26 +103,6 @@
         assertEquals(CREDS1, state.getCredentials(BOGUS));
     }
 
-    public void testHttpStateProxyCredentials() {
-        HttpState state = new HttpState();
-        state.setProxyCredentials(SCOPE1, CREDS1);
-        state.setProxyCredentials(SCOPE2, CREDS2);
-        assertEquals(CREDS1, state.getProxyCredentials(SCOPE1));
-        assertEquals(CREDS2, state.getProxyCredentials(SCOPE2));
-    }
-
-    public void testHttpStateProxyNoCredentials() {
-        HttpState state = new HttpState();
-        assertEquals(null, state.getProxyCredentials(BOGUS));
-    }
-
-    public void testHttpStateProxyDefaultCredentials() {
-        HttpState state = new HttpState();
-	    state.setProxyCredentials(AuthScope.ANY, CREDS1);
-	    state.setProxyCredentials(SCOPE2, CREDS2);
-        assertEquals(CREDS1, state.getProxyCredentials(BOGUS));
-    }
-
     // --------------------------------- Test Methods for Selecting Credentials
     
     public void testDefaultCredentials() throws Exception {



Mime
View raw message