Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Sawicki2011-12-12 23:36:44 +0000
committerKevin Sawicki2011-12-12 23:36:44 +0000
commitca40854c3794b7e720e9d3762c3bbd45c5674c9b (patch)
tree9eecbcba3b99106958e63d6db51e6c13eaf6d50a
parent999a2fb99bf67025e38542003af0e5022b3b5b94 (diff)
downloadegit-github-ca40854c.tar.gz
egit-github-ca40854c.tar.xz
egit-github-ca40854c.zip
Drop dependency on Apache HttpComponents (HC)
HC was used sparingly and added several additional JAR requirements that made the GitHub Java API unusable on Android due to these dependencies. A HttpURLConnection is now used instead to make all request types. Change-Id: I82e442139d3adec3d2331f279bde69320b13638d Signed-off-by: Kevin Sawicki <kevin@github.com>
-rw-r--r--org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/EncodingUtilsTest.java6
-rw-r--r--org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/GitHubClientTest.java8
-rw-r--r--org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/live/LiveTest.java14
-rw-r--r--org.eclipse.egit.github.core/META-INF/MANIFEST.MF20
-rw-r--r--org.eclipse.egit.github.core/META-INF/SOURCE-MANIFEST.MF20
-rw-r--r--org.eclipse.egit.github.core/pom-jar.xml18
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/AuthInterceptor.java61
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/EntityDeleteMethod.java53
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubClient.java616
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubRequest.java26
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubResponse.java50
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/IGitHubConstants.java2
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/OAuth2Scheme.java57
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PageIterator.java15
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PageLinks.java20
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PagedRequest.java21
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/DownloadService.java96
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/GitHubService.java4
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/Base64.java312
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/EncodingUtils.java28
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/MultiPartUtils.java93
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/UrlUtils.java101
22 files changed, 951 insertions, 690 deletions
diff --git a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/EncodingUtilsTest.java b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/EncodingUtilsTest.java
index 5f42868d..5b0b6da4 100644
--- a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/EncodingUtilsTest.java
+++ b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/EncodingUtilsTest.java
@@ -37,10 +37,10 @@ public class EncodingUtilsTest {
@Test
public void encodeDecode() {
String test = "content";
- byte[] encoded = EncodingUtils.toBase64(test.getBytes());
+ String encoded = EncodingUtils.toBase64(test.getBytes());
assertNotNull(encoded);
- assertFalse(encoded.length == 0);
- assertFalse(test.equals(new String(encoded)));
+ assertFalse(encoded.length() == 0);
+ assertFalse(test.equals(encoded));
byte[] decoded = EncodingUtils.fromBase64(new String(encoded));
assertNotNull(decoded);
assertFalse(decoded.length == 0);
diff --git a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/GitHubClientTest.java b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/GitHubClientTest.java
index 818d0903..6eae112b 100644
--- a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/GitHubClientTest.java
+++ b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/GitHubClientTest.java
@@ -34,14 +34,6 @@ public class GitHubClientTest {
}
/**
- * Create client with null host
- */
- @Test(expected = IllegalArgumentException.class)
- public void constructorNullArgument() {
- new GitHubClient((HttpHost) null);
- }
-
- /**
* Verify prefix with API v2 host
*/
@Test
diff --git a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/live/LiveTest.java b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/live/LiveTest.java
index f7927bac..c6930239 100644
--- a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/live/LiveTest.java
+++ b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/live/LiveTest.java
@@ -4,7 +4,7 @@
* 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:
* Kevin Sawicki (GitHub Inc.) - initial API and implementation
*******************************************************************************/
@@ -15,7 +15,6 @@ import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import java.net.URL;
-import org.apache.http.HttpHost;
import org.eclipse.egit.github.core.client.GitHubClient;
import org.junit.Before;
@@ -36,7 +35,7 @@ public abstract class LiveTest {
/**
* Configure client
- *
+ *
* @param client
* @return specified client
*/
@@ -50,7 +49,7 @@ public abstract class LiveTest {
/**
* Create client for url
- *
+ *
* @param url
* @return client
* @throws IOException
@@ -59,9 +58,8 @@ public abstract class LiveTest {
GitHubClient client = null;
if (url != null) {
URL parsed = new URL(url);
- HttpHost httpHost = new HttpHost(parsed.getHost(),
- parsed.getPort(), parsed.getProtocol());
- client = new GitHubClient(httpHost);
+ client = new GitHubClient(parsed.getHost(), parsed.getPort(),
+ parsed.getProtocol());
} else
client = new GitHubClient();
return configure(client);
@@ -69,7 +67,7 @@ public abstract class LiveTest {
/**
* Set up live unit test
- *
+ *
* @throws Exception
*/
@Before
diff --git a/org.eclipse.egit.github.core/META-INF/MANIFEST.MF b/org.eclipse.egit.github.core/META-INF/MANIFEST.MF
index 15c1acb1..3a54338e 100644
--- a/org.eclipse.egit.github.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.egit.github.core/META-INF/MANIFEST.MF
@@ -8,25 +8,7 @@ Bundle-Vendor: %providerName
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: com.google.gson;version="[1.6.0,2.0.0)",
com.google.gson.annotations;version="[1.6.0,2.0.0)",
- com.google.gson.reflect;version="[1.6.0,2.0.0)",
- org.apache.commons.codec.binary;version="[1.3.0,2.0.0)",
- org.apache.http;version="[4.1.0,5.0.0)",
- org.apache.http.auth;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.protocol;version="[4.1.0,5.0.0)",
- org.apache.http.client.utils;version="[4.1.0,5.0.0)",
- org.apache.http.conn;version="[4.1.0,5.0.0)",
- org.apache.http.conn.routing;version="[4.1.0,5.0.0)",
- org.apache.http.entity;version="[4.1.0,5.0.0)",
- org.apache.http.entity.mime;version="[4.1.0,5.0.0)",
- org.apache.http.entity.mime.content;version="[4.1.0,5.0.0)",
- org.apache.http.impl.auth;version="[4.1.0,5.0.0)",
- org.apache.http.impl.client;version="[4.1.0,5.0.0)",
- org.apache.http.impl.conn;version="[4.1.0,5.0.0)",
- org.apache.http.message;version="[4.1.0,5.0.0)",
- org.apache.http.protocol;version="[4.1.0,5.0.0)",
- org.apache.http.util;version="[4.1.0,5.0.0)"
+ com.google.gson.reflect;version="[1.6.0,2.0.0)"
Export-Package: org.eclipse.egit.github.core;version="1.3.0",
org.eclipse.egit.github.core.client;version="1.3.0",
org.eclipse.egit.github.core.service;version="1.3.0",
diff --git a/org.eclipse.egit.github.core/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.egit.github.core/META-INF/SOURCE-MANIFEST.MF
index ea1f6efd..9e81c482 100644
--- a/org.eclipse.egit.github.core/META-INF/SOURCE-MANIFEST.MF
+++ b/org.eclipse.egit.github.core/META-INF/SOURCE-MANIFEST.MF
@@ -7,25 +7,7 @@ Bundle-Vendor: Eclipse EGit
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: com.google.gson;version="[1.6.0,2.0.0)",
com.google.gson.annotations;version="[1.6.0,2.0.0)",
- com.google.gson.reflect;version="[1.6.0,2.0.0)",
- org.apache.commons.codec.binary;version="[1.3.0,2.0.0)",
- org.apache.http;version="[4.1.0,5.0.0)",
- org.apache.http.auth;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.protocol;version="[4.1.0,5.0.0)",
- org.apache.http.client.utils;version="[4.1.0,5.0.0)",
- org.apache.http.conn;version="[4.1.0,5.0.0)",
- org.apache.http.conn.routing;version="[4.1.0,5.0.0)",
- org.apache.http.entity;version="[4.1.0,5.0.0)",
- org.apache.http.entity.mime;version="[4.1.0,5.0.0)",
- org.apache.http.entity.mime.content;version="[4.1.0,5.0.0)",
- org.apache.http.impl.auth;version="[4.1.0,5.0.0)",
- org.apache.http.impl.client;version="[4.1.0,5.0.0)",
- org.apache.http.impl.conn;version="[4.1.0,5.0.0)",
- org.apache.http.message;version="[4.1.0,5.0.0)",
- org.apache.http.protocol;version="[4.1.0,5.0.0)",
- org.apache.http.util;version="[4.1.0,5.0.0)"
+ com.google.gson.reflect;version="[1.6.0,2.0.0)"
Export-Package: org.eclipse.egit.github.core;version="1.1.0",
org.eclipse.egit.github.core.client;version="1.1.0",
org.eclipse.egit.github.core.service;version="1.1.0",
diff --git a/org.eclipse.egit.github.core/pom-jar.xml b/org.eclipse.egit.github.core/pom-jar.xml
index 36791d40..7ff0967d 100644
--- a/org.eclipse.egit.github.core/pom-jar.xml
+++ b/org.eclipse.egit.github.core/pom-jar.xml
@@ -173,24 +173,6 @@
<dependencies>
<dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
- <version>4.1.2</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpcore</artifactId>
- <version>4.1.3</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpmime</artifactId>
- <version>4.1.2</version>
- <scope>compile</scope>
- </dependency>
- <dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>1.7.2</version>
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/AuthInterceptor.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/AuthInterceptor.java
deleted file mode 100644
index daf5cb70..00000000
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/AuthInterceptor.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/******************************************************************************
- * Copyright (c) 2011 GitHub Inc.
- * 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:
- * Kevin Sawicki (GitHub Inc.) - initial API and implementation
- *****************************************************************************/
-package org.eclipse.egit.github.core.client;
-
-import static org.apache.http.client.protocol.ClientContext.AUTH_CACHE;
-import static org.apache.http.client.protocol.ClientContext.CREDS_PROVIDER;
-import static org.apache.http.client.protocol.ClientContext.TARGET_AUTH_STATE;
-import static org.apache.http.protocol.ExecutionContext.HTTP_TARGET_HOST;
-
-import java.io.IOException;
-
-import org.apache.http.HttpException;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpRequestInterceptor;
-import org.apache.http.auth.AuthScheme;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.AuthState;
-import org.apache.http.auth.Credentials;
-import org.apache.http.client.AuthCache;
-import org.apache.http.client.CredentialsProvider;
-import org.apache.http.protocol.HttpContext;
-
-/**
- * Interceptor that sets authentication credentials
- */
-public class AuthInterceptor implements HttpRequestInterceptor {
-
- public void process(final HttpRequest request, final HttpContext context)
- throws HttpException, IOException {
- AuthState authState = (AuthState) context
- .getAttribute(TARGET_AUTH_STATE);
- if (authState == null || authState.getAuthScheme() != null)
- return;
- HttpHost targetHost = (HttpHost) context.getAttribute(HTTP_TARGET_HOST);
- if (targetHost == null)
- return;
- AuthCache cache = (AuthCache) context.getAttribute(AUTH_CACHE);
- AuthScheme authScheme = cache.get(targetHost);
- if (authScheme == null)
- return;
- CredentialsProvider provider = (CredentialsProvider) context
- .getAttribute(CREDS_PROVIDER);
- if (provider == null)
- return;
- Credentials creds = provider.getCredentials(new AuthScope(targetHost
- .getHostName(), targetHost.getPort()));
- if (creds == null)
- return;
- authState.setAuthScheme(authScheme);
- authState.setCredentials(creds);
- }
-}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/EntityDeleteMethod.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/EntityDeleteMethod.java
deleted file mode 100644
index f663602a..00000000
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/EntityDeleteMethod.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/******************************************************************************
- * Copyright (c) 2011 GitHub Inc.
- * 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:
- * Kevin Sawicki (GitHub Inc.) - initial API and implementation
- *****************************************************************************/
-package org.eclipse.egit.github.core.client;
-
-import java.net.URI;
-
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
-
-/**
- * DELETE request that supports an enclosed entity
- */
-public class EntityDeleteMethod extends HttpEntityEnclosingRequestBase {
-
- /**
- * Create DELETE
- */
- public EntityDeleteMethod() {
- super();
- }
-
- /**
- * Create DELETE
- *
- * @param uri
- */
- public EntityDeleteMethod(final URI uri) {
- super();
- setURI(uri);
- }
-
- /**
- * Create DELETE
- *
- * @param uri
- */
- public EntityDeleteMethod(final String uri) {
- super();
- setURI(URI.create(uri));
- }
-
- public String getMethod() {
- return HttpDelete.METHOD_NAME;
- }
-}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubClient.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubClient.java
index 3344340a..e2fe7a47 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubClient.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubClient.java
@@ -11,16 +11,14 @@
*******************************************************************************/
package org.eclipse.egit.github.core.client;
-import static org.apache.http.HttpStatus.SC_BAD_REQUEST;
-import static org.apache.http.HttpStatus.SC_CREATED;
-import static org.apache.http.HttpStatus.SC_FORBIDDEN;
-import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR;
-import static org.apache.http.HttpStatus.SC_NOT_FOUND;
-import static org.apache.http.HttpStatus.SC_NO_CONTENT;
-import static org.apache.http.HttpStatus.SC_OK;
-import static org.apache.http.HttpStatus.SC_UNAUTHORIZED;
-import static org.apache.http.HttpStatus.SC_UNPROCESSABLE_ENTITY;
-import static org.apache.http.client.protocol.ClientContext.AUTH_CACHE;
+import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
+import static java.net.HttpURLConnection.HTTP_CREATED;
+import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
+import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
import static org.eclipse.egit.github.core.client.IGitHubConstants.AUTH_TOKEN;
import static org.eclipse.egit.github.core.client.IGitHubConstants.CHARSET_UTF8;
import static org.eclipse.egit.github.core.client.IGitHubConstants.CONTENT_TYPE_JSON;
@@ -35,40 +33,17 @@ import static org.eclipse.egit.github.core.client.IGitHubConstants.SEGMENT_V3_AP
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
-import java.net.ProxySelector;
+import java.net.HttpURLConnection;
import java.net.URL;
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpHost;
-import org.apache.http.HttpMessage;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.StatusLine;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.Credentials;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.AuthCache;
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
-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.entity.StringEntity;
-import org.apache.http.impl.auth.BasicScheme;
-import org.apache.http.impl.client.BasicAuthCache;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
-import org.apache.http.message.BasicHeader;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.HTTP;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.util.EntityUtils;
import org.eclipse.egit.github.core.RequestError;
+import org.eclipse.egit.github.core.util.EncodingUtils;
/**
* Client class for interacting with GitHub HTTP/JSON API.
@@ -96,23 +71,76 @@ public class GitHubClient {
}
}
- private static final Header USER_AGENT = new BasicHeader(HTTP.USER_AGENT,
- "GitHubJava/1.2.0"); //$NON-NLS-1$
+ /**
+ * Content-Type header
+ */
+ protected static final String HEADER_CONTENT_TYPE = "Content-Type"; //$NON-NLS-1$
- private final HttpHost httpHost;
+ /**
+ * Accept header
+ */
+ protected static final String HEADER_ACCEPT = "Accept"; //$NON-NLS-1$
- private final HttpContext httpContext;
+ /**
+ * Authorization header
+ */
+ protected static final String HEADER_AUTHORIZATION = "Authorization"; //$NON-NLS-1$
- private final DefaultHttpClient client = new DefaultHttpClient();
+ /**
+ * User-Agent header
+ */
+ protected static final String HEADER_USER_AGENT = "User-Agent"; //$NON-NLS-1$
- private Header userAgent = USER_AGENT;
+ /**
+ * METHOD_GET
+ */
+ protected static final String METHOD_GET = "GET"; //$NON-NLS-1$
- private final Header accept = new BasicHeader(
- "Accept", "application/vnd.github.beta+json"); //$NON-NLS-1$ //$NON-NLS-2$
+ /**
+ * METHOD_PUT
+ */
+ protected static final String METHOD_PUT = "PUT"; //$NON-NLS-1$
- private final String prefix;
+ /**
+ * METHOD_POST
+ */
+ protected static final String METHOD_POST = "POST"; //$NON-NLS-1$
- private Gson gson = GsonUtils.getGson();
+ /**
+ * METHOD_DELETE
+ */
+ protected static final String METHOD_DELETE = "DELETE"; //$NON-NLS-1$
+
+ /**
+ * Default user agent request header value
+ */
+ protected static final String USER_AGENT = "GitHubJava/1.2.0"; //$NON-NLS-1$
+
+ /**
+ * 422 status code for unprocessable entity
+ */
+ protected static final int HTTP_UNPROCESSABLE_ENTITY = 422;
+
+ /**
+ * Base URI
+ */
+ protected final String baseUri;
+
+ /**
+ * Prefix to apply to base URI
+ */
+ protected final String prefix;
+
+ /**
+ * {@link Gson} instance
+ */
+ protected Gson gson = GsonUtils.getGson();
+
+ private String user;
+
+ private String credentials;
+
+ private String userAgent;
/**
* Create default client
@@ -137,38 +165,20 @@ public class GitHubClient {
* @param port
* @param scheme
*/
- public GitHubClient(String hostname, int port, String scheme) {
- this(new HttpHost(hostname, port, scheme));
- }
-
- /**
- * Create client for host configuration
- *
- * @param httpHost
- */
- public GitHubClient(HttpHost httpHost) {
- if (httpHost == null)
- throw new IllegalArgumentException("Http host cannot be null"); //$NON-NLS-1$
-
- this.httpHost = httpHost;
+ public GitHubClient(final String hostname, final int port,
+ final String scheme) {
+ final StringBuilder uri = new StringBuilder(scheme);
+ uri.append("://"); //$NON-NLS-1$
+ uri.append(hostname);
+ if (port > 0)
+ uri.append(port);
+ baseUri = uri.toString();
// Use URI prefix on non-standard host names
- String host = httpHost.getHostName();
- if (HOST_API.equals(host) || HOST_API_V2.equals(host))
+ if (HOST_API.equals(hostname) || HOST_API_V2.equals(hostname))
prefix = null;
else
prefix = SEGMENT_V3_API;
-
- // Support JVM configured proxy servers
- client.setRoutePlanner(new ProxySelectorRoutePlanner(client
- .getConnectionManager().getSchemeRegistry(), ProxySelector
- .getDefault()));
-
- // Preemptive authentication
- httpContext = new BasicHttpContext();
- AuthCache authCache = new BasicAuthCache();
- httpContext.setAttribute(AUTH_CACHE, authCache);
- client.addRequestInterceptor(new AuthInterceptor(), 0);
}
/**
@@ -190,9 +200,9 @@ public class GitHubClient {
* @param agent
* @return this client
*/
- public GitHubClient setUserAgent(String agent) {
+ public GitHubClient setUserAgent(final String agent) {
if (agent != null && agent.length() > 0)
- userAgent = new BasicHeader(HTTP.USER_AGENT, agent);
+ userAgent = agent;
else
userAgent = USER_AGENT;
return this;
@@ -204,9 +214,12 @@ public class GitHubClient {
* @param request
* @return configured request
*/
- protected <V extends HttpMessage> V configureRequest(V request) {
- request.addHeader(userAgent);
- request.addHeader(accept);
+ protected HttpURLConnection configureRequest(final HttpURLConnection request) {
+ if (credentials != null)
+ request.setRequestProperty(HEADER_AUTHORIZATION, credentials);
+ request.setRequestProperty(HEADER_USER_AGENT, userAgent);
+ request.setRequestProperty(HEADER_ACCEPT,
+ "application/vnd.github.beta+json"); //$NON-NLS-1$
return request;
}
@@ -224,60 +237,74 @@ public class GitHubClient {
}
/**
- * Create standard post method
+ * Create connection to URI
*
* @param uri
- * @return post
+ * @return connection
+ * @throws IOException
*/
- protected HttpPost createPost(final String uri) {
- return configureRequest(new HttpPost(configureUri(uri)));
+ protected HttpURLConnection createConnection(String uri) throws IOException {
+ URL url = new URL(createUri(uri));
+ return (HttpURLConnection) url.openConnection();
}
/**
- * Create standard put method
+ * Create connection to URI
*
* @param uri
- * @return post
+ * @param method
+ * @return connection
+ * @throws IOException
*/
- protected HttpPut createPut(final String uri) {
- return configureRequest(new HttpPut(configureUri(uri)));
+ protected HttpURLConnection createConnection(String uri, String method)
+ throws IOException {
+ HttpURLConnection connection = createConnection(uri);
+ connection.setRequestMethod(method);
+ return configureRequest(connection);
}
/**
- * Create get method
+ * Create a GET request connection to the URI
*
* @param uri
- * @return get method
+ * @return connection
+ * @throws IOException
*/
- protected HttpGet createGet(final String uri) {
- return configureRequest(new HttpGet(configureUri(uri)));
+ protected HttpURLConnection createGet(String uri) throws IOException {
+ return createConnection(uri, METHOD_GET);
}
/**
- * Create delete method
+ * Create a POST request connection to the URI
*
* @param uri
- * @return get method
+ * @return connection
+ * @throws IOException
*/
- protected HttpDelete createDelete(String uri) {
- return configureRequest(new HttpDelete(configureUri(uri)));
+ protected HttpURLConnection createPost(String uri) throws IOException {
+ return createConnection(uri, METHOD_POST);
}
/**
- * Update credential on HTTP client credentials provider
+ * Create a PUT request connection to the URI
*
- * @param user
- * @param password
- * @return this client
+ * @param uri
+ * @return connection
+ * @throws IOException
*/
- protected GitHubClient updateCredentials(String user, String password) {
- if (user != null && password != null)
- client.getCredentialsProvider().setCredentials(
- new AuthScope(httpHost.getHostName(), httpHost.getPort()),
- new UsernamePasswordCredentials(user, password));
- else
- client.getCredentialsProvider().clear();
- return this;
+ protected HttpURLConnection createPut(String uri) throws IOException {
+ return createConnection(uri, METHOD_PUT);
+ }
+
+ /**
+ * Create a DELETE request connection to the URI
+ *
+ * @param uri
+ * @return connection
+ * @throws IOException
+ */
+ protected HttpURLConnection createDelete(String uri) throws IOException {
+ return createConnection(uri, METHOD_DELETE);
}
/**
@@ -287,10 +314,14 @@ public class GitHubClient {
* @param password
* @return this client
*/
- public GitHubClient setCredentials(String user, String password) {
- updateCredentials(user, password);
- AuthCache authCache = (AuthCache) httpContext.getAttribute(AUTH_CACHE);
- authCache.put(httpHost, new BasicScheme());
+ public GitHubClient setCredentials(final String user, final String password) {
+ this.user = user;
+ if (user != null && user.length() > 0 && password != null
+ && password.length() > 0)
+ credentials = "Basic " //$NON-NLS-1$
+ + EncodingUtils.toBase64(user + ':' + password);
+ else
+ credentials = null;
return this;
}
@@ -301,9 +332,10 @@ public class GitHubClient {
* @return this client
*/
public GitHubClient setOAuth2Token(String token) {
- updateCredentials(AUTH_TOKEN, token);
- AuthCache authCache = (AuthCache) httpContext.getAttribute(AUTH_CACHE);
- authCache.put(httpHost, new OAuth2Scheme());
+ if (token != null && token.length() > 0)
+ credentials = AUTH_TOKEN + ' ' + token;
+ else
+ credentials = null;
return this;
}
@@ -313,27 +345,36 @@ public class GitHubClient {
* @return user or null if not authentication
*/
public String getUser() {
- Credentials credentials = client.getCredentialsProvider()
- .getCredentials(
- new AuthScope(httpHost.getHostName(), httpHost
- .getPort()));
- return credentials != null ? credentials.getUserPrincipal().getName()
- : null;
+ return user;
+ }
+
+ /**
+ * Convert object to a JSON string
+ *
+ * @param object
+ * @return JSON string
+ * @throws IOException
+ */
+ protected String toJson(Object object) throws IOException {
+ try {
+ return gson.toJson(object);
+ } catch (JsonParseException jpe) {
+ throw new IOException(jpe.getMessage());
+ }
}
/**
* Parse JSON to specified type
*
* @param <V>
- * @param response
+ * @param stream
* @param type
- * @return type
+ * @return parsed type
* @throws IOException
*/
- protected <V> V parseJson(HttpResponse response, Type type)
- throws IOException {
- InputStreamReader reader = new InputStreamReader(getStream(response),
- CHARSET_UTF8);
+ protected <V> V parseJson(InputStream stream, Type type) throws IOException {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ stream, CHARSET_UTF8));
try {
return gson.fromJson(reader, type);
} catch (JsonParseException jpe) {
@@ -348,46 +389,49 @@ public class GitHubClient {
}
/**
- * Convert object to a JSON string
+ * Does status code denote an error
*
- * @param object
- * @return JSON string
- * @throws IOException
+ * @param code
+ * @return true if error, false otherwise
*/
- private String toJson(Object object) throws IOException {
- try {
- return gson.toJson(object);
- } catch (JsonParseException jpe) {
- throw new IOException(jpe.getMessage());
+ protected boolean isError(final int code) {
+ switch (code) {
+ case HTTP_BAD_REQUEST:
+ case HTTP_UNAUTHORIZED:
+ case HTTP_FORBIDDEN:
+ case HTTP_NOT_FOUND:
+ case HTTP_UNPROCESSABLE_ENTITY:
+ case HTTP_INTERNAL_ERROR:
+ return true;
+ default:
+ return false;
}
}
/**
- * Get {@link HttpEntity} from response
+ * Does status code denote a non-error response?
*
- * @param response
- * @return non-null entity
- * @throws IOException
+ * @param code
+ * @return true if okay, false otherwise
*/
- protected HttpEntity getEntity(HttpResponse response) throws IOException {
- HttpEntity entity = response.getEntity();
- if (entity == null)
- throw new IOException("Response has no entity"); //$NON-NLS-1$
- return entity;
+ protected boolean isOk(final int code) {
+ switch (code) {
+ case HTTP_OK:
+ case HTTP_CREATED:
+ return true;
+ default:
+ return false;
+ }
}
/**
- * Get {@link InputStream} from response
+ * Is the response empty?
*
- * @param response
- * @return non-null input stream
- * @throws IOException
+ * @param code
+ * @return true if empty, false otherwise
*/
- protected InputStream getStream(HttpResponse response) throws IOException {
- InputStream stream = getEntity(response).getContent();
- if (stream == null)
- throw new IOException("Empty body"); //$NON-NLS-1$
- return stream;
+ protected boolean isEmpty(final int code) {
+ return HTTP_NO_CONTENT == code;
}
/**
@@ -397,224 +441,207 @@ public class GitHubClient {
* @return request error
* @throws IOException
*/
- protected RequestError parseError(HttpResponse response) throws IOException {
+ protected RequestError parseError(InputStream response) throws IOException {
return parseJson(response, RequestError.class);
}
/**
+ * Get body from response inputs stream
+ *
+ * @param request
+ * @param stream
+ * @return parsed body
+ * @throws IOException
+ */
+ protected Object getBody(GitHubRequest request, InputStream stream)
+ throws IOException {
+ Type type = request.getType();
+ if (type != null)
+ return parseJson(stream, type);
+ else
+ return null;
+ }
+
+ /**
* Create error exception from response and throw it
*
* @param response
+ * @param code
* @param status
* @return non-null newly created {@link IOException}
*/
- protected IOException createException(HttpResponse response,
- StatusLine status) {
- final int code = status.getStatusCode();
- switch (code) {
- case SC_BAD_REQUEST:
- case SC_UNAUTHORIZED:
- case SC_FORBIDDEN:
- case SC_NOT_FOUND:
- case SC_UNPROCESSABLE_ENTITY:
- case SC_INTERNAL_SERVER_ERROR:
- RequestError error;
+ protected IOException createException(InputStream response, int code,
+ String status) {
+ if (isError(code)) {
+ final RequestError error;
try {
error = parseError(response);
} catch (IOException e) {
return e;
}
return new RequestException(error, code);
- default:
- return new IOException(status.getReasonPhrase());
- }
+ } else
+ return new IOException(status);
}
/**
- * Is the response successful?
+ * Post to URI
*
- * @param response
- * @param status
- * @return true if okay, false otherwise
+ * @param uri
+ * @throws IOException
*/
- protected boolean isOk(HttpResponse response, StatusLine status) {
- switch (status.getStatusCode()) {
- case SC_OK:
- case SC_CREATED:
- return true;
- default:
- return false;
- }
+ public void post(String uri) throws IOException {
+ post(uri, null, null);
}
/**
- * Is the response empty?
+ * Put to URI
*
- * @param response
- * @param status
- * @return true if empty, false otherwise
+ * @param uri
+ * @throws IOException
*/
- protected boolean isEmpty(HttpResponse response, StatusLine status) {
- return SC_NO_CONTENT == status.getStatusCode();
+ public void put(String uri) throws IOException {
+ put(uri, null, null);
}
/**
- * Get status line from response
+ * Delete resource at URI. This method will throw an {@link IOException}
+ * when the response status is not a 204 (No Content).
*
- * @param response
- * @return Non-null status line
+ * @param uri
* @throws IOException
*/
- protected StatusLine getStatus(HttpResponse response) throws IOException {
- StatusLine statusLine = response.getStatusLine();
- if (statusLine == null)
- throw new IOException("Empty HTTP response status line"); //$NON-NLS-1$
- return statusLine;
+ public void delete(String uri) throws IOException {
+ delete(uri, null);
}
/**
- * Get response stream from URI. It is the responsibility of the calling
- * method to close the returned stream.
+ * Send parameters to output stream of request
*
* @param request
- * @return stream
+ * @param params
* @throws IOException
*/
- public InputStream getStream(GitHubRequest request) throws IOException {
- HttpGet method = createGet(request.generateUri());
- HttpResponse response = client.execute(httpHost, method, httpContext);
- StatusLine status = getStatus(response);
- if (isOk(response, status))
- return getStream(response);
- throw createException(response, status);
+ protected void sendParams(HttpURLConnection request, Object params)
+ throws IOException {
+ request.setDoOutput(true);
+ request.setRequestProperty(HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON
+ + "; charset=" + CHARSET_UTF8); //$NON-NLS-1$
+ byte[] data = toJson(params).getBytes(CHARSET_UTF8);
+ request.setFixedLengthStreamingMode(data.length);
+ BufferedOutputStream output = new BufferedOutputStream(
+ request.getOutputStream());
+ try {
+ output.write(data);
+ } finally {
+ output.close();
+ }
}
- /**
- * Get response from URI and bind to specified type
- *
- * @param request
- * @return response
- * @throws IOException
- */
- public GitHubResponse get(GitHubRequest request) throws IOException {
- HttpGet method = createGet(request.generateUri());
- HttpResponse response = client.execute(httpHost, method, httpContext);
- StatusLine status = getStatus(response);
- if (isOk(response, status)) {
- Object body = null;
- Type type = request.getType();
+ private <V> V sendJson(final HttpURLConnection request,
+ final Object params, final Type type) throws IOException {
+ if (params != null)
+ sendParams(request, params);
+ final int code = request.getResponseCode();
+ if (isOk(code))
if (type != null)
- body = parseJson(response, type);
+ return parseJson(getStream(request), type);
else
- EntityUtils.consume(response.getEntity());
- return new GitHubResponse(response, body);
- }
- if (isEmpty(response, status))
- return new GitHubResponse(response, null);
- throw createException(response, status);
+ return null;
+ if (isEmpty(code))
+ return null;
+ throw createException(getStream(request), code,
+ request.getResponseMessage());
}
/**
- * Send JSON using specified method
+ * Create full URI from path
*
- * @param <V>
- * @param method
- * @param params
- * @param type
- * @return resource
- * @throws IOException
+ * @param path
+ * @return uri
*/
- protected <V> V sendJson(HttpEntityEnclosingRequestBase method,
- Object params, Type type) throws IOException {
- if (params != null)
- method.setEntity(new StringEntity(toJson(params),
- CONTENT_TYPE_JSON, CHARSET_UTF8));
- HttpResponse response = client.execute(httpHost, method, httpContext);
- StatusLine status = getStatus(response);
- if (isOk(response, status)) {
- if (type != null)
- return parseJson(response, type);
- EntityUtils.consume(response.getEntity());
- return null;
- }
- if (isEmpty(response, status))
- return null;
- throw createException(response, status);
+ protected String createUri(final String path) {
+ return baseUri + configureUri(path);
}
/**
- * Post data to URI
+ * Get response stream from URI. It is the responsibility of the calling
+ * method to close the returned stream.
*
- * @param <V>
- * @param uri
- * @param params
- * @param type
- * @return response
+ * @param request
+ * @return stream
* @throws IOException
*/
- public <V> V post(String uri, Object params, Type type) throws IOException {
- return sendJson(createPost(uri), params, type);
+ public InputStream getStream(GitHubRequest request) throws IOException {
+ return getStream(createGet(request.generateUri()));
}
/**
- * Post to URI
+ * Get stream from request
*
- * @param uri
+ * @param request
+ * @return stream
* @throws IOException
*/
- public void post(String uri) throws IOException {
- post(uri, null, null);
+ protected InputStream getStream(HttpURLConnection request)
+ throws IOException {
+ if (request.getResponseCode() < HTTP_BAD_REQUEST)
+ return request.getInputStream();
+ else {
+ InputStream stream = request.getErrorStream();
+ return stream != null ? stream : request.getInputStream();
+ }
}
/**
- * Put data to URI
+ * Get response from URI and bind to specified type
*
- * @param <V>
- * @param uri
- * @param params
- * @param type
+ * @param request
* @return response
* @throws IOException
*/
- public <V> V put(String uri, Object params, Type type) throws IOException {
- return sendJson(createPut(uri), params, type);
+ public GitHubResponse get(GitHubRequest request) throws IOException {
+ HttpURLConnection httpRequest = createGet(request.generateUri());
+ final int code = httpRequest.getResponseCode();
+ if (isOk(code))
+ return new GitHubResponse(httpRequest, getBody(request,
+ getStream(httpRequest)));
+ if (isEmpty(code))
+ return new GitHubResponse(httpRequest, null);
+ throw createException(getStream(httpRequest), code,
+ httpRequest.getResponseMessage());
}
/**
- * Put to URI
+ * Post data to URI
*
+ * @param <V>
* @param uri
+ * @param params
+ * @param type
+ * @return response
* @throws IOException
*/
- public void put(String uri) throws IOException {
- put(uri, null, null);
+ public <V> V post(final String uri, final Object params, final Type type)
+ throws IOException {
+ HttpURLConnection request = createPost(uri);
+ return sendJson(request, params, type);
}
/**
- * Delete resource at URI. This method will throw an {@link IOException}
- * when the response status is not a 204 (No Content).
+ * Put data to URI
*
+ * @param <V>
* @param uri
* @param params
+ * @param type
+ * @return response
* @throws IOException
*/
- public void delete(String uri, Object params) throws IOException {
- HttpRequest method;
- if (params == null)
- method = createDelete(uri);
- else {
- EntityDeleteMethod delete = configureRequest(new EntityDeleteMethod(
- uri));
- delete.setEntity(new StringEntity(toJson(params),
- CONTENT_TYPE_JSON, CHARSET_UTF8));
- method = delete;
- }
-
- HttpResponse response = client.execute(httpHost, method, httpContext);
- StatusLine status = getStatus(response);
- if (!isEmpty(response, status))
- throw new RequestException(parseError(response),
- status.getStatusCode());
+ public <V> V put(final String uri, final Object params, final Type type)
+ throws IOException {
+ HttpURLConnection request = createPut(uri);
+ return sendJson(request, params, type);
}
/**
@@ -622,9 +649,16 @@ public class GitHubClient {
* when the response status is not a 204 (No Content).
*
* @param uri
+ * @param params
* @throws IOException
*/
- public void delete(String uri) throws IOException {
- delete(uri, null);
+ public void delete(final String uri, final Object params)
+ throws IOException {
+ HttpURLConnection request = createDelete(uri);
+ if (params != null)
+ sendParams(request, params);
+ final int code = request.getResponseCode();
+ if (!isEmpty(code))
+ throw new RequestException(parseError(getStream(request)), code);
}
}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubRequest.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubRequest.java
index c558c557..9a69cdcb 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubRequest.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubRequest.java
@@ -11,14 +11,9 @@
package org.eclipse.egit.github.core.client;
import java.lang.reflect.Type;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.utils.URLEncodedUtils;
-import org.apache.http.message.BasicNameValuePair;
+import org.eclipse.egit.github.core.util.UrlUtils;
/**
* GitHub API request class that contains the URI and parameters of the request
@@ -50,18 +45,12 @@ public class GitHubRequest {
}
/**
- * Get name value pairs for data map.
+ * Add request params to URI
*
- * @param data
- * @return name value pair array
+ * @param uri
*/
- protected List<NameValuePair> getPairs(Map<String, String> data) {
- List<NameValuePair> pairs = new LinkedList<NameValuePair>();
- if (data != null && !data.isEmpty())
- for (Entry<String, String> entry : data.entrySet())
- pairs.add(new BasicNameValuePair(entry.getKey(), entry
- .getValue()));
- return pairs;
+ protected void addParams(final StringBuilder uri) {
+ UrlUtils.addParams(getParams(), uri);
}
/**
@@ -75,8 +64,9 @@ public class GitHubRequest {
return null;
if (baseUri.indexOf('?') != -1)
return baseUri;
- String params = URLEncodedUtils.format(getPairs(getParams()), null);
- if (params != null && params.length() > 0)
+ final StringBuilder params = new StringBuilder();
+ addParams(params);
+ if (params.length() > 0)
return baseUri + '?' + params;
else
return baseUri;
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubResponse.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubResponse.java
index 8b713feb..df426edc 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubResponse.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/GitHubResponse.java
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.egit.github.core.client;
-import org.apache.http.HttpResponse;
+import java.net.HttpURLConnection;
/**
* GitHub API response class that provides the parsed response body as well as
@@ -18,9 +18,20 @@ import org.apache.http.HttpResponse;
*/
public class GitHubResponse {
- private PageLinks links;
+ /**
+ * HTTP response
+ */
+ protected final HttpURLConnection response;
- private Object body;
+ /**
+ * Response body
+ */
+ protected final Object body;
+
+ /**
+ * Links to other pages
+ */
+ protected PageLinks links;
/**
* Create response
@@ -28,18 +39,39 @@ public class GitHubResponse {
* @param response
* @param body
*/
- public GitHubResponse(HttpResponse response, Object body) {
- links = new PageLinks(response);
+ public GitHubResponse(HttpURLConnection response, Object body) {
+ this.response = response;
this.body = body;
}
/**
+ * Get header value
+ *
+ * @param name
+ * @return value
+ */
+ public String getHeader(String name) {
+ return response.getHeaderField(name);
+ }
+
+ /**
+ * Get page links
+ *
+ * @return links
+ */
+ protected PageLinks getLinks() {
+ if (links == null)
+ links = new PageLinks(this);
+ return links;
+ }
+
+ /**
* Get link uri to first page
*
* @return possibly null uri
*/
public String getFirst() {
- return links.getFirst();
+ return getLinks().getFirst();
}
/**
@@ -48,7 +80,7 @@ public class GitHubResponse {
* @return possibly null uri
*/
public String getPrevious() {
- return links.getPrev();
+ return getLinks().getPrev();
}
/**
@@ -57,7 +89,7 @@ public class GitHubResponse {
* @return possibly null uri
*/
public String getNext() {
- return links.getNext();
+ return getLinks().getNext();
}
/**
@@ -66,7 +98,7 @@ public class GitHubResponse {
* @return possibly null uri
*/
public String getLast() {
- return links.getLast();
+ return getLinks().getLast();
}
/**
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/IGitHubConstants.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/IGitHubConstants.java
index 1f313748..50bb83e2 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/IGitHubConstants.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/IGitHubConstants.java
@@ -21,6 +21,8 @@ public interface IGitHubConstants {
/** */
String CHARSET_UTF8 = "UTF-8"; //$NON-NLS-1$
/** */
+ String CHARSET_ISO_8859_1 = "ISO-8859-1"; //$NON-NLS-1$
+ /** */
String CONTENT_TYPE_JSON = "application/json"; //$NON-NLS-1$
/** */
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/OAuth2Scheme.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/OAuth2Scheme.java
deleted file mode 100644
index 47cac7b4..00000000
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/OAuth2Scheme.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/******************************************************************************
- * Copyright (c) 2011 GitHub Inc.
- * 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:
- * Kevin Sawicki (GitHub Inc.) - initial API and implementation
- *****************************************************************************/
-package org.eclipse.egit.github.core.client;
-
-import static org.apache.http.HttpHeaders.AUTHORIZATION;
-import static org.eclipse.egit.github.core.client.IGitHubConstants.SCHEME_OAUTH2;
-
-import org.apache.http.Header;
-import org.apache.http.HttpRequest;
-import org.apache.http.auth.AuthenticationException;
-import org.apache.http.auth.Credentials;
-import org.apache.http.auth.MalformedChallengeException;
-import org.apache.http.impl.auth.RFC2617Scheme;
-import org.apache.http.message.BasicHeader;
-
-/**
- * OAuth2 authorization scheme. Sets an authorization header with a value of the
- * space-separated user principal name and password from credentials.
- */
-public class OAuth2Scheme extends RFC2617Scheme {
-
- private boolean complete = false;
-
- public void processChallenge(Header header)
- throws MalformedChallengeException {
- super.processChallenge(header);
- complete = true;
- }
-
- public String getSchemeName() {
- return SCHEME_OAUTH2;
- }
-
- public boolean isConnectionBased() {
- return false;
- }
-
- public boolean isComplete() {
- return complete;
- }
-
- public Header authenticate(Credentials credentials, HttpRequest request)
- throws AuthenticationException {
- if (credentials == null)
- throw new IllegalArgumentException("Credentials cannot be null"); //$NON-NLS-1$
- return new BasicHeader(AUTHORIZATION, credentials.getUserPrincipal()
- .getName() + ' ' + credentials.getPassword());
- }
-}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PageIterator.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PageIterator.java
index 20f7a574..1a10cce9 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PageIterator.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PageIterator.java
@@ -22,9 +22,8 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.utils.URLEncodedUtils;
import org.eclipse.egit.github.core.IResourceProvider;
+import org.eclipse.egit.github.core.util.UrlUtils;
/**
* Iterator for getting paged responses. Each call to {@link #next()} will make
@@ -95,16 +94,20 @@ public class PageIterator<V> implements Iterator<Collection<V>>,
protected int parsePageNumber(String uri) {
if (uri == null || uri.length() == 0)
return -1;
+ final URI parsed;
try {
- for (NameValuePair pair : URLEncodedUtils.parse(new URI(uri), null))
- if (PARAM_PAGE.equals(pair.getName()))
- return Integer.parseInt(pair.getValue());
+ parsed = new URI(uri);
} catch (URISyntaxException e) {
return -1;
+ }
+ final String param = UrlUtils.getParam(parsed, PARAM_PAGE);
+ if (param == null || param.length() == 0)
+ return -1;
+ try {
+ return Integer.parseInt(param);
} catch (NumberFormatException nfe) {
return -1;
}
- return -1;
}
/**
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PageLinks.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PageLinks.java
index 6d9bbabd..0fa3dff1 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PageLinks.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PageLinks.java
@@ -19,9 +19,6 @@ import static org.eclipse.egit.github.core.client.IGitHubConstants.META_NEXT;
import static org.eclipse.egit.github.core.client.IGitHubConstants.META_PREV;
import static org.eclipse.egit.github.core.client.IGitHubConstants.META_REL;
-import org.apache.http.Header;
-import org.apache.http.HttpResponse;
-
/**
* Page link class to be used to determine the links to other pages of request
* responses encoded in the current response. These will be present if the
@@ -43,10 +40,10 @@ public class PageLinks {
*
* @param response
*/
- public PageLinks(HttpResponse response) {
- Header[] linkHeaders = response.getHeaders(HEADER_LINK);
- if (linkHeaders.length > 0) {
- String[] links = linkHeaders[0].getValue().split(DELIM_LINKS);
+ public PageLinks(GitHubResponse response) {
+ String linkHeader = response.getHeader(HEADER_LINK);
+ if (linkHeader != null) {
+ String[] links = linkHeader.split(DELIM_LINKS);
for (String link : links) {
String[] segments = link.split(DELIM_LINK_PARAM);
if (segments.length < 2)
@@ -77,13 +74,8 @@ public class PageLinks {
}
}
} else {
- Header[] nextHeaders = response.getHeaders(HEADER_NEXT);
- if (nextHeaders.length > 0)
- next = nextHeaders[0].getValue();
-
- Header[] lastHeaders = response.getHeaders(HEADER_LAST);
- if (lastHeaders.length > 0)
- last = lastHeaders[0].getValue();
+ next = response.getHeader(HEADER_NEXT);
+ last = response.getHeader(HEADER_LAST);
}
}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PagedRequest.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PagedRequest.java
index 15238b1b..4ebe2022 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PagedRequest.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/client/PagedRequest.java
@@ -13,11 +13,7 @@ package org.eclipse.egit.github.core.client;
import static org.eclipse.egit.github.core.client.IGitHubConstants.PARAM_PAGE;
import static org.eclipse.egit.github.core.client.IGitHubConstants.PARAM_PER_PAGE;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.http.NameValuePair;
-import org.apache.http.message.BasicNameValuePair;
+import org.eclipse.egit.github.core.util.UrlUtils;
/**
* Paged request class that contains the initial page size and page number of
@@ -69,17 +65,14 @@ public class PagedRequest<V> extends GitHubRequest {
}
@Override
- protected List<NameValuePair> getPairs(Map<String, String> data) {
- List<NameValuePair> pairs = super.getPairs(data);
- int size = getPageSize();
+ protected void addParams(final StringBuilder uri) {
+ super.addParams(uri);
+ final int size = getPageSize();
if (size > 0)
- pairs.add(new BasicNameValuePair(PARAM_PER_PAGE, Integer
- .toString(size)));
- int number = getPage();
+ UrlUtils.addParam(PARAM_PER_PAGE, Integer.toString(size), uri);
+ final int number = getPage();
if (number > 0)
- pairs.add(new BasicNameValuePair(PARAM_PAGE, Integer
- .toString(number)));
- return pairs;
+ UrlUtils.addParam(PARAM_PAGE, Integer.toString(number), uri);
}
/**
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/DownloadService.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/DownloadService.java
index 1a4caa0a..97c44421 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/DownloadService.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/DownloadService.java
@@ -10,6 +10,7 @@
*****************************************************************************/
package org.eclipse.egit.github.core.service;
+import static java.net.HttpURLConnection.HTTP_CREATED;
import static org.eclipse.egit.github.core.client.IGitHubConstants.SEGMENT_DOWNLOADS;
import static org.eclipse.egit.github.core.client.IGitHubConstants.SEGMENT_REPOS;
import static org.eclipse.egit.github.core.client.PagedRequest.PAGE_FIRST;
@@ -21,19 +22,11 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.ProxySelector;
+import java.net.HttpURLConnection;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
-import org.apache.http.HttpHeaders;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.mime.MultipartEntity;
-import org.apache.http.entity.mime.content.InputStreamBody;
-import org.apache.http.entity.mime.content.StringBody;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
import org.eclipse.egit.github.core.Download;
import org.eclipse.egit.github.core.DownloadResource;
import org.eclipse.egit.github.core.IRepositoryIdProvider;
@@ -41,6 +34,7 @@ import org.eclipse.egit.github.core.client.GitHubClient;
import org.eclipse.egit.github.core.client.GitHubRequest;
import org.eclipse.egit.github.core.client.PageIterator;
import org.eclipse.egit.github.core.client.PagedRequest;
+import org.eclipse.egit.github.core.util.MultiPartUtils;
/**
* Service for accessing, creating, and deleting repositories downloads.
@@ -90,23 +84,10 @@ public class DownloadService extends GitHubService {
*/
public static final String UPLOAD_FILE = "file"; //$NON-NLS-1$
- private static class SizedInputStreamBody extends InputStreamBody {
-
- private final long size;
-
- /**
- * @param in
- * @param size
- */
- public SizedInputStreamBody(InputStream in, long size) {
- super(in, null);
- this.size = size;
- }
-
- public long getContentLength() {
- return size;
- }
- }
+ /**
+ * UPLOAD_CONTENT_TYPE
+ */
+ public static final String UPLOAD_CONTENT_TYPE = "Content-Type"; //$NON-NLS-1$
/**
* Create download service
@@ -251,19 +232,6 @@ public class DownloadService extends GitHubService {
}
/**
- * Create client to use to upload a resource to
- *
- * @return non-null http client
- */
- protected HttpClient createDownloadClient() {
- DefaultHttpClient client = new DefaultHttpClient();
- client.setRoutePlanner(new ProxySelectorRoutePlanner(client
- .getConnectionManager().getSchemeRegistry(), ProxySelector
- .getDefault()));
- return client;
- }
-
- /**
* Upload a resource to be available as the download described by the given
* resource.
*
@@ -281,28 +249,21 @@ public class DownloadService extends GitHubService {
throw new IllegalArgumentException(
"Content input stream cannot be null"); //$NON-NLS-1$
- HttpClient client = createDownloadClient();
-
- HttpPost post = new HttpPost(resource.getS3Url());
- MultipartEntity entity = new MultipartEntity();
- entity.addPart(UPLOAD_KEY, new StringBody(resource.getPath()));
- entity.addPart(UPLOAD_ACL, new StringBody(resource.getAcl()));
- entity.addPart(UPLOAD_SUCCESS_ACTION_STATUS,
- new StringBody(Integer.toString(HttpStatus.SC_CREATED)));
- entity.addPart(UPLOAD_FILENAME, new StringBody(resource.getName()));
- entity.addPart(UPLOAD_AWS_ACCESS_KEY_ID,
- new StringBody(resource.getAccesskeyid()));
- entity.addPart(UPLOAD_POLICY, new StringBody(resource.getPolicy()));
- entity.addPart(UPLOAD_SIGNATURE,
- new StringBody(resource.getSignature()));
- entity.addPart(HttpHeaders.CONTENT_TYPE,
- new StringBody(resource.getMimeType()));
- entity.addPart(UPLOAD_FILE, new SizedInputStreamBody(content, size));
- post.setEntity(entity);
-
- HttpResponse response = client.execute(post);
- int status = response.getStatusLine().getStatusCode();
- if (status != HttpStatus.SC_CREATED)
+ Map<String, Object> parts = new LinkedHashMap<String, Object>();
+ parts.put(UPLOAD_KEY, resource.getPath());
+ parts.put(UPLOAD_ACL, resource.getAcl());
+ parts.put(UPLOAD_SUCCESS_ACTION_STATUS, Integer.toString(HTTP_CREATED));
+ parts.put(UPLOAD_FILENAME, resource.getName());
+ parts.put(UPLOAD_AWS_ACCESS_KEY_ID, resource.getAccesskeyid());
+ parts.put(UPLOAD_POLICY, resource.getPolicy());
+ parts.put(UPLOAD_SIGNATURE, resource.getSignature());
+ parts.put(UPLOAD_CONTENT_TYPE, resource.getMimeType());
+ parts.put(UPLOAD_FILE, content);
+
+ HttpURLConnection connection = MultiPartUtils.post(resource.getS3Url(),
+ parts);
+ int status = connection.getResponseCode();
+ if (status != HTTP_CREATED)
throw new IOException("Unexpected response status of " + status); //$NON-NLS-1$
}
@@ -320,13 +281,15 @@ public class DownloadService extends GitHubService {
* raw content of the download
* @param size
* size of content in the input stream
+ * @return created resource
* @throws IOException
*/
- public void createDownload(IRepositoryIdProvider repository,
+ public DownloadResource createDownload(IRepositoryIdProvider repository,
Download download, InputStream content, long size)
throws IOException {
DownloadResource resource = createResource(repository, download);
uploadResource(resource, content, size);
+ return resource;
}
/**
@@ -338,14 +301,15 @@ public class DownloadService extends GitHubService {
* metadata about the download
* @param file
* must be non-null
+ * @return created resource
* @throws IOException
*/
- public void createDownload(IRepositoryIdProvider repository,
+ public DownloadResource createDownload(IRepositoryIdProvider repository,
Download download, File file) throws IOException {
if (file == null)
throw new IllegalArgumentException("File cannot be null"); //$NON-NLS-1$
- createDownload(repository, download, new FileInputStream(file),
+ return createDownload(repository, download, new FileInputStream(file),
file.length());
}
}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/GitHubService.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/GitHubService.java
index fd53c2be..78b13e91 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/GitHubService.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/GitHubService.java
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.egit.github.core.service;
-import static org.apache.http.HttpStatus.SC_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static org.eclipse.egit.github.core.client.PagedRequest.PAGE_FIRST;
import static org.eclipse.egit.github.core.client.PagedRequest.PAGE_SIZE;
@@ -152,7 +152,7 @@ public abstract class GitHubService {
client.get(createRequest().setUri(uri));
return true;
} catch (RequestException e) {
- if (e.getStatus() == SC_NOT_FOUND)
+ if (e.getStatus() == HTTP_NOT_FOUND)
return false;
throw e;
}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/Base64.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/Base64.java
new file mode 100644
index 00000000..587d52c9
--- /dev/null
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/Base64.java
@@ -0,0 +1,312 @@
+//
+// NOTE: The following source code is heavily derived from the
+// iHarder.net public domain Base64 library. See the original at
+// http://iharder.sourceforge.net/current/java/base64/
+//
+
+package org.eclipse.egit.github.core.util;
+
+import static org.eclipse.egit.github.core.client.IGitHubConstants.CHARSET_UTF8;
+
+import java.io.UnsupportedEncodingException;
+import java.text.MessageFormat;
+import java.util.Arrays;
+
+/**
+ * Encodes and decodes to and from Base64 notation.
+ * <p>
+ * I am placing this code in the Public Domain. Do with it as you will. This
+ * software comes with no guarantees or warranties but with plenty of
+ * well-wishing instead! Please visit <a
+ * href="http://iharder.net/base64">http://iharder.net/base64</a> periodically
+ * to check for updates or to contribute improvements.
+ * </p>
+ *
+ * @author Robert Harder
+ * @author rob@iharder.net
+ * @version 2.1, stripped to minimum feature set used by JGit.
+ */
+class Base64 {
+ /** The equals sign (=) as a byte. */
+ private final static byte EQUALS_SIGN = (byte) '=';
+
+ /** Indicates equals sign in encoding. */
+ private final static byte EQUALS_SIGN_DEC = -1;
+
+ /** Indicates white space in encoding. */
+ private final static byte WHITE_SPACE_DEC = -2;
+
+ /** Indicates an invalid byte during decoding. */
+ private final static byte INVALID_DEC = -3;
+
+ /** The 64 valid Base64 values. */
+ private final static byte[] ENC;
+
+ /**
+ * Translates a Base64 value to either its 6-bit reconstruction value or a
+ * negative number indicating some other meaning. The table is only 7 bits
+ * wide, as the 8th bit is discarded during decoding.
+ */
+ private final static byte[] DEC;
+
+ static {
+ try {
+ ENC = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" //
+ + "abcdefghijklmnopqrstuvwxyz" //
+ + "0123456789" //
+ + "+/" //
+ ).getBytes(CHARSET_UTF8);
+ } catch (UnsupportedEncodingException uee) {
+ throw new RuntimeException(uee.getMessage(), uee);
+ }
+
+ DEC = new byte[128];
+ Arrays.fill(DEC, INVALID_DEC);
+
+ for (int i = 0; i < 64; i++)
+ DEC[ENC[i]] = (byte) i;
+ DEC[EQUALS_SIGN] = EQUALS_SIGN_DEC;
+
+ DEC['\t'] = WHITE_SPACE_DEC;
+ DEC['\n'] = WHITE_SPACE_DEC;
+ DEC['\r'] = WHITE_SPACE_DEC;
+ DEC[' '] = WHITE_SPACE_DEC;
+ }
+
+ /** Defeats instantiation. */
+ private Base64() {
+ // Suppress empty block warning.
+ }
+
+ /**
+ * Encodes up to three bytes of the array <var>source</var> and writes the
+ * resulting four Base64 bytes to <var>destination</var>. The source and
+ * destination arrays can be manipulated anywhere along their length by
+ * specifying <var>srcOffset</var> and <var>destOffset</var>. This method
+ * does not check to make sure your arrays are large enough to accommodate
+ * <var>srcOffset</var> + 3 for the <var>source</var> array or
+ * <var>destOffset</var> + 4 for the <var>destination</var> array. The
+ * actual number of significant bytes in your array is given by
+ * <var>numSigBytes</var>.
+ *
+ * @param source
+ * the array to convert
+ * @param srcOffset
+ * the index where conversion begins
+ * @param numSigBytes
+ * the number of significant bytes in your array
+ * @param destination
+ * the array to hold the conversion
+ * @param destOffset
+ * the index where output will be put
+ */
+ private static void encode3to4(byte[] source, int srcOffset,
+ int numSigBytes, byte[] destination, int destOffset) {
+ // We have to shift left 24 in order to flush out the 1's that appear
+ // when Java treats a value as negative that is cast from a byte.
+
+ int inBuff = 0;
+ switch (numSigBytes) {
+ case 3:
+ inBuff |= (source[srcOffset + 2] << 24) >>> 24;
+ //$FALL-THROUGH$
+
+ case 2:
+ inBuff |= (source[srcOffset + 1] << 24) >>> 16;
+ //$FALL-THROUGH$
+
+ case 1:
+ inBuff |= (source[srcOffset] << 24) >>> 8;
+ }
+
+ switch (numSigBytes) {
+ case 3:
+ destination[destOffset] = ENC[(inBuff >>> 18)];
+ destination[destOffset + 1] = ENC[(inBuff >>> 12) & 0x3f];
+ destination[destOffset + 2] = ENC[(inBuff >>> 6) & 0x3f];
+ destination[destOffset + 3] = ENC[(inBuff) & 0x3f];
+ break;
+
+ case 2:
+ destination[destOffset] = ENC[(inBuff >>> 18)];
+ destination[destOffset + 1] = ENC[(inBuff >>> 12) & 0x3f];
+ destination[destOffset + 2] = ENC[(inBuff >>> 6) & 0x3f];
+ destination[destOffset + 3] = EQUALS_SIGN;
+ break;
+
+ case 1:
+ destination[destOffset] = ENC[(inBuff >>> 18)];
+ destination[destOffset + 1] = ENC[(inBuff >>> 12) & 0x3f];
+ destination[destOffset + 2] = EQUALS_SIGN;
+ destination[destOffset + 3] = EQUALS_SIGN;
+ break;
+ }
+ }
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ *
+ * @param source
+ * The data to convert
+ * @return encoded base64 representation of source.
+ */
+ public static String encodeBytes(byte[] source) {
+ return encodeBytes(source, 0, source.length);
+ }
+
+ /**
+ * Encodes a byte array into Base64 notation.
+ *
+ * @param source
+ * The data to convert
+ * @param off
+ * Offset in array where conversion should begin
+ * @param len
+ * Length of data to convert
+ * @return encoded base64 representation of source.
+ */
+ public static String encodeBytes(byte[] source, int off, int len) {
+ final int len43 = len * 4 / 3;
+
+ byte[] outBuff = new byte[len43 + ((len % 3) > 0 ? 4 : 0)];
+ int d = 0;
+ int e = 0;
+ int len2 = len - 2;
+
+ for (; d < len2; d += 3, e += 4)
+ encode3to4(source, d + off, 3, outBuff, e);
+
+ if (d < len) {
+ encode3to4(source, d + off, len - d, outBuff, e);
+ e += 4;
+ }
+
+ try {
+ return new String(outBuff, 0, e, CHARSET_UTF8);
+ } catch (UnsupportedEncodingException uue) {
+ return new String(outBuff, 0, e);
+ }
+ }
+
+ /**
+ * Decodes four bytes from array <var>source</var> and writes the resulting
+ * bytes (up to three of them) to <var>destination</var>. The source and
+ * destination arrays can be manipulated anywhere along their length by
+ * specifying <var>srcOffset</var> and <var>destOffset</var>. This method
+ * does not check to make sure your arrays are large enough to accommodate
+ * <var>srcOffset</var> + 4 for the <var>source</var> array or
+ * <var>destOffset</var> + 3 for the <var>destination</var> array. This
+ * method returns the actual number of bytes that were converted from the
+ * Base64 encoding.
+ *
+ * @param source
+ * the array to convert
+ * @param srcOffset
+ * the index where conversion begins
+ * @param destination
+ * the array to hold the conversion
+ * @param destOffset
+ * the index where output will be put
+ * @return the number of decoded bytes converted
+ */
+ private static int decode4to3(byte[] source, int srcOffset,
+ byte[] destination, int destOffset) {
+ // Example: Dk==
+ if (source[srcOffset + 2] == EQUALS_SIGN) {
+ int outBuff = ((DEC[source[srcOffset]] & 0xFF) << 18)
+ | ((DEC[source[srcOffset + 1]] & 0xFF) << 12);
+ destination[destOffset] = (byte) (outBuff >>> 16);
+ return 1;
+ }
+
+ // Example: DkL=
+ else if (source[srcOffset + 3] == EQUALS_SIGN) {
+ int outBuff = ((DEC[source[srcOffset]] & 0xFF) << 18)
+ | ((DEC[source[srcOffset + 1]] & 0xFF) << 12)
+ | ((DEC[source[srcOffset + 2]] & 0xFF) << 6);
+ destination[destOffset] = (byte) (outBuff >>> 16);
+ destination[destOffset + 1] = (byte) (outBuff >>> 8);
+ return 2;
+ }
+
+ // Example: DkLE
+ else {
+ int outBuff = ((DEC[source[srcOffset]] & 0xFF) << 18)
+ | ((DEC[source[srcOffset + 1]] & 0xFF) << 12)
+ | ((DEC[source[srcOffset + 2]] & 0xFF) << 6)
+ | ((DEC[source[srcOffset + 3]] & 0xFF));
+
+ destination[destOffset] = (byte) (outBuff >> 16);
+ destination[destOffset + 1] = (byte) (outBuff >> 8);
+ destination[destOffset + 2] = (byte) (outBuff);
+
+ return 3;
+ }
+ }
+
+ /**
+ * Low-level decoding ASCII characters from a byte array.
+ *
+ * @param source
+ * The Base64 encoded data
+ * @param off
+ * The offset of where to begin decoding
+ * @param len
+ * The length of characters to decode
+ * @return decoded data
+ * @throws IllegalArgumentException
+ * the input is not a valid Base64 sequence.
+ */
+ public static byte[] decode(byte[] source, int off, int len) {
+ byte[] outBuff = new byte[len * 3 / 4]; // Upper limit on size of output
+ int outBuffPosn = 0;
+
+ byte[] b4 = new byte[4];
+ int b4Posn = 0;
+
+ for (int i = off; i < off + len; i++) {
+ byte sbiCrop = (byte) (source[i] & 0x7f);
+ byte sbiDecode = DEC[sbiCrop];
+
+ if (EQUALS_SIGN_DEC <= sbiDecode) {
+ b4[b4Posn++] = sbiCrop;
+ if (b4Posn > 3) {
+ outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
+ b4Posn = 0;
+
+ // If that was the equals sign, break out of 'for' loop
+ if (sbiCrop == EQUALS_SIGN)
+ break;
+ }
+
+ } else if (sbiDecode != WHITE_SPACE_DEC)
+ throw new IllegalArgumentException(MessageFormat.format(
+ "Bad Base64 input character at {0} : {1} (decimal)", i,
+ source[i] & 0xff));
+ }
+
+ if (outBuff.length == outBuffPosn)
+ return outBuff;
+
+ byte[] out = new byte[outBuffPosn];
+ System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
+ return out;
+ }
+
+ /**
+ * Decodes data from Base64 notation.
+ *
+ * @param s
+ * the string to decode
+ * @return the decoded data
+ */
+ public static byte[] decode(String s) {
+ byte[] bytes;
+ try {
+ bytes = s.getBytes(CHARSET_UTF8);
+ } catch (UnsupportedEncodingException uee) {
+ bytes = s.getBytes();
+ }
+ return decode(bytes, 0, bytes.length);
+ }
+}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/EncodingUtils.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/EncodingUtils.java
index 6f430977..21c08597 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/EncodingUtils.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/EncodingUtils.java
@@ -14,8 +14,6 @@ import static org.eclipse.egit.github.core.client.IGitHubConstants.CHARSET_UTF8;
import java.io.UnsupportedEncodingException;
-import org.apache.commons.codec.binary.Base64;
-
/**
* Encoding utilities
*/
@@ -28,11 +26,7 @@ public abstract class EncodingUtils {
* @return byte array
*/
public static final byte[] fromBase64(final String content) {
- try {
- return Base64.decodeBase64(content.getBytes(CHARSET_UTF8));
- } catch (UnsupportedEncodingException e) {
- return Base64.decodeBase64(content.getBytes());
- }
+ return Base64.decode(content);
}
/**
@@ -41,7 +35,23 @@ public abstract class EncodingUtils {
* @param content
* @return byte array
*/
- public static final byte[] toBase64(final byte[] content) {
- return Base64.encodeBase64(content);
+ public static final String toBase64(final byte[] content) {
+ return Base64.encodeBytes(content);
+ }
+
+ /**
+ * Base64 encode given byte array
+ *
+ * @param content
+ * @return byte array
+ */
+ public static final String toBase64(final String content) {
+ byte[] bytes;
+ try {
+ bytes = content.getBytes(CHARSET_UTF8);
+ } catch (UnsupportedEncodingException e) {
+ bytes = content.getBytes();
+ }
+ return toBase64(bytes);
}
}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/MultiPartUtils.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/MultiPartUtils.java
new file mode 100644
index 00000000..875c6e09
--- /dev/null
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/MultiPartUtils.java
@@ -0,0 +1,93 @@
+/******************************************************************************
+ * Copyright (c) 2011 GitHub Inc.
+ * 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:
+ * Kevin Sawicki (GitHub Inc.) - initial API and implementation
+ *****************************************************************************/
+package org.eclipse.egit.github.core.util;
+
+import static org.eclipse.egit.github.core.client.IGitHubConstants.CHARSET_UTF8;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Utilities for writing multiple HTTP requests
+ */
+public class MultiPartUtils {
+
+ /**
+ * Post parts to URL
+ *
+ * @param url
+ * @param parts
+ * @return connection that was posted to
+ * @throws IOException
+ */
+ public static HttpURLConnection post(String url, Map<String, Object> parts)
+ throws IOException {
+ HttpURLConnection post = (HttpURLConnection) new URL(url)
+ .openConnection();
+ post.setRequestMethod("POST"); //$NON-NLS-1$
+ return post(post, parts);
+ }
+
+ /**
+ * Post parts to connection
+ *
+ * @param post
+ * @param parts
+ * @return connection that was posted to
+ * @throws IOException
+ */
+ public static HttpURLConnection post(HttpURLConnection post,
+ Map<String, Object> parts) throws IOException {
+ String boundary = "00content0boundary00"; //$NON-NLS-1$
+ post.setDoOutput(true);
+ post.setRequestProperty("Content-Type", //$NON-NLS-1$
+ "multipart/form-data; boundary=" + boundary); //$NON-NLS-1$
+ BufferedOutputStream output = new BufferedOutputStream(
+ post.getOutputStream());
+ byte[] buffer = new byte[8192];
+ byte[] boundarySeparator = ("--" + boundary + "\r\n") //$NON-NLS-1$ //$NON-NLS-2$
+ .getBytes(CHARSET_UTF8);
+ byte[] newline = "\r\n".getBytes(CHARSET_UTF8); //$NON-NLS-1$
+ try {
+ for (Entry<String, Object> part : parts.entrySet()) {
+ output.write(boundarySeparator);
+ StringBuilder partBuffer = new StringBuilder(
+ "Content-Disposition: "); //$NON-NLS-1$
+ partBuffer.append("form-data; name=\""); //$NON-NLS-1$
+ partBuffer.append(part.getKey());
+ partBuffer.append('"');
+ output.write(partBuffer.toString().getBytes(CHARSET_UTF8));
+ output.write(newline);
+ output.write(newline);
+ final Object value = part.getValue();
+ if (value instanceof InputStream) {
+ InputStream input = (InputStream) value;
+ int read;
+ while ((read = input.read(buffer)) != -1)
+ output.write(buffer, 0, read);
+ input.close();
+ } else
+ output.write(part.getValue().toString()
+ .getBytes(CHARSET_UTF8));
+ output.write(newline);
+ }
+ output.write(("--" + boundary + "--\r\n").getBytes(CHARSET_UTF8)); //$NON-NLS-1$ //$NON-NLS-2$
+ } finally {
+ output.close();
+ }
+ return post;
+ }
+}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/UrlUtils.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/UrlUtils.java
index 62e2f9e0..4b24de92 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/UrlUtils.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/util/UrlUtils.java
@@ -10,13 +10,17 @@
*****************************************************************************/
package org.eclipse.egit.github.core.util;
+import static org.eclipse.egit.github.core.client.IGitHubConstants.CHARSET_ISO_8859_1;
import static org.eclipse.egit.github.core.client.IGitHubConstants.HOST_DEFAULT;
import static org.eclipse.egit.github.core.client.IGitHubConstants.SUFFIX_GIT;
import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLDecoder;
import java.net.URLEncoder;
+import java.util.Map;
+import java.util.Map.Entry;
-import org.apache.http.protocol.HTTP;
import org.eclipse.egit.github.core.IRepositoryIdProvider;
/**
@@ -25,20 +29,6 @@ import org.eclipse.egit.github.core.IRepositoryIdProvider;
public abstract class UrlUtils {
/**
- * Encode given url
- *
- * @param url
- * @return encoded url
- */
- public static String encode(String url) {
- try {
- return URLEncoder.encode(url, HTTP.DEFAULT_CONTENT_CHARSET);
- } catch (UnsupportedEncodingException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
* Create SSH URL used for repository remote configs
*
* @param repository
@@ -108,4 +98,85 @@ public abstract class UrlUtils {
IRepositoryIdProvider repository, String host) {
return "git://" + host + "/" + repository.generateId() + SUFFIX_GIT; //$NON-NLS-1$ //$NON-NLS-2$
}
+
+ /**
+ * URL-encode value using 'ISO-8859-1' character set
+ *
+ * @param value
+ * @return encoded value
+ */
+ public static String encode(final String value) {
+ try {
+ return URLEncoder.encode(value, CHARSET_ISO_8859_1);
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * URL-decode value using 'ISO-8859-1' character set
+ *
+ * @param value
+ * @return encoded value
+ */
+ public static String decode(final String value) {
+ try {
+ return URLDecoder.decode(value, CHARSET_ISO_8859_1);
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Add encoded parameter to URI
+ *
+ * @param name
+ * @param value
+ * @param uri
+ */
+ public static void addParam(final String name, final String value,
+ final StringBuilder uri) {
+ if (uri.length() > 0)
+ uri.append('&');
+ uri.append(encode(name)).append('=');
+ if (value != null)
+ uri.append(encode(value));
+ }
+
+ /**
+ * Add request parameters to URI
+ *
+ * @param params
+ * @param uri
+ */
+ public static void addParams(final Map<String, String> params,
+ final StringBuilder uri) {
+ if (params == null || params.isEmpty())
+ return;
+ for (Entry<String, String> param : params.entrySet())
+ addParam(param.getKey(), param.getValue(), uri);
+ }
+
+ /**
+ * Get parameter value with name
+ *
+ * @param uri
+ * @param name
+ * @return value or null if not found in URI query
+ */
+ public static String getParam(final URI uri, final String name) {
+ final String query = uri.getRawQuery();
+ if (query == null || query.length() == 0)
+ return null;
+ final String[] params = query.split("&"); //$NON-NLS-1$
+ for (String param : params) {
+ final String[] parts = param.split("="); //$NON-NLS-1$
+ if (parts.length != 2)
+ continue;
+ if (!name.equals(parts[0]))
+ continue;
+ return decode(parts[1]);
+ }
+ return null;
+ }
}

Back to the top