/******************************************************************************* * Copyright (c) 2012 Pivotal Software, 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: * Pivotal Software, Inc. - initial API and implementation *******************************************************************************/ package org.springsource.ide.eclipse.commons.internal.core.net; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HostConfiguration; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.HeadMethod; import org.apache.commons.httpclient.util.DateParseException; import org.apache.commons.httpclient.util.DateUtil; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.mylyn.commons.net.WebLocation; import org.eclipse.osgi.util.NLS; import org.springsource.ide.eclipse.commons.internal.core.CorePlugin; /** * A utility for accessing web resources. * @author Steffen Pingel */ public class HttpClientTransportService implements ITransportService { private static final int BUFFER_SIZE = 4 * 1024; public HttpClientTransportService() { } /** * Download an HTTP-based resource * * @param target the target file to which the content is saved * @param location the web location of the content * @param monitor the monitor * @throws IOException if a network or IO problem occurs */ public void download(java.net.URI uri, OutputStream out, IProgressMonitor progressMonitor) throws CoreException { WebLocation location = new WebLocation(uri.toString()); SubMonitor monitor = SubMonitor.convert(progressMonitor); monitor.subTask(NLS.bind("Fetching {0}", location.getUrl())); try { HttpClient client = new HttpClient(); org.eclipse.mylyn.commons.net.WebUtil.configureHttpClient(client, ""); //$NON-NLS-1$ GetMethod method = new GetMethod(location.getUrl()); try { HostConfiguration hostConfiguration = org.eclipse.mylyn.commons.net.WebUtil.createHostConfiguration( client, location, monitor); int result = org.eclipse.mylyn.commons.net.WebUtil.execute(client, hostConfiguration, method, monitor); if (result == HttpStatus.SC_OK) { long total = method.getResponseContentLength(); if (total != -1) { monitor.setWorkRemaining((int) total); } InputStream in = org.eclipse.mylyn.commons.net.WebUtil.getResponseBodyAsStream(method, monitor); try { in = new BufferedInputStream(in); byte[] buffer = new byte[BUFFER_SIZE]; int len; while ((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); if (total != -1) { monitor.worked(len); } else { monitor.worked(1); monitor.setWorkRemaining(10000); } if (monitor.isCanceled()) { // this point is reached if the user requests a // cancellation throw new OperationCanceledException(); } } } catch (OperationCanceledException e) { // this point is reached if there is some problem with // the download throw toException(location, result); } catch (IOException e) { // this point is reached if there is some problem with // the network throw toException(location, 500); } finally { in.close(); } } else { throw toException(location, result); } } finally { method.releaseConnection(); } } catch (IOException e) { throw toException(location, e); } finally { monitor.done(); } } /** * Verify availability of resources at the given web locations. Normally * this would be done using an HTTP HEAD. * * @param locations the locations of the resource to verify * @param one indicate if only one of the resources must exist * @param progressMonitor the monitor * @return true if the resource exists */ public long getLastModified(java.net.URI uri, IProgressMonitor progressMonitor) throws CoreException { WebLocation location = new WebLocation(uri.toString()); SubMonitor monitor = SubMonitor.convert(progressMonitor); monitor.subTask(NLS.bind("Fetching {0}", location.getUrl())); try { HttpClient client = new HttpClient(); org.eclipse.mylyn.commons.net.WebUtil.configureHttpClient(client, ""); //$NON-NLS-1$ HeadMethod method = new HeadMethod(location.getUrl()); try { HostConfiguration hostConfiguration = org.eclipse.mylyn.commons.net.WebUtil.createHostConfiguration( client, location, monitor); int result = org.eclipse.mylyn.commons.net.WebUtil.execute(client, hostConfiguration, method, monitor); if (result == HttpStatus.SC_OK) { Header lastModified = method.getResponseHeader("Last-Modified"); //$NON-NLS-1$ if (lastModified != null) { try { return DateUtil.parseDate(lastModified.getValue()).getTime(); } catch (DateParseException e) { // fall through } } return 0; } else { throw toException(location, result); } } catch (IOException e) { throw toException(location, e); } finally { method.releaseConnection(); } } finally { monitor.done(); } } /** * Read a web-based resource at the specified location using the given * processor. * * @param location the web location of the content * @param processor the processor that will handle content * @param progressMonitor the monitor * @throws IOException if a network or IO problem occurs */ public InputStream stream(java.net.URI uri, IProgressMonitor progressMonitor) throws CoreException { WebLocation location = new WebLocation(uri.toString()); SubMonitor monitor = SubMonitor.convert(progressMonitor); monitor.subTask(NLS.bind("Fetching {0}", location.getUrl())); try { HttpClient client = new HttpClient(); org.eclipse.mylyn.commons.net.WebUtil.configureHttpClient(client, ""); //$NON-NLS-1$ boolean success = false; GetMethod method = new GetMethod(location.getUrl()); try { HostConfiguration hostConfiguration = org.eclipse.mylyn.commons.net.WebUtil.createHostConfiguration( client, location, monitor); int result = org.eclipse.mylyn.commons.net.WebUtil.execute(client, hostConfiguration, method, monitor); if (result == HttpStatus.SC_OK) { InputStream in = org.eclipse.mylyn.commons.net.WebUtil.getResponseBodyAsStream(method, monitor); success = true; return in; } else { throw toException(location, result); } } catch (IOException e) { throw toException(location, e); } finally { if (!success) { method.releaseConnection(); } } } finally { monitor.done(); } } private CoreException toException(WebLocation location, int result) { return new CoreException(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, NLS.bind( "Download of {0} failed: Unexpected HTTP response {1}", location.getUrl(), result))); } private CoreException toException(WebLocation location, IOException e) throws CoreException { String message = e.getMessage() != null ? e.getMessage() : "Unexpected error"; return new CoreException(new Status(IStatus.ERROR, CorePlugin.PLUGIN_ID, NLS.bind( "Download of {0} failed: {1}", location.getUrl(), message), e)); } }