summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Halstrick <christian.halstrick@sap.com>2013-08-04 23:37:50 +0200
committerChristian Halstrick <christian.halstrick@sap.com>2014-02-18 21:04:17 +0100
commit2290516ddb5a92ccc296df500aa5e9e30cbc240e (patch)
tree04397a7a84eddccdc7fed53e5aa47efbb7fa77c5
parent38c4f35d8b911426e007716697b37d746740b788 (diff)
downloadjgit-2290516ddb5a92ccc296df500aa5e9e30cbc240e.tar.gz
jgit-2290516ddb5a92ccc296df500aa5e9e30cbc240e.zip
Add an implementation for HttpConnection using Apache HttpClient
This change implements the http connection abstraction with the help of org.apache.http.client.HttpClient. The default implementation used by JGit is still the JDK HttpURLConnection. But now JGit users have the possibility to switch completely to org.apache.httpclient. The reason for this is that in certain (e.g. cloud) environments you are forced to use the org.apache classes. Change-Id: I0b357f23243ed13a014c79ba179fa327dfe318b2 Signed-off-by: Christian Halstrick <christian.halstrick@sap.com> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
-rw-r--r--org.eclipse.jgit.http.test/META-INF/MANIFEST.MF6
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java21
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java21
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java21
-rw-r--r--org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml14
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml7
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.target6
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target6
-rw-r--r--org.eclipse.jgit/META-INF/MANIFEST.MF18
-rw-r--r--org.eclipse.jgit/pom.xml5
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/http/HttpConnection.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java366
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/HttpClientConnectionFactory.java66
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/TemporaryBufferEntity.java109
-rw-r--r--pom.xml8
18 files changed, 677 insertions, 1 deletions
diff --git a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
index ce69bfb58c..4bc2e74593 100644
--- a/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.http.test/META-INF/MANIFEST.MF
@@ -35,7 +35,11 @@ Import-Package: javax.servlet;version="[2.5.0,3.0.0)",
org.eclipse.jgit.revwalk;version="[3.3.0,3.4.0)",
org.eclipse.jgit.storage.file;version="[3.3.0,3.4.0)",
org.eclipse.jgit.transport;version="[3.3.0,3.4.0)",
+ org.eclipse.jgit.transport.http;version="[3.3.0,3.4.0)",
+ org.eclipse.jgit.transport.http.apache;version="[3.3.0,3.4.0)",
org.eclipse.jgit.transport.resolver;version="[3.3.0,3.4.0)",
org.eclipse.jgit.util;version="[3.3.0,3.4.0)",
org.hamcrest.core;version="[1.1.0,2.0.0)",
- org.junit;version="[4.0.0,5.0.0)"
+ org.junit;version="[4.0.0,5.0.0)",
+ org.junit.runner;version="[4.0.0,5.0.0)",
+ org.junit.runners;version="[4.0.0,5.0.0)"
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java
index 1726dc5eb9..dec9b59f2d 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientDumbServerTest.java
@@ -55,6 +55,8 @@ import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.net.URI;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -76,9 +78,16 @@ import org.eclipse.jgit.transport.HttpTransport;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
+import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+@RunWith(Parameterized.class)
public class DumbClientDumbServerTest extends HttpTestCase {
private Repository remoteRepository;
@@ -88,6 +97,18 @@ public class DumbClientDumbServerTest extends HttpTestCase {
private RevCommit A, B;
+ @Parameters
+ public static Collection<Object[]> data() {
+ // run all tests with both connection factories we have
+ return Arrays.asList(new Object[][] {
+ { new JDKHttpConnectionFactory() },
+ { new HttpClientConnectionFactory() } });
+ }
+
+ public DumbClientDumbServerTest(HttpConnectionFactory cf) {
+ HttpTransport.setConnectionFactory(cf);
+ }
+
@Before
public void setUp() throws Exception {
super.setUp();
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
index 354b0439ab..7b4270f1b8 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
@@ -55,6 +55,8 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -79,11 +81,18 @@ import org.eclipse.jgit.transport.HttpTransport;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
+import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+@RunWith(Parameterized.class)
public class DumbClientSmartServerTest extends HttpTestCase {
private Repository remoteRepository;
@@ -93,6 +102,18 @@ public class DumbClientSmartServerTest extends HttpTestCase {
private RevCommit A, B;
+ @Parameters
+ public static Collection<Object[]> data() {
+ // run all tests with both connection factories we have
+ return Arrays.asList(new Object[][] {
+ { new JDKHttpConnectionFactory() },
+ { new HttpClientConnectionFactory() } });
+ }
+
+ public DumbClientSmartServerTest(HttpConnectionFactory cf) {
+ HttpTransport.setConnectionFactory(cf);
+ }
+
@Before
public void setUp() throws Exception {
super.setUp();
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
index 7b3c717afd..bb612b1a68 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
@@ -56,6 +56,8 @@ import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -98,11 +100,18 @@ import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
+import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+@RunWith(Parameterized.class)
public class SmartClientSmartServerTest extends HttpTestCase {
private static final String HDR_TRANSFER_ENCODING = "Transfer-Encoding";
@@ -116,6 +125,18 @@ public class SmartClientSmartServerTest extends HttpTestCase {
private RevCommit A, B;
+ @Parameters
+ public static Collection<Object[]> data() {
+ // run all tests with both connection factories we have
+ return Arrays.asList(new Object[][] {
+ { new JDKHttpConnectionFactory() },
+ { new HttpClientConnectionFactory() } });
+ }
+
+ public SmartClientSmartServerTest(HttpConnectionFactory cf) {
+ HttpTransport.setConnectionFactory(cf);
+ }
+
@Before
public void setUp() throws Exception {
super.setUp();
diff --git a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
index 0991fb61d5..61058ed143 100644
--- a/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit.junit.http/META-INF/MANIFEST.MF
@@ -9,6 +9,7 @@ Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: javax.servlet;version="[2.5.0,3.0.0)",
javax.servlet.http;version="[2.5.0,3.0.0)",
+ org.apache.commons.logging;version="[1.1.1,2.0.0)",
org.eclipse.jetty.http;version="[7.6.0,8.0.0)",
org.eclipse.jetty.security;version="[7.6.0,8.0.0)",
org.eclipse.jetty.security.authentication;version="[7.6.0,8.0.0)",
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
index 4ca2629220..443fffe07c 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.feature/feature.xml
@@ -57,4 +57,18 @@
version="0.0.0"
unpack="false"/>
+ <plugin
+ id="org.apache.httpcomponents.httpcore"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.apache.httpcomponents.httpclient"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
index d23e4d72d5..6877a5f24f 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.junit.feature/feature.xml
@@ -47,4 +47,11 @@
version="0.0.0"
unpack="false"/>
+ <plugin
+ id="org.apache.commons.logging"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.target
index 7e1673b50c..9bf94ccc8a 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.3.target
@@ -35,6 +35,12 @@
<unit id="org.apache.ant" version="1.8.4.v201303080030"/>
<unit id="org.apache.commons.compress" version="1.6.0.v201310281400"/>
<unit id="org.apache.commons.compress.source" version="1.6.0.v201310281400"/>
+ <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/>
+ <unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
+ <unit id="org.apache.httpcomponents.httpcore" version="4.1.4.v201203221030"/>
+ <unit id="org.apache.httpcomponents.httpcore.source" version="4.1.4.v201203221030"/>
+ <unit id="org.apache.httpcomponents.httpclient" version="4.1.3.v201209201135"/>
+ <unit id="org.apache.httpcomponents.httpclient.source" version="4.1.3.v201209201135"/>
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
<unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
<unit id="org.kohsuke.args4j" version="2.0.21.v201301150030"/>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target
index dabfae0ddd..a99cfd64f2 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.4.target
@@ -35,6 +35,12 @@
<unit id="org.apache.ant" version="1.9.2.v201307241445"/>
<unit id="org.apache.commons.compress" version="1.6.0.v201310281400"/>
<unit id="org.apache.commons.compress.source" version="1.6.0.v201310281400"/>
+ <unit id="org.apache.commons.logging" version="1.1.1.v201101211721"/>
+ <unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
+ <unit id="org.apache.httpcomponents.httpcore" version="4.1.4.v201203221030"/>
+ <unit id="org.apache.httpcomponents.httpcore.source" version="4.1.4.v201203221030"/>
+ <unit id="org.apache.httpcomponents.httpclient" version="4.1.3.v201209201135"/>
+ <unit id="org.apache.httpcomponents.httpclient.source" version="4.1.3.v201209201135"/>
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
<unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
<unit id="org.kohsuke.args4j" version="2.0.21.v201301150030"/>
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index 2b05980510..1249b29c6a 100644
--- a/org.eclipse.jgit/META-INF/MANIFEST.MF
+++ b/org.eclipse.jgit/META-INF/MANIFEST.MF
@@ -109,6 +109,12 @@ Export-Package: org.eclipse.jgit.api;version="3.3.0";
org.eclipse.jgit.storage.pack",
org.eclipse.jgit.transport.http;version="3.3.0";
uses:="javax.net.ssl",
+ org.eclipse.jgit.transport.http.apache;version="3.3.0";
+ uses:="org.eclipse.jgit.transport.http,
+ javax.net.ssl,
+ org.apache.http.client,
+ org.apache.http.client.methods,
+ org.apache.http",
org.eclipse.jgit.transport.resolver;version="3.3.0";
uses:="org.eclipse.jgit.lib,org.eclipse.jgit.transport",
org.eclipse.jgit.treewalk;version="3.3.0";
@@ -128,5 +134,17 @@ Require-Bundle: com.jcraft.jsch;bundle-version="[0.1.37,0.2.0)"
Import-Package: com.googlecode.javaewah;version="[0.7.9,0.8.0)",
javax.crypto,
javax.net.ssl,
+ org.apache.http;version="[4.1.0,5.0.0)",
+ org.apache.http.client;version="[4.1.0,5.0.0)",
+ org.apache.http.client.methods;version="[4.1.0,5.0.0)",
+ org.apache.http.client.params;version="[4.1.0,5.0.0)",
+ org.apache.http.conn;version="[4.1.0,5.0.0)",
+ org.apache.http.conn.params;version="[4.1.0,5.0.0)",
+ org.apache.http.conn.scheme;version="[4.1.0,5.0.0)",
+ org.apache.http.conn.ssl;version="[4.1.0,5.0.0)",
+ org.apache.http.entity;version="[4.1.0,5.0.0)",
+ org.apache.http.impl.client;version="[4.1.0,5.0.0)",
+ org.apache.http.impl.client.cache;version="[4.1.0,5.0.0)",
+ org.apache.http.params;version="[4.1.0,5.0.0)",
org.xml.sax,
org.xml.sax.helpers
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index f45c4f8a8b..c3f681e9c6 100644
--- a/org.eclipse.jgit/pom.xml
+++ b/org.eclipse.jgit/pom.xml
@@ -78,6 +78,11 @@
<groupId>com.googlecode.javaewah</groupId>
<artifactId>JavaEWAH</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </dependency>
</dependencies>
<build>
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index bb67c127a7..40b5c0b2d2 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -522,6 +522,7 @@ unexpectedOddResult=odd: {0} + {1} - {2}
unexpectedRefReport={0}: unexpected ref report: {1}
unexpectedReportLine=unexpected report line: {0}
unexpectedReportLine2={0} unexpected report line: {1}
+unexpectedSSLContextException=unexpected exception when searching for the TLS protocol
unknownOrUnsupportedCommand=Unknown or unsupported command "{0}", only "{1}" is allowed.
unknownDIRCVersion=Unknown DIRC version {0}
unknownHost=unknown host
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index f9700a1ff4..dcee707275 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -584,6 +584,7 @@ public class JGitText extends TranslationBundle {
/***/ public String unexpectedRefReport;
/***/ public String unexpectedReportLine;
/***/ public String unexpectedReportLine2;
+ /***/ public String unexpectedSSLContextException;
/***/ public String unknownOrUnsupportedCommand;
/***/ public String unknownDIRCVersion;
/***/ public String unknownHost;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/HttpConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/HttpConnection.java
index 0cf12aaa26..09613fd7ac 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/HttpConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/HttpConnection.java
@@ -258,6 +258,7 @@ public interface HttpConnection {
* @param random
* the source of randomness for this generator or null. See
* {@link SSLContext#init(KeyManager[], TrustManager[], SecureRandom)}
+ *
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java
new file mode 100644
index 0000000000..16003df1f9
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/HttpClientConnection.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2013 Christian Halstrick <christian.halstrick@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.transport.http.apache;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.Proxy;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+
+import org.apache.http.Header;
+import org.apache.http.HeaderElement;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpPut;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.params.ClientPNames;
+import org.apache.http.conn.params.ConnRoutePNames;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.params.CoreConnectionPNames;
+import org.apache.http.params.HttpParams;
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.transport.http.HttpConnection;
+import org.eclipse.jgit.util.TemporaryBuffer;
+import org.eclipse.jgit.util.TemporaryBuffer.LocalFile;
+
+/**
+ * A {@link HttpConnection} which uses {@link HttpClient}
+ *
+ * @since 3.3
+ */
+public class HttpClientConnection implements HttpConnection {
+ HttpClient client;
+
+ String urlStr;
+
+ HttpUriRequest req;
+
+ HttpResponse resp = null;
+
+ String method = "GET"; //$NON-NLS-1$
+
+ private TemporaryBufferEntity entity;
+
+ private boolean isUsingProxy = false;
+
+ private Proxy proxy;
+
+ private Integer timeout = null;
+
+ private Integer readTimeout;
+
+ private Boolean followRedirects;
+
+ private X509HostnameVerifier hostnameverifier;
+
+ SSLContext ctx;
+
+ private HttpClient getClient() {
+ if (client == null)
+ client = new DefaultHttpClient();
+ HttpParams params = client.getParams();
+ if (proxy != null && !Proxy.NO_PROXY.equals(proxy)) {
+ isUsingProxy = true;
+ InetSocketAddress adr = (InetSocketAddress) proxy.address();
+ params.setParameter(ConnRoutePNames.DEFAULT_PROXY,
+ new HttpHost(adr.getHostName(), adr.getPort()));
+ }
+ if (timeout != null)
+ params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
+ timeout.intValue());
+ if (readTimeout != null)
+ params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT,
+ readTimeout.intValue());
+ if (followRedirects != null)
+ params.setBooleanParameter(ClientPNames.HANDLE_REDIRECTS,
+ followRedirects.booleanValue());
+ if (hostnameverifier != null) {
+ SSLSocketFactory sf;
+ sf = new SSLSocketFactory(getSSLContext(), hostnameverifier);
+ Scheme https = new Scheme("https", 443, sf); //$NON-NLS-1$
+ client.getConnectionManager().getSchemeRegistry().register(https);
+ }
+
+ return client;
+ }
+
+ private SSLContext getSSLContext() {
+ if (ctx == null) {
+ try {
+ ctx = SSLContext.getInstance("TLS"); //$NON-NLS-1$
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalStateException(
+ JGitText.get().unexpectedSSLContextException, e);
+ }
+ }
+ return ctx;
+ }
+
+ /**
+ * Sets the buffer from which to take the request body
+ *
+ * @param buffer
+ */
+ public void setBuffer(TemporaryBuffer buffer) {
+ this.entity = new TemporaryBufferEntity(buffer);
+ }
+
+ /**
+ * @param urlStr
+ */
+ public HttpClientConnection(String urlStr) {
+ this(urlStr, null);
+ }
+
+ /**
+ * @param urlStr
+ * @param proxy
+ */
+ public HttpClientConnection(String urlStr, Proxy proxy) {
+ this(urlStr, proxy, null);
+ }
+
+ /**
+ * @param urlStr
+ * @param proxy
+ * @param cl
+ */
+ public HttpClientConnection(String urlStr, Proxy proxy, HttpClient cl) {
+ this.client = cl;
+ this.urlStr = urlStr;
+ this.proxy = proxy;
+ }
+
+ public int getResponseCode() throws IOException {
+ execute();
+ return resp.getStatusLine().getStatusCode();
+ }
+
+ public URL getURL() {
+ try {
+ return new URL(urlStr);
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ public String getResponseMessage() throws IOException {
+ execute();
+ return resp.getStatusLine().getReasonPhrase();
+ }
+
+ private void execute() throws IOException, ClientProtocolException {
+ if (resp == null)
+ if (entity != null) {
+ if (req instanceof HttpEntityEnclosingRequest) {
+ HttpEntityEnclosingRequest eReq = (HttpEntityEnclosingRequest) req;
+ eReq.setEntity(entity);
+ }
+ resp = getClient().execute(req);
+ entity.getBuffer().close();
+ entity = null;
+ } else
+ resp = getClient().execute(req);
+ }
+
+ public Map<String, List<String>> getHeaderFields() {
+ Map<String, List<String>> ret = new HashMap<String, List<String>>();
+ for (Header hdr : resp.getAllHeaders()) {
+ List<String> list = new LinkedList<String>();
+ for (HeaderElement hdrElem : hdr.getElements())
+ list.add(hdrElem.toString());
+ ret.put(hdr.getName(), list);
+ }
+ return ret;
+ }
+
+ public void setRequestProperty(String name, String value) {
+ req.addHeader(name, value);
+ }
+
+ public void setRequestMethod(String method) throws ProtocolException {
+ this.method = method;
+ if ("GET".equalsIgnoreCase(method)) //$NON-NLS-1$
+ req = new HttpGet(urlStr);
+ else if ("PUT".equalsIgnoreCase(method)) //$NON-NLS-1$
+ req = new HttpPut(urlStr);
+ else if ("POST".equalsIgnoreCase(method)) //$NON-NLS-1$
+ req = new HttpPost(urlStr);
+ else {
+ this.method = null;
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public void setUseCaches(boolean usecaches) {
+ // not needed
+ }
+
+ public void setConnectTimeout(int timeout) {
+ this.timeout = new Integer(timeout);
+ }
+
+ public void setReadTimeout(int readTimeout) {
+ this.readTimeout = new Integer(readTimeout);
+ }
+
+ public String getContentType() {
+ HttpEntity responseEntity = resp.getEntity();
+ if (responseEntity != null) {
+ Header contentType = responseEntity.getContentType();
+ if (contentType != null)
+ return contentType.getValue();
+ }
+ return null;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return resp.getEntity().getContent();
+ }
+
+ // will return only the first field
+ public String getHeaderField(String name) {
+ Header header = resp.getFirstHeader(name);
+ return (header == null) ? null : header.getValue();
+ }
+
+ public int getContentLength() {
+ return Integer.parseInt(resp.getFirstHeader("content-length") //$NON-NLS-1$
+ .getValue());
+ }
+
+ public void setInstanceFollowRedirects(boolean followRedirects) {
+ this.followRedirects = new Boolean(followRedirects);
+ }
+
+ public void setDoOutput(boolean dooutput) {
+ // TODO: check whether we can really ignore this.
+ }
+
+ public void setFixedLengthStreamingMode(int contentLength) {
+ if (entity != null)
+ throw new IllegalArgumentException();
+ entity = new TemporaryBufferEntity(new LocalFile());
+ entity.setContentLength(contentLength);
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ if (entity == null)
+ entity = new TemporaryBufferEntity(new LocalFile());
+ return entity.getBuffer();
+ }
+
+ public void setChunkedStreamingMode(int chunklen) {
+ if (entity == null)
+ entity = new TemporaryBufferEntity(new LocalFile());
+ entity.setChunked(true);
+ }
+
+ public String getRequestMethod() {
+ return method;
+ }
+
+ public boolean usingProxy() {
+ return isUsingProxy;
+ }
+
+ public void connect() throws IOException {
+ execute();
+ }
+
+ public void setHostnameVerifier(final HostnameVerifier hostnameverifier) {
+ this.hostnameverifier = new X509HostnameVerifier() {
+ public boolean verify(String hostname, SSLSession session) {
+ return hostnameverifier.verify(hostname, session);
+ }
+
+ public void verify(String host, String[] cns, String[] subjectAlts)
+ throws SSLException {
+ throw new UnsupportedOperationException(); // TODO message
+ }
+
+ public void verify(String host, X509Certificate cert)
+ throws SSLException {
+ throw new UnsupportedOperationException(); // TODO message
+ }
+
+ public void verify(String host, SSLSocket ssl) throws IOException {
+ hostnameverifier.verify(host, ssl.getSession());
+ }
+ };
+ }
+
+ public void configure(KeyManager[] km, TrustManager[] tm,
+ SecureRandom random) throws KeyManagementException {
+ getSSLContext().init(km, tm, random);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/HttpClientConnectionFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/HttpClientConnectionFactory.java
new file mode 100644
index 0000000000..fe1eef484a
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/HttpClientConnectionFactory.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 Christian Halstrick <christian.halstrick@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.transport.http.apache;
+
+import java.io.IOException;
+import java.net.Proxy;
+import java.net.URL;
+
+import org.eclipse.jgit.transport.http.HttpConnection;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+
+/**
+ * A factory returning instances of {@link HttpClientConnection}
+ *
+ * @since 3.3
+ */
+public class HttpClientConnectionFactory implements HttpConnectionFactory {
+ public HttpConnection create(URL url) throws IOException {
+ return new HttpClientConnection(url.toString());
+ }
+
+ public HttpConnection create(URL url, Proxy proxy)
+ throws IOException {
+ return new HttpClientConnection(url.toString(), proxy);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/TemporaryBufferEntity.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/TemporaryBufferEntity.java
new file mode 100644
index 0000000000..1ff168e237
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/http/apache/TemporaryBufferEntity.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 Christian Halstrick <christian.halstrick@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ * names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.transport.http.apache;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.entity.AbstractHttpEntity;
+import org.eclipse.jgit.util.TemporaryBuffer;
+
+/**
+ * A {@link HttpEntity} which takes it's content from a {@link TemporaryBuffer}
+ *
+ * @since 3.3
+ */
+public class TemporaryBufferEntity extends AbstractHttpEntity {
+ private TemporaryBuffer buffer;
+
+ private Integer contentLength;
+
+ /**
+ * Construct a new {@link HttpEntity} which will contain the content stored
+ * in the specified buffer
+ *
+ * @param buffer
+ */
+ public TemporaryBufferEntity(TemporaryBuffer buffer) {
+ this.buffer = buffer;
+ }
+
+ /**
+ * @return buffer containing the content
+ */
+ public TemporaryBuffer getBuffer() {
+ return buffer;
+ }
+
+ public boolean isRepeatable() {
+ return true;
+ }
+
+ public long getContentLength() {
+ if (contentLength != null)
+ return contentLength.intValue();
+ return buffer.length();
+ }
+
+ public InputStream getContent() throws IOException, IllegalStateException {
+ return buffer.openInputStream();
+ }
+
+ public void writeTo(OutputStream outstream) throws IOException {
+ // TODO: dont we need a progressmonitor
+ buffer.writeTo(outstream, null);
+ }
+
+ public boolean isStreaming() {
+ return false;
+ }
+
+ /**
+ * @param contentLength
+ */
+ public void setContentLength(int contentLength) {
+ this.contentLength = new Integer(contentLength);
+ }
+}
diff --git a/pom.xml b/pom.xml
index 84ac448145..5d564d27ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -186,6 +186,7 @@
<servlet-api-version>2.5</servlet-api-version>
<jetty-version>7.6.14.v20131031</jetty-version>
<clirr-version>2.4</clirr-version>
+ <httpclient-version>4.1.3</httpclient-version>
</properties>
<repositories>
@@ -193,6 +194,7 @@
<id>jgit-repository</id>
<url>http://download.eclipse.org/jgit/maven</url>
</repository>
+
</repositories>
<pluginRepositories>
@@ -474,6 +476,12 @@
<artifactId>org.osgi.core</artifactId>
<version>${osgi-core-version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>${httpclient-version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>