summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteffen Pingel2012-01-17 18:51:38 (EST)
committerSteffen Pingel2012-01-17 18:51:38 (EST)
commitbba2de5766319ad8697bef544e49145dbf9bcd60 (patch)
tree78a25fee83b52240c9d7b655998c146e0bf92396
parent6eba6ca65b76ed6589cc2f81c103d17e36fc055f (diff)
downloadorg.eclipse.mylyn.commons-bba2de5766319ad8697bef544e49145dbf9bcd60.zip
org.eclipse.mylyn.commons-bba2de5766319ad8697bef544e49145dbf9bcd60.tar.gz
org.eclipse.mylyn.commons-bba2de5766319ad8697bef544e49145dbf9bcd60.tar.bz2
NEW - bug 368777: [api] support pre-emptive authentication in
CommonHttpClient https://bugs.eclipse.org/bugs/show_bug.cgi?id=368777 Change-Id: I1e0b2f0d8cf864703b650b64217683da7d676919
-rw-r--r--org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/operations/IOperationMonitor.java1
-rw-r--r--org.eclipse.mylyn.commons.repositories.http.core/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/CommonHttpClient.java29
-rw-r--r--org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/HttpRequestProcessor.java8
-rw-r--r--org.eclipse.mylyn.commons.repositories.http.tests/src/org/eclipse/mylyn/commons/repositories/http/tests/CommonHttpClientProxyTest.java106
-rw-r--r--org.eclipse.mylyn.commons.sdk.util/src/org/eclipse/mylyn/commons/sdk/util/TestProxy.java7
6 files changed, 151 insertions, 1 deletions
diff --git a/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/operations/IOperationMonitor.java b/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/operations/IOperationMonitor.java
index 2b869a2..b563cc1 100644
--- a/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/operations/IOperationMonitor.java
+++ b/org.eclipse.mylyn.commons.core/src/org/eclipse/mylyn/commons/core/operations/IOperationMonitor.java
@@ -18,6 +18,7 @@ import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
* @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended by clients.
* @since 3.7
+ * @see OperationUtil
*/
public interface IOperationMonitor extends IProgressMonitorWithBlocking {
diff --git a/org.eclipse.mylyn.commons.repositories.http.core/META-INF/MANIFEST.MF b/org.eclipse.mylyn.commons.repositories.http.core/META-INF/MANIFEST.MF
index 111a796..1c91a6b 100644
--- a/org.eclipse.mylyn.commons.repositories.http.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.mylyn.commons.repositories.http.core/META-INF/MANIFEST.MF
@@ -18,6 +18,7 @@ Import-Package: org.apache.commons.logging;version="[1.0.4,2.0.0)",
org.apache.http.impl;version="4.1.0",
org.apache.http.auth;version="4.1.0",
org.apache.http.auth.params;version="4.1.0",
+ org.apache.http.impl.auth;version="4.1.0",
org.apache.http.util;version="4.1.0",
org.apache.http.client;version="4.1.0",
org.apache.http.client.methods;version="4.1.0",
diff --git a/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/CommonHttpClient.java b/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/CommonHttpClient.java
index 38a85d7..c070178 100644
--- a/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/CommonHttpClient.java
+++ b/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/CommonHttpClient.java
@@ -15,13 +15,16 @@ import java.io.IOException;
import javax.net.ssl.TrustManager;
+import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.AbstractHttpClient;
+import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.SyncBasicHttpContext;
@@ -44,6 +47,8 @@ import org.eclipse.mylyn.commons.repositories.core.auth.UserCredentials;
*/
public class CommonHttpClient {
+ private boolean preemptiveAuthenticationEnabled;
+
private boolean authenticated;
private final SyncBasicHttpContext context;
@@ -95,6 +100,10 @@ public class CommonHttpClient {
return authenticated;
}
+ public boolean isPreemptiveAuthenticationEnabled() {
+ return preemptiveAuthenticationEnabled;
+ }
+
public boolean needsAuthentication() {
return !isAuthenticated() && getLocation().getCredentials(AuthenticationType.REPOSITORY, false) != null;
}
@@ -107,13 +116,31 @@ public class CommonHttpClient {
this.httpAuthenticationType = httpAuthenticationType;
}
+ public void setPreemptiveAuthenticationEnabled(boolean preemptiveAuthenticationEnabled) {
+ this.preemptiveAuthenticationEnabled = preemptiveAuthenticationEnabled;
+ }
+
private void prepareRequest(HttpRequestBase request, IOperationMonitor monitor) {
UserCredentials httpCredentials = location.getCredentials(httpAuthenticationType);
if (httpCredentials != null) {
HttpUtil.configureAuthentication(getHttpClient(), location, httpCredentials);
+
+ if (isPreemptiveAuthenticationEnabled()) {
+ // create or pre-populate auth cache
+ HttpHost host = HttpUtil.createHost(request);
+ Object authCache = context.getAttribute(ClientContext.AUTH_CACHE);
+ if (authCache == null) {
+ authCache = new BasicAuthCache();
+ context.setAttribute(ClientContext.AUTH_CACHE, authCache);
+ }
+ if (authCache instanceof BasicAuthCache) {
+ if (((BasicAuthCache) authCache).get(host) == null) {
+ ((BasicAuthCache) authCache).put(host, new BasicScheme());
+ }
+ }
+ }
}
HttpUtil.configureProxy(getHttpClient(), location);
- HttpUtil.configureProxy(getHttpClient(), location);
CertificateCredentials socketCredentials = location.getCredentials(AuthenticationType.CERTIFICATE);
if (socketCredentials != null) {
diff --git a/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/HttpRequestProcessor.java b/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/HttpRequestProcessor.java
index ec27d8b..5e45e59 100644
--- a/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/HttpRequestProcessor.java
+++ b/org.eclipse.mylyn.commons.repositories.http.core/src/org/eclipse/mylyn/commons/repositories/http/core/HttpRequestProcessor.java
@@ -20,6 +20,14 @@ import org.eclipse.mylyn.commons.core.operations.IOperationMonitor;
*/
public abstract class HttpRequestProcessor<T> {
+ public static final HttpRequestProcessor<CommonHttpResponse> DEFAULT = new HttpRequestProcessor<CommonHttpResponse>() {
+ @Override
+ protected CommonHttpResponse doProcess(CommonHttpResponse response, IOperationMonitor monitor)
+ throws IOException {
+ return response;
+ }
+ };
+
private final boolean autoRelease;
public HttpRequestProcessor() {
diff --git a/org.eclipse.mylyn.commons.repositories.http.tests/src/org/eclipse/mylyn/commons/repositories/http/tests/CommonHttpClientProxyTest.java b/org.eclipse.mylyn.commons.repositories.http.tests/src/org/eclipse/mylyn/commons/repositories/http/tests/CommonHttpClientProxyTest.java
new file mode 100644
index 0000000..9500ee4
--- /dev/null
+++ b/org.eclipse.mylyn.commons.repositories.http.tests/src/org/eclipse/mylyn/commons/repositories/http/tests/CommonHttpClientProxyTest.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2010 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.commons.repositories.http.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.http.HttpStatus;
+import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation;
+import org.eclipse.mylyn.commons.repositories.core.auth.AuthenticationException;
+import org.eclipse.mylyn.commons.repositories.core.auth.AuthenticationType;
+import org.eclipse.mylyn.commons.repositories.core.auth.UserCredentials;
+import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpClient;
+import org.eclipse.mylyn.commons.repositories.http.core.CommonHttpResponse;
+import org.eclipse.mylyn.commons.repositories.http.core.HttpRequestProcessor;
+import org.eclipse.mylyn.commons.sdk.util.TestProxy;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Steffen Pingel
+ */
+public class CommonHttpClientProxyTest {
+
+ private TestProxy testProxy;
+
+ public CommonHttpClientProxyTest() {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ testProxy = new TestProxy();
+ testProxy.startAndWait();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ testProxy.stop();
+ }
+
+ @Test
+ public void testExecuteGetNoPreemptiveAuth() throws Exception {
+ RepositoryLocation location = new RepositoryLocation(testProxy.getUrl());
+ location.setCredentials(AuthenticationType.HTTP, new UserCredentials("user", "pass"));
+ CommonHttpClient client = new CommonHttpClient(location);
+
+ testProxy.addResponse(TestProxy.OK);
+ CommonHttpResponse response = client.executeGet("/", null, HttpRequestProcessor.DEFAULT);
+ assertEquals(HttpStatus.SC_OK, response.getStatusCode());
+ assertEquals(null, testProxy.getRequest().getHeader("Authorization"));
+ }
+
+ @Test(expected = AuthenticationException.class)
+ public void testExecuteGetAuthChallengeNoCredentials() throws Exception {
+ RepositoryLocation location = new RepositoryLocation(testProxy.getUrl());
+ CommonHttpClient client = new CommonHttpClient(location);
+
+ testProxy.addResponse(TestProxy.UNAUTHORIZED);
+ client.executeGet("/", null, HttpRequestProcessor.DEFAULT);
+ }
+
+ @Test
+ public void testExecuteGetAuthChallenge() throws Exception {
+ RepositoryLocation location = new RepositoryLocation(testProxy.getUrl());
+ location.setCredentials(AuthenticationType.HTTP, new UserCredentials("user", "pass"));
+ CommonHttpClient client = new CommonHttpClient(location);
+
+ testProxy.addResponse(TestProxy.UNAUTHORIZED);
+ testProxy.addResponse(TestProxy.OK);
+ CommonHttpResponse response = client.executeGet("/", null, HttpRequestProcessor.DEFAULT);
+ assertEquals(HttpStatus.SC_OK, response.getStatusCode());
+ assertEquals("Did not expect preemptive credentails", null, testProxy.getRequest().getHeader("Authorization"));
+ assertEquals("Expect credentails on challenge", "Authorization: Basic dXNlcjpwYXNz", testProxy.getRequest()
+ .getHeader("Authorization"));
+ }
+
+ @Test
+ public void testExecuteGetPreemptiveAuth() throws Exception {
+ RepositoryLocation location = new RepositoryLocation(testProxy.getUrl());
+ location.setCredentials(AuthenticationType.HTTP, new UserCredentials("user", "pass"));
+ CommonHttpClient client = new CommonHttpClient(location);
+
+ client.setPreemptiveAuthenticationEnabled(true);
+ testProxy.addResponse(TestProxy.OK);
+ CommonHttpResponse response = client.executeGet("/", null, HttpRequestProcessor.DEFAULT);
+ assertEquals("Authorization: Basic dXNlcjpwYXNz", testProxy.getRequest().getHeader("Authorization"));
+ assertEquals(HttpStatus.SC_OK, response.getStatusCode());
+
+ // subsequent requests will have cached credentials
+ client.setPreemptiveAuthenticationEnabled(false);
+ testProxy.addResponse(TestProxy.OK);
+ response = client.executeGet("/", null, HttpRequestProcessor.DEFAULT);
+ assertEquals("Authorization: Basic dXNlcjpwYXNz", testProxy.getRequest().getHeader("Authorization"));
+ assertEquals(HttpStatus.SC_OK, response.getStatusCode());
+ }
+
+}
diff --git a/org.eclipse.mylyn.commons.sdk.util/src/org/eclipse/mylyn/commons/sdk/util/TestProxy.java b/org.eclipse.mylyn.commons.sdk.util/src/org/eclipse/mylyn/commons/sdk/util/TestProxy.java
index 336521d..ac8702e 100644
--- a/org.eclipse.mylyn.commons.sdk.util/src/org/eclipse/mylyn/commons/sdk/util/TestProxy.java
+++ b/org.eclipse.mylyn.commons.sdk.util/src/org/eclipse/mylyn/commons/sdk/util/TestProxy.java
@@ -112,6 +112,8 @@ public class TestProxy implements Runnable {
public static final Message TIMEOUT = new Message("HTTP/1.1 200 OK");
+ public static final Message UNAUTHORIZED = new Message("HTTP/1.1 401 Unauthorized");
+
public static final Message SERVICE_UNVAILABLE = createEmptyMessage("HTTP/1.1 503 Service Unavailable");
static {
@@ -119,6 +121,7 @@ public class TestProxy implements Runnable {
OK.headers.add(HEADER_CONNECTION_CLOSE);
SERVICE_UNVAILABLE.headers.add(HEADER_CONNECTION_CLOSE);
TIMEOUT.headers.add("Content-Length: 500");
+ UNAUTHORIZED.headers.add("WWW-Authenticate: Basic realm=\"Test\"");
}
private static Message createEmptyMessage(String status) {
@@ -317,6 +320,10 @@ public class TestProxy implements Runnable {
return serverSocket.getLocalPort();
}
+ public String getUrl() {
+ return "http://" + serverSocket.getInetAddress().getHostAddress() + ":" + serverSocket.getLocalPort();
+ }
+
public void stop() {
stopped = true;
try {