diff options
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); + } +} @@ -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> |