Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/index/AsyncFetcher.java')
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/index/AsyncFetcher.java283
1 files changed, 283 insertions, 0 deletions
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/index/AsyncFetcher.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/index/AsyncFetcher.java
new file mode 100644
index 00000000..458df72d
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/index/AsyncFetcher.java
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.internal.index;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.net.HttpURLConnection;
+
+import com.ning.http.client.AsyncHandler;
+import com.ning.http.client.AsyncHttpClient;
+import com.ning.http.client.AsyncHttpClientConfig;
+import com.ning.http.client.HttpResponseBodyPart;
+import com.ning.http.client.HttpResponseHeaders;
+import com.ning.http.client.HttpResponseStatus;
+import com.ning.http.client.ProxyServer;
+import com.ning.http.client.Realm;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.osgi.util.NLS;
+
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.io.RawInputStreamFacade;
+
+import org.apache.maven.index.updater.AbstractResourceFetcher;
+import org.apache.maven.wagon.authentication.AuthenticationInfo;
+import org.apache.maven.wagon.proxy.ProxyInfo;
+import org.apache.maven.wagon.proxy.ProxyUtils;
+import org.apache.maven.wagon.repository.Repository;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.internal.Messages;
+
+
+/**
+ * A resource fetcher using Async HTTP Client.
+ *
+ * @author Benjamin Bentmann
+ */
+class AsyncFetcher extends AbstractResourceFetcher {
+
+ private final AuthenticationInfo authInfo;
+
+ private final ProxyInfo proxyInfo;
+
+ final IProgressMonitor monitor;
+
+ private AsyncHttpClient httpClient;
+
+ private Realm authRealm;
+
+ private ProxyServer proxyServer;
+
+ private String baseUrl;
+
+ public AsyncFetcher(final AuthenticationInfo authInfo, final ProxyInfo proxyInfo, final IProgressMonitor monitor) {
+ this.authInfo = authInfo;
+ this.proxyInfo = proxyInfo;
+ this.monitor = (monitor != null) ? monitor : new NullProgressMonitor();
+ }
+
+ private static Realm toRealm(AuthenticationInfo authInfo) {
+ Realm realm = null;
+
+ if(authInfo != null && authInfo.getUserName() != null && authInfo.getUserName().length() > 0) {
+ realm = new Realm.RealmBuilder().setPrincipal(authInfo.getUserName()).setPassword(authInfo.getPassword())
+ .setUsePreemptiveAuth(false).build();
+ }
+
+ return realm;
+ }
+
+ private static ProxyServer toProxyServer(ProxyInfo proxyInfo) {
+ ProxyServer proxyServer = null;
+
+ if(proxyInfo != null) {
+ ProxyServer.Protocol protocol = "https".equalsIgnoreCase(proxyInfo.getType()) ? ProxyServer.Protocol.HTTPS //$NON-NLS-1$
+ : ProxyServer.Protocol.HTTP;
+ proxyServer = new ProxyServer(protocol, proxyInfo.getHost(), proxyInfo.getPort(), proxyInfo.getUserName(),
+ proxyInfo.getPassword());
+ }
+
+ return proxyServer;
+ }
+
+ private ProxyServer getProxyServer(ProxyInfo proxyInfo, String url) {
+ if(proxyInfo != null) {
+ Repository repo = new Repository("id", url); //$NON-NLS-1$
+ if(!ProxyUtils.validateNonProxyHosts(proxyInfo, repo.getHost())) {
+ return toProxyServer(proxyInfo);
+ }
+ }
+ return null;
+ }
+
+ public void connect(String id, String url) {
+ AsyncHttpClientConfig.Builder configBuilder = new AsyncHttpClientConfig.Builder();
+ configBuilder.setUserAgent("M2Eclipse/" + MavenPlugin.getQualifiedVersion()); //$NON-NLS-1$
+ configBuilder.setConnectionTimeoutInMs(15 * 1000);
+ configBuilder.setRequestTimeoutInMs(60 * 1000);
+ configBuilder.setCompressionEnabled(true);
+ configBuilder.setFollowRedirects(true);
+
+ httpClient = new AsyncHttpClient(configBuilder.build());
+
+ baseUrl = url.endsWith("/") ? url : (url + '/'); //$NON-NLS-1$
+ authRealm = toRealm(authInfo);
+ proxyServer = getProxyServer(proxyInfo, url);
+ }
+
+ public void disconnect() {
+ authRealm = null;
+ proxyServer = null;
+ baseUrl = null;
+ if(httpClient != null) {
+ httpClient.close();
+ }
+ httpClient = null;
+ }
+
+ @SuppressWarnings("deprecation")
+ public void retrieve(String name, File targetFile) throws IOException, FileNotFoundException {
+ InputStream is = retrieve(name);
+ try {
+ FileUtils.copyStreamToFile(new RawInputStreamFacade(is), targetFile);
+ } finally {
+ IOUtil.close(is);
+ }
+ }
+
+ public InputStream retrieve(String name) throws IOException, FileNotFoundException {
+ String url = buildUrl(baseUrl, name);
+
+ monitor.subTask(NLS.bind(Messages.AsyncFetcher_task_fetching, url));
+
+ PipedErrorInputStream pis = new PipedErrorInputStream();
+
+ httpClient.prepareGet(url).setRealm(authRealm).setProxyServer(proxyServer).execute(new RequestHandler(url, pis));
+
+ return pis;
+ }
+
+ private static String buildUrl(String baseUrl, String resourceName) {
+ String url = baseUrl;
+
+ if(resourceName.startsWith("/")) { //$NON-NLS-1$
+ url += resourceName.substring(1);
+ } else {
+ url += resourceName;
+ }
+
+ return url;
+ }
+
+ static final class PipedErrorInputStream extends PipedInputStream {
+
+ private volatile Throwable error;
+
+ public PipedErrorInputStream() {
+ buffer = new byte[1024 * 128];
+ }
+
+ public void setError(Throwable t) {
+ if(error == null) {
+ error = t;
+ }
+ }
+
+ private void checkError() throws IOException {
+ if(error != null) {
+ throw (IOException) new IOException(error.getMessage()).initCause(error);
+ }
+ }
+
+ public synchronized int read() throws IOException {
+ checkError();
+ int b = super.read();
+ checkError();
+ return b;
+ }
+ }
+
+ final class RequestHandler implements AsyncHandler<String> {
+
+ private final String url;
+
+ private final PipedErrorInputStream pis;
+
+ private PipedOutputStream pos;
+
+ private long total = -1;
+
+ private long transferred;
+
+ public RequestHandler(String url, PipedErrorInputStream pis) throws IOException {
+ this.url = url;
+ this.pis = pis;
+ pos = new PipedOutputStream(pis);
+ }
+
+ private void finish(Throwable exception) {
+ pis.setError(exception);
+ if(pos != null) {
+ try {
+ pos.close();
+ } catch(IOException ex) {
+ // tried it
+ }
+ pos = null;
+ }
+ }
+
+ private STATE checkCancel() {
+ if(monitor.isCanceled()) {
+ finish(new IOException(Messages.AsyncFetcher_error_cancelled));
+ return STATE.ABORT;
+ }
+ return STATE.CONTINUE;
+ }
+
+ public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception {
+ if(checkCancel() == STATE.ABORT || pos == null) {
+ return STATE.ABORT;
+ }
+ int bytes = content.getBodyByteBuffer().remaining();
+ content.writeTo(pos);
+ if(total > 0) {
+ transferred += bytes;
+ monitor.subTask(NLS.bind(Messages.AsyncFetcher_task_fetching2,url, transferred * 100 / total));
+ }
+ return STATE.CONTINUE;
+ }
+
+ public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
+ if(checkCancel() == STATE.ABORT) {
+ return STATE.ABORT;
+ }
+ try {
+ total = Long.parseLong(headers.getHeaders().getFirstValue("Content-Length")); //$NON-NLS-1$
+ } catch(Exception e) {
+ total = -1;
+ }
+ return STATE.CONTINUE;
+ }
+
+ public STATE onStatusReceived(HttpResponseStatus status) throws Exception {
+ if(status.getStatusCode() != HttpURLConnection.HTTP_OK) {
+ finish(new IOException(NLS.bind(Messages.AsyncFetcher_error_server, status.getStatusCode(), status.getStatusText())));
+ return STATE.ABORT;
+ }
+ if(checkCancel() == STATE.ABORT) {
+ return STATE.ABORT;
+ }
+ return STATE.CONTINUE;
+ }
+
+ public String onCompleted() throws Exception {
+ monitor.subTask(""); //$NON-NLS-1$
+ finish(null);
+ return ""; //$NON-NLS-1$
+ }
+
+ public void onThrowable(Throwable t) {
+ finish(t);
+ }
+
+ }
+
+}

Back to the top