| /******************************************************************************* |
| * Copyright (c) 2004, 2011 Composent, Inc., IBM 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: |
| * Composent, Inc. - initial API and implementation |
| * Maarten Meijer - bug 237936, added gzip encoded transfer default |
| * Henrich Kraemer - bug 263869, testHttpsReceiveFile fails using HTTP proxy |
| * Henrich Kraemer - bug 263613, [transport] Update site contacting / downloading is not cancelable |
| * Henrich Kraemer - Bug 297742 - [transport] Investigate how to maintain HTTP session |
| ******************************************************************************/ |
| package org.eclipse.ecf.provider.filetransfer.httpclient; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.HttpURLConnection; |
| import java.net.Socket; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| import javax.net.SocketFactory; |
| import org.apache.commons.httpclient.Credentials; |
| import org.apache.commons.httpclient.Header; |
| import org.apache.commons.httpclient.HostConfiguration; |
| import org.apache.commons.httpclient.HttpClient; |
| import org.apache.commons.httpclient.HttpConnection; |
| import org.apache.commons.httpclient.HttpException; |
| import org.apache.commons.httpclient.HttpState; |
| import org.apache.commons.httpclient.HttpStatus; |
| import org.apache.commons.httpclient.HttpVersion; |
| import org.apache.commons.httpclient.NTCredentials; |
| import org.apache.commons.httpclient.UsernamePasswordCredentials; |
| import org.apache.commons.httpclient.auth.AuthScope; |
| import org.apache.commons.httpclient.auth.CredentialsProvider; |
| import org.apache.commons.httpclient.methods.GetMethod; |
| import org.apache.commons.httpclient.protocol.Protocol; |
| import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; |
| import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; |
| import org.apache.commons.httpclient.util.DateUtil; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.ecf.core.identity.ID; |
| import org.eclipse.ecf.core.security.Callback; |
| import org.eclipse.ecf.core.security.CallbackHandler; |
| import org.eclipse.ecf.core.security.IConnectContext; |
| import org.eclipse.ecf.core.security.NameCallback; |
| import org.eclipse.ecf.core.security.ObjectCallback; |
| import org.eclipse.ecf.core.security.UnsupportedCallbackException; |
| import org.eclipse.ecf.core.util.Proxy; |
| import org.eclipse.ecf.core.util.ProxyAddress; |
| import org.eclipse.ecf.core.util.Trace; |
| import org.eclipse.ecf.filetransfer.FileTransferJob; |
| import org.eclipse.ecf.filetransfer.IFileRangeSpecification; |
| import org.eclipse.ecf.filetransfer.IFileTransferPausable; |
| import org.eclipse.ecf.filetransfer.IFileTransferRunnable; |
| import org.eclipse.ecf.filetransfer.IRetrieveFileTransferOptions; |
| import org.eclipse.ecf.filetransfer.IncomingFileTransferException; |
| import org.eclipse.ecf.filetransfer.InvalidFileRangeSpecificationException; |
| import org.eclipse.ecf.filetransfer.events.IFileTransferConnectStartEvent; |
| import org.eclipse.ecf.filetransfer.events.socket.ISocketEventSource; |
| import org.eclipse.ecf.filetransfer.events.socket.ISocketListener; |
| import org.eclipse.ecf.filetransfer.identity.IFileID; |
| import org.eclipse.ecf.internal.provider.filetransfer.httpclient.Activator; |
| import org.eclipse.ecf.internal.provider.filetransfer.httpclient.ConnectingSocketMonitor; |
| import org.eclipse.ecf.internal.provider.filetransfer.httpclient.ConnectionManagerHelper; |
| import org.eclipse.ecf.internal.provider.filetransfer.httpclient.DebugOptions; |
| import org.eclipse.ecf.internal.provider.filetransfer.httpclient.ECFHttpClientProtocolSocketFactory; |
| import org.eclipse.ecf.internal.provider.filetransfer.httpclient.ECFHttpClientSecureProtocolSocketFactory; |
| import org.eclipse.ecf.internal.provider.filetransfer.httpclient.HttpClientProxyCredentialProvider; |
| import org.eclipse.ecf.internal.provider.filetransfer.httpclient.ISSLSocketFactoryModifier; |
| import org.eclipse.ecf.internal.provider.filetransfer.httpclient.Messages; |
| import org.eclipse.ecf.provider.filetransfer.events.socket.SocketEventSource; |
| import org.eclipse.ecf.provider.filetransfer.identity.FileTransferID; |
| import org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer; |
| import org.eclipse.ecf.provider.filetransfer.retrieve.HttpHelper; |
| import org.eclipse.ecf.provider.filetransfer.util.JREProxyHelper; |
| import org.eclipse.ecf.provider.filetransfer.util.ProxySetupHelper; |
| import org.eclipse.osgi.util.NLS; |
| |
| public class HttpClientRetrieveFileTransfer extends AbstractRetrieveFileTransfer { |
| |
| /** |
| * gzip encoding wrapper for httpclient class. Copied from Mylyn project, bug 205708 |
| * |
| */ |
| public class GzipGetMethod extends GetMethod { |
| |
| private static final String CONTENT_ENCODING = "Content-Encoding"; //$NON-NLS-1$ |
| private static final String ACCEPT_ENCODING = "Accept-encoding"; //$NON-NLS-1$ |
| private static final String CONTENT_ENCODING_GZIP = "gzip"; //$NON-NLS-1$ |
| |
| private static final String CONTENT_ENCODING_ACCEPTED = CONTENT_ENCODING_GZIP; |
| |
| private boolean gzipReceived = false; |
| |
| public GzipGetMethod(String urlString) { |
| super(urlString); |
| } |
| |
| private boolean isZippedResponse() { |
| // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=269018 |
| boolean contentEncodingGzip = (null != this.getResponseHeader(CONTENT_ENCODING) && this.getResponseHeader(CONTENT_ENCODING).getValue().equals(CONTENT_ENCODING_GZIP)); |
| Trace.trace(Activator.PLUGIN_ID, "Content-Encoding: gzip header " + (contentEncodingGzip ? "PRESENT" : "ABSENT")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| boolean hasGzSuffix = targetHasGzSuffix(remoteFileName); |
| return contentEncodingGzip && !hasGzSuffix; |
| } |
| |
| public int execute(HttpState state, HttpConnection conn) throws HttpException, IOException { |
| Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, this.getClass(), "GzipGetMethod.execute"); //$NON-NLS-1$ |
| // Insert accept-encoding header |
| int result = super.execute(state, conn); |
| // Code to deal with implications described on bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=261881 |
| switch (result) { |
| case HttpStatus.SC_MOVED_TEMPORARILY : |
| case HttpStatus.SC_MOVED_PERMANENTLY : |
| case HttpStatus.SC_SEE_OTHER : |
| case HttpStatus.SC_TEMPORARY_REDIRECT : |
| Trace.trace(Activator.PLUGIN_ID, "GzipGetMethod.execute. Received redirect=" + result + ". Removing gzip accept encoding"); //$NON-NLS-1$ //$NON-NLS-2$ |
| gzipReceived = false; |
| removeRequestHeader(GzipGetMethod.ACCEPT_ENCODING); |
| default : |
| } |
| // test what is sent back |
| Trace.exiting(Activator.PLUGIN_ID, DebugOptions.METHODS_EXITING, this.getClass(), "GzipGetMethod.execute", new Integer(result)); //$NON-NLS-1$ |
| return result; |
| } |
| |
| public InputStream getResponseBodyAsUnzippedStream() throws IOException { |
| gzipReceived = isZippedResponse(); |
| InputStream input = super.getResponseBodyAsStream(); |
| try { |
| if (gzipReceived) { |
| Trace.trace(Activator.PLUGIN_ID, "Using gzip input stream to decode"); //$NON-NLS-1$ |
| // extract on the fly |
| return new java.util.zip.GZIPInputStream(input); |
| } |
| Trace.trace(Activator.PLUGIN_ID, "Not using gzip input stream"); //$NON-NLS-1$ |
| } catch (IOException e) { |
| Activator.getDefault().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, IStatus.WARNING, "Exception creating gzip input stream", e)); //$NON-NLS-1$ |
| throw e; |
| } |
| return input; |
| } |
| |
| private Object releaseLock = new Object(); |
| |
| // This override is a workaround for |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=279457 |
| // This makes GetMethod.releaseConnection non-reentrant, |
| // as with reentrancy under some circumstances a NPE can be |
| // thrown with multithreaded access |
| public void releaseConnection() { |
| synchronized (releaseLock) { |
| super.releaseConnection(); |
| } |
| } |
| } |
| |
| static final class HostConfigHelper { |
| private ISocketEventSource source; |
| private ISocketListener socketListener; |
| private String targetURL; |
| private String targetRelativePath; |
| |
| private HostConfiguration hostConfiguration; |
| |
| public HostConfigHelper(ISocketEventSource source, ISocketListener socketListener) { |
| Assert.isNotNull(source); |
| this.source = source; |
| this.socketListener = socketListener; |
| hostConfiguration = new HostConfiguration(); |
| } |
| |
| public HostConfiguration getHostConfiguration() { |
| return hostConfiguration; |
| } |
| |
| // drops the scheme server and port (e.g http://server:8080/a/b.html -> /a/b.html |
| private static String getTargetRelativePathFromURL(String url) { |
| // RFC 3986 |
| /* |
| * |
| * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] |
| |
| hier-part = "//" authority path-abempty |
| / path-absolute |
| / path-rootless |
| / path-empty |
| * |
| * path = path-abempty ; begins with "/" or is empty |
| / path-absolute ; begins with "/" but not "//" |
| / path-noscheme ; begins with a non-colon segment |
| / path-rootless ; begins with a segment |
| / path-empty ; zero characters |
| |
| * |
| */ |
| // This routine is supposed to remove authority information from the url |
| // to make this a 'relative path' for |
| // HttpClients method constructor (for example GetMethod(String uri)) as |
| // ECF executes methods passing in a HostConfiguration which represents the |
| // authority. |
| final int colonSlashSlash = url.indexOf("://"); //$NON-NLS-1$ |
| if (colonSlashSlash < 0) |
| return url; |
| |
| // '://' indicates there must be an authority. |
| // the authority must not contain a '/' character. |
| final int nextSlash = url.indexOf('/', colonSlashSlash + 3); |
| if (nextSlash == -1) { |
| // try root? or should it be empty? |
| return ""; //$NON-NLS-1$ |
| } |
| String relativeURL = url.substring(nextSlash); // include the slash |
| // This is a workaround for multiple consecutive slashes after the authority. |
| // HttpClient will parse this as another authority instead of using |
| // it as a path. In anticipation we add "//example.com" so that this will |
| // be removed instead of the first path segment. |
| // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=270749#c28 |
| // for a full explanation |
| if (relativeURL.startsWith("//")) { //$NON-NLS-1$ |
| final String host = "example.com"; //$NON-NLS-1$ |
| relativeURL = "//" + host + relativeURL; //$NON-NLS-1$ |
| |
| } |
| return relativeURL; |
| } |
| |
| public void setTargetHostByURL(CredentialsProvider credProvider, String url) { |
| this.targetURL = url; |
| this.targetRelativePath = getTargetRelativePathFromURL(targetURL); |
| String host = getHostFromURL(targetURL); |
| int port = getPortFromURL(targetURL); |
| |
| if (HttpClientRetrieveFileTransfer.urlUsesHttps(targetURL)) { |
| ISSLSocketFactoryModifier sslSocketFactoryModifier = Activator.getDefault().getSSLSocketFactoryModifier(); |
| if (sslSocketFactoryModifier == null) { |
| sslSocketFactoryModifier = new HttpClientDefaultSSLSocketFactoryModifier(); |
| } |
| SecureProtocolSocketFactory psf = new ECFHttpClientSecureProtocolSocketFactory(sslSocketFactoryModifier, source, socketListener); |
| Protocol sslProtocol = new Protocol(HttpClientRetrieveFileTransfer.HTTPS, (ProtocolSocketFactory) psf, HTTPS_PORT); |
| |
| Trace.trace(Activator.PLUGIN_ID, "retrieve host=" + host + ";port=" + port); //$NON-NLS-1$ //$NON-NLS-2$ |
| hostConfiguration.setHost(host, port, sslProtocol); |
| hostConfiguration.getParams().setParameter(CredentialsProvider.PROVIDER, credProvider); |
| |
| } else { |
| ProtocolSocketFactory psf = new ECFHttpClientProtocolSocketFactory(SocketFactory.getDefault(), source, socketListener); |
| Protocol protocol = new Protocol(HttpClientRetrieveFileTransfer.HTTP, psf, HTTP_PORT); |
| Trace.trace(Activator.PLUGIN_ID, "retrieve host=" + host + ";port=" + port); //$NON-NLS-1$ //$NON-NLS-2$ |
| hostConfiguration.setHost(host, port, protocol); |
| hostConfiguration.getParams().setParameter(CredentialsProvider.PROVIDER, credProvider); |
| } |
| } |
| |
| public String getTargetRelativePath() { |
| return targetRelativePath; |
| } |
| |
| } |
| |
| private static final String USERNAME_PREFIX = Messages.HttpClientRetrieveFileTransfer_Username_Prefix; |
| |
| // changing to 2 minutes (120000) as per bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=266246 |
| // 10/26/2009: Added being able to set with system property with name org.eclipse.ecf.provider.filetransfer.httpclient.retrieve.connectTimeout |
| // for https://bugs.eclipse.org/bugs/show_bug.cgi?id=292995 |
| protected static final int DEFAULT_CONNECTION_TIMEOUT = ConnectionManagerHelper.DEFAULT_CONNECTION_TIMEOUT; |
| // changing to 2 minutes (120000) as per bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=266246 |
| // 10/26/2009: Added being able to set with system property with name org.eclipse.ecf.provider.filetransfer.httpclient.retrieve.readTimeout |
| // for https://bugs.eclipse.org/bugs/show_bug.cgi?id=292995 |
| protected static final int DEFAULT_READ_TIMEOUT = ConnectionManagerHelper.DEFAULT_READ_TIMEOUT; |
| |
| protected static final int HTTP_PORT = 80; |
| |
| protected static final int HTTPS_PORT = 443; |
| |
| protected static final int MAX_RETRY = 2; |
| |
| protected static final String HTTPS = Messages.FileTransferNamespace_Https_Protocol; |
| |
| protected static final String HTTP = Messages.FileTransferNamespace_Http_Protocol; |
| |
| protected static final String[] supportedProtocols = {HTTP, HTTPS}; |
| |
| private static final String LAST_MODIFIED_HEADER = "Last-Modified"; //$NON-NLS-1$ |
| |
| private GzipGetMethod getMethod = null; |
| |
| private HttpClient httpClient = null; |
| |
| private String username; |
| |
| private String password; |
| |
| private int responseCode = -1; |
| private volatile boolean doneFired = false; |
| |
| private String remoteFileName; |
| |
| protected int httpVersion = 1; |
| |
| protected IFileID fileid = null; |
| |
| protected JREProxyHelper proxyHelper = null; |
| |
| private HostConfigHelper hostConfigHelper; |
| private SocketEventSource socketEventSource; |
| |
| private ConnectingSocketMonitor connectingSockets; |
| private FileTransferJob connectJob; |
| |
| public HttpClientRetrieveFileTransfer(HttpClient client) { |
| this.httpClient = client; |
| proxyHelper = new JREProxyHelper(); |
| connectingSockets = new ConnectingSocketMonitor(1); |
| socketEventSource = new SocketEventSource() { |
| public Object getAdapter(Class adapter) { |
| if (adapter == null) { |
| return null; |
| } |
| if (adapter.isInstance(this)) { |
| return this; |
| } |
| return HttpClientRetrieveFileTransfer.this.getAdapter(adapter); |
| } |
| |
| }; |
| |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#getRemoteFileName() |
| */ |
| public String getRemoteFileName() { |
| return remoteFileName; |
| } |
| |
| public synchronized void cancel() { |
| Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, this.getClass(), "cancel"); //$NON-NLS-1$ |
| if (isCanceled()) { |
| return; // break job cancel recursion |
| } |
| setDoneCanceled(exception); |
| boolean fireDoneEvent = true; |
| if (connectJob != null) { |
| Trace.trace(Activator.PLUGIN_ID, "calling connectJob.cancel()"); //$NON-NLS-1$ |
| connectJob.cancel(); |
| } |
| synchronized (jobLock) { |
| if (job != null) { |
| // Its the transfer jobs responsibility to throw the event. |
| fireDoneEvent = false; |
| Trace.trace(Activator.PLUGIN_ID, "calling transfer job.cancel()"); //$NON-NLS-1$ |
| job.cancel(); |
| } |
| } |
| if (getMethod != null) { |
| if (!getMethod.isAborted()) { |
| Trace.trace(Activator.PLUGIN_ID, "calling getMethod.abort()"); //$NON-NLS-1$ |
| getMethod.abort(); |
| } |
| } |
| if (connectingSockets != null) { |
| // this should unblock socket connect calls, if any |
| for (Iterator iterator = connectingSockets.getConnectingSockets().iterator(); iterator.hasNext();) { |
| Socket socket = (Socket) iterator.next(); |
| try { |
| Trace.trace(Activator.PLUGIN_ID, "Call socket.close() for socket=" + socket.toString()); //$NON-NLS-1$ |
| socket.close(); |
| } catch (IOException e) { |
| Trace.catching(Activator.PLUGIN_ID, DebugOptions.EXCEPTIONS_CATCHING, this.getClass(), "cancel", e); //$NON-NLS-1$ |
| } |
| } |
| } |
| hardClose(); |
| if (fireDoneEvent) { |
| fireTransferReceiveDoneEvent(); |
| } |
| Trace.exiting(Activator.PLUGIN_ID, DebugOptions.METHODS_EXITING, this.getClass(), "cancel");//$NON-NLS-1$ |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#hardClose() |
| */ |
| protected void hardClose() { |
| super.hardClose(); |
| if (getMethod != null) { |
| getMethod.releaseConnection(); |
| getMethod = null; |
| } |
| responseCode = -1; |
| if (proxyHelper != null) { |
| proxyHelper.dispose(); |
| proxyHelper = null; |
| } |
| } |
| |
| protected Credentials getFileRequestCredentials() throws UnsupportedCallbackException, IOException { |
| if (connectContext == null) |
| return null; |
| final CallbackHandler callbackHandler = connectContext.getCallbackHandler(); |
| if (callbackHandler == null) |
| return null; |
| final NameCallback usernameCallback = new NameCallback(USERNAME_PREFIX); |
| final ObjectCallback passwordCallback = new ObjectCallback(); |
| callbackHandler.handle(new Callback[] {usernameCallback, passwordCallback}); |
| username = usernameCallback.getName(); |
| password = (String) passwordCallback.getObject(); |
| return new UsernamePasswordCredentials(username, password); |
| } |
| |
| protected void setupProxies() { |
| // If it's been set directly (via ECF API) then this overrides platform settings |
| if (proxy == null) { |
| try { |
| // give SOCKS priority see https://bugs.eclipse.org/bugs/show_bug.cgi?id=295030#c61 |
| proxy = ProxySetupHelper.getSocksProxy(getRemoteFileURL()); |
| if (proxy == null) { |
| proxy = ProxySetupHelper.getProxy(getRemoteFileURL().toExternalForm()); |
| } |
| } catch (NoClassDefFoundError e) { |
| // If the proxy API is not available a NoClassDefFoundError will be thrown here. |
| // If that happens then we just want to continue on. |
| Activator.logNoProxyWarning(e); |
| } |
| } |
| if (proxy != null) |
| setupProxy(proxy); |
| } |
| |
| protected void setupAuthentication(String urlString) throws UnsupportedCallbackException, IOException { |
| Credentials credentials = null; |
| if (username == null) { |
| credentials = getFileRequestCredentials(); |
| } |
| |
| if (credentials != null && username != null) { |
| final AuthScope authScope = new AuthScope(getHostFromURL(urlString), getPortFromURL(urlString), AuthScope.ANY_REALM); |
| Trace.trace(Activator.PLUGIN_ID, "retrieve credentials=" + credentials); //$NON-NLS-1$ |
| httpClient.getState().setCredentials(authScope, credentials); |
| } |
| } |
| |
| protected void setupHostAndPort(CredentialsProvider credProvider, String urlString) { |
| getHostConfiguration(); // creates hostConfigHelper if needed |
| hostConfigHelper.setTargetHostByURL(credProvider, urlString); |
| } |
| |
| protected void setRequestHeaderValues() throws InvalidFileRangeSpecificationException { |
| final IFileRangeSpecification rangeSpec = getFileRangeSpecification(); |
| if (rangeSpec != null) { |
| final long startPosition = rangeSpec.getStartPosition(); |
| final long endPosition = rangeSpec.getEndPosition(); |
| if (startPosition < 0) |
| throw new InvalidFileRangeSpecificationException(Messages.HttpClientRetrieveFileTransfer_RESUME_START_POSITION_LESS_THAN_ZERO, rangeSpec); |
| if (endPosition != -1L && endPosition <= startPosition) |
| throw new InvalidFileRangeSpecificationException(Messages.HttpClientRetrieveFileTransfer_RESUME_ERROR_END_POSITION_LESS_THAN_START, rangeSpec); |
| String rangeHeader = "bytes=" + startPosition + "-" + ((endPosition == -1L) ? "" : ("" + endPosition)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
| Trace.trace(Activator.PLUGIN_ID, "retrieve range header=" + rangeHeader); //$NON-NLS-1$ |
| setRangeHeader(rangeHeader); |
| } |
| // set max-age for cache control to 0 for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=249990 |
| getMethod.addRequestHeader("Cache-Control", "max-age=0"); //$NON-NLS-1$//$NON-NLS-2$ |
| setRequestHeaderValuesFromOptions(); |
| } |
| |
| private void setRequestHeaderValuesFromOptions() { |
| Map localOptions = getOptions(); |
| if (localOptions != null) { |
| Object o = localOptions.get(IRetrieveFileTransferOptions.REQUEST_HEADERS); |
| if (o != null && o instanceof Map) { |
| Map requestHeaders = (Map) o; |
| for (Iterator i = requestHeaders.keySet().iterator(); i.hasNext();) { |
| Object n = i.next(); |
| Object v = requestHeaders.get(n); |
| if (n != null && n instanceof String && v != null && v instanceof String) |
| getMethod.addRequestHeader((String) n, (String) v); |
| } |
| } |
| } |
| } |
| |
| private void setRangeHeader(String value) { |
| getMethod.addRequestHeader("Range", value); //$NON-NLS-1$ |
| } |
| |
| private boolean isHTTP11() { |
| return (httpVersion >= 1); |
| } |
| |
| public int getResponseCode() { |
| if (responseCode != -1) |
| return responseCode; |
| HttpVersion version = getMethod.getEffectiveVersion(); |
| if (version == null) { |
| responseCode = -1; |
| httpVersion = 1; |
| return responseCode; |
| } |
| httpVersion = version.getMinor(); |
| responseCode = getMethod.getStatusCode(); |
| return responseCode; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.core.identity.IIdentifiable#getID() |
| */ |
| public ID getID() { |
| return fileid; |
| } |
| |
| private long getLastModifiedTimeFromHeader() throws IOException { |
| Header lastModifiedHeader = getMethod.getResponseHeader(LAST_MODIFIED_HEADER); |
| if (lastModifiedHeader == null) |
| throw new IOException(Messages.HttpClientRetrieveFileTransfer_INVALID_LAST_MODIFIED_TIME); |
| |
| String lastModifiedString = lastModifiedHeader.getValue(); |
| long lastModified = 0; |
| if (lastModifiedString != null) { |
| try { |
| lastModified = DateUtil.parseDate(lastModifiedString).getTime(); |
| } catch (Exception e) { |
| throw new IOException(Messages.HttpClientRetrieveFileTransfer_EXCEPITION_INVALID_LAST_MODIFIED_FROM_SERVER); |
| } |
| } |
| return lastModified; |
| } |
| |
| protected void getResponseHeaderValues() throws IOException { |
| if (getResponseCode() == -1) |
| throw new IOException(Messages.HttpClientRetrieveFileTransfer_INVALID_SERVER_RESPONSE_TO_PARTIAL_RANGE_REQUEST); |
| Header lastModifiedHeader = getMethod.getResponseHeader(LAST_MODIFIED_HEADER); |
| if (lastModifiedHeader != null) { |
| setLastModifiedTime(getLastModifiedTimeFromHeader()); |
| } |
| setFileLength(getMethod.getResponseContentLength()); |
| fileid = new FileTransferID(getRetrieveNamespace(), getRemoteFileURL()); |
| |
| // Get content disposition header and get remote file name from it if possible. |
| Header contentDispositionHeader = getMethod.getResponseHeader(HttpHelper.CONTENT_DISPOSITION_HEADER); |
| if (contentDispositionHeader != null) { |
| remoteFileName = HttpHelper.getRemoteFileNameFromContentDispositionHeader(contentDispositionHeader.getValue()); |
| } |
| // If still null, get the path from httpclient.getMethod() |
| if (remoteFileName == null) { |
| // No name could be extracted using Content-Disposition. Let's try the |
| // path from the getMethod. |
| String pathStr = getMethod.getPath(); |
| if (pathStr != null && pathStr.length() > 0) { |
| IPath path = Path.fromPortableString(pathStr); |
| if (path.segmentCount() > 0) |
| remoteFileName = path.lastSegment(); |
| } |
| // If still null, use the input file name |
| if (remoteFileName == null) |
| // Last resort. Use the path of the initial URL request |
| remoteFileName = super.getRemoteFileName(); |
| } |
| } |
| |
| final class ECFCredentialsProvider extends HttpClientProxyCredentialProvider { |
| |
| protected Proxy getECFProxy() { |
| return getProxy(); |
| } |
| |
| protected Credentials getNTLMCredentials(Proxy lp) { |
| if (hasForceNTLMProxyOption()) |
| return HttpClientRetrieveFileTransfer.createNTLMCredentials(lp); |
| return null; |
| } |
| |
| } |
| |
| Proxy getProxy() { |
| return proxy; |
| } |
| |
| protected void setInputStream(InputStream ins) { |
| remoteFileContents = ins; |
| } |
| |
| protected InputStream wrapTransferReadInputStream(InputStream inputStream, IProgressMonitor monitor) { |
| return inputStream; |
| } |
| |
| protected boolean hasForceNTLMProxyOption() { |
| Map localOptions = getOptions(); |
| if (localOptions != null && localOptions.get(HttpClientOptions.FORCE_NTLM_PROP) != null) |
| return true; |
| return (System.getProperties().getProperty(HttpClientOptions.FORCE_NTLM_PROP) != null); |
| } |
| |
| protected int getSocketReadTimeout() { |
| return ConnectionManagerHelper.getSocketReadTimeout(getOptions()); |
| } |
| |
| /** |
| * @since 4.0 |
| */ |
| protected int getConnectTimeout() { |
| return ConnectionManagerHelper.getConnectTimeout(getOptions()); |
| } |
| |
| private void initHttpClientConnectionManager() { |
| Activator.getDefault().getConnectionManagerHelper().initConnectionManager(httpClient, getOptions()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#openStreams() |
| */ |
| protected void openStreams() throws IncomingFileTransferException { |
| |
| Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, this.getClass(), "openStreams"); //$NON-NLS-1$ |
| final String urlString = getRemoteFileURL().toString(); |
| this.doneFired = false; |
| |
| int code = -1; |
| |
| try { |
| initHttpClientConnectionManager(); |
| setupAuthentication(urlString); |
| |
| CredentialsProvider credProvider = new ECFCredentialsProvider(); |
| setupHostAndPort(credProvider, urlString); |
| |
| getMethod = new GzipGetMethod(hostConfigHelper.getTargetRelativePath()); |
| getMethod.addRequestHeader("Connection", "Keep-Alive"); //$NON-NLS-1$ //$NON-NLS-2$ |
| getMethod.setFollowRedirects(true); |
| // Define a CredentialsProvider - found that possibility while debugging in org.apache.commons.httpclient.HttpMethodDirector.processProxyAuthChallenge(HttpMethod) |
| // Seems to be another way to select the credentials. |
| getMethod.getParams().setParameter(CredentialsProvider.PROVIDER, credProvider); |
| setRequestHeaderValues(); |
| |
| Trace.trace(Activator.PLUGIN_ID, "retrieve=" + urlString); //$NON-NLS-1$ |
| // Set request header for possible gzip encoding, but only if |
| // 1) The file range specification is null (we want the whole file) |
| // 2) The target remote file does *not* end in .gz (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=280205) |
| if (getFileRangeSpecification() == null && !targetHasGzSuffix(super.getRemoteFileName())) { |
| Trace.trace(Activator.PLUGIN_ID, "Accept-Encoding: gzip added to request header"); //$NON-NLS-1$ |
| getMethod.setRequestHeader(GzipGetMethod.ACCEPT_ENCODING, GzipGetMethod.CONTENT_ENCODING_ACCEPTED); |
| } else { |
| Trace.trace(Activator.PLUGIN_ID, "Accept-Encoding NOT added to header"); //$NON-NLS-1$ |
| } |
| |
| fireConnectStartEvent(); |
| if (checkAndHandleDone()) { |
| return; |
| } |
| |
| connectingSockets.clear(); |
| // Actually execute get and get response code (since redirect is set to true, then |
| // redirect response code handled internally |
| if (connectJob == null) { |
| performConnect(new NullProgressMonitor()); |
| } else { |
| connectJob.schedule(); |
| connectJob.join(); |
| connectJob = null; |
| } |
| if (checkAndHandleDone()) { |
| return; |
| } |
| |
| code = responseCode; |
| |
| responseHeaders = getResponseHeaders(); |
| |
| Trace.trace(Activator.PLUGIN_ID, "retrieve resp=" + code); //$NON-NLS-1$ |
| |
| // Check for NTLM proxy in response headers |
| // This check is to deal with bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=252002 |
| boolean ntlmProxyFound = NTLMProxyDetector.detectNTLMProxy(getMethod); |
| if (ntlmProxyFound && !hasForceNTLMProxyOption()) |
| throw new IncomingFileTransferException("HttpClient Provider is not configured to support NTLM proxy authentication.", HttpClientOptions.NTLM_PROXY_RESPONSE_CODE); //$NON-NLS-1$ |
| |
| if (code == HttpURLConnection.HTTP_PARTIAL || code == HttpURLConnection.HTTP_OK) { |
| getResponseHeaderValues(); |
| setInputStream(getMethod.getResponseBodyAsUnzippedStream()); |
| fireReceiveStartEvent(); |
| } else if (code == HttpURLConnection.HTTP_NOT_FOUND) { |
| getMethod.releaseConnection(); |
| throw new IncomingFileTransferException(NLS.bind("File not found: {0}", urlString), code); //$NON-NLS-1$ |
| } else if (code == HttpURLConnection.HTTP_UNAUTHORIZED) { |
| getMethod.releaseConnection(); |
| throw new IncomingFileTransferException(Messages.HttpClientRetrieveFileTransfer_Unauthorized, code); |
| } else if (code == HttpURLConnection.HTTP_FORBIDDEN) { |
| getMethod.releaseConnection(); |
| throw new IncomingFileTransferException("Forbidden", code); //$NON-NLS-1$ |
| } else if (code == HttpURLConnection.HTTP_PROXY_AUTH) { |
| getMethod.releaseConnection(); |
| throw new IncomingFileTransferException(Messages.HttpClientRetrieveFileTransfer_Proxy_Auth_Required, code); |
| } else { |
| getMethod.releaseConnection(); |
| throw new IncomingFileTransferException(NLS.bind(Messages.HttpClientRetrieveFileTransfer_ERROR_GENERAL_RESPONSE_CODE, new Integer(code)), code); |
| } |
| } catch (final Exception e) { |
| Trace.throwing(Activator.PLUGIN_ID, DebugOptions.EXCEPTIONS_THROWING, this.getClass(), "openStreams", e); //$NON-NLS-1$ |
| if (code == -1) { |
| if (!isDone()) { |
| setDoneException(e); |
| } |
| fireTransferReceiveDoneEvent(); |
| } else { |
| IncomingFileTransferException ex = (IncomingFileTransferException) ((e instanceof IncomingFileTransferException) ? e : new IncomingFileTransferException(NLS.bind(Messages.HttpClientRetrieveFileTransfer_EXCEPTION_COULD_NOT_CONNECT, urlString), e, code)); |
| throw ex; |
| } |
| } |
| Trace.exiting(Activator.PLUGIN_ID, DebugOptions.METHODS_EXITING, this.getClass(), "openStreams"); //$NON-NLS-1$ |
| } |
| |
| private Map getResponseHeaders() { |
| if (getMethod == null) |
| return null; |
| Header[] headers = getMethod.getResponseHeaders(); |
| Map result = null; |
| if (headers != null && headers.length > 0) { |
| result = new HashMap(); |
| for (int i = 0; i < headers.length; i++) { |
| String name = headers[i].getName(); |
| String val = headers[i].getValue(); |
| if (name != null && val != null) |
| result.put(name, val); |
| } |
| } |
| return Collections.unmodifiableMap(result); |
| } |
| |
| private boolean checkAndHandleDone() { |
| if (isDone()) { |
| // for cancel the done event should have been fired always. |
| if (!doneFired) { |
| fireTransferReceiveDoneEvent(); |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#setConnectContextForAuthentication(org.eclipse.ecf.core.security.IConnectContext) |
| */ |
| public void setConnectContextForAuthentication(IConnectContext connectContext) { |
| super.setConnectContextForAuthentication(connectContext); |
| this.username = null; |
| this.password = null; |
| } |
| |
| protected static String getHostFromURL(String url) { |
| String result = url; |
| final int colonSlashSlash = url.indexOf("://"); //$NON-NLS-1$ |
| if (colonSlashSlash < 0) |
| return ""; //$NON-NLS-1$ |
| if (colonSlashSlash >= 0) { |
| result = url.substring(colonSlashSlash + 3); |
| } |
| |
| final int colonPort = result.indexOf(':'); |
| final int requestPath = result.indexOf('/'); |
| |
| int substringEnd; |
| |
| if (colonPort > 0 && requestPath > 0) |
| substringEnd = Math.min(colonPort, requestPath); |
| else if (colonPort > 0) |
| substringEnd = colonPort; |
| else if (requestPath > 0) |
| substringEnd = requestPath; |
| else |
| substringEnd = result.length(); |
| |
| return result.substring(0, substringEnd); |
| |
| } |
| |
| protected static int getPortFromURL(String url) { |
| final int colonSlashSlash = url.indexOf("://"); //$NON-NLS-1$ |
| if (colonSlashSlash < 0) |
| return urlUsesHttps(url) ? HTTPS_PORT : HTTP_PORT; |
| // This is wrong as if the url has no colonPort before '?' then it should return the default |
| |
| final int colonPort = url.indexOf(':', colonSlashSlash + 1); |
| if (colonPort < 0) |
| return urlUsesHttps(url) ? HTTPS_PORT : HTTP_PORT; |
| // Make sure that the colonPort is not from some part of the rest of the URL |
| int nextSlash = url.indexOf('/', colonSlashSlash + 3); |
| if (nextSlash != -1 && colonPort > nextSlash) |
| return urlUsesHttps(url) ? HTTPS_PORT : HTTP_PORT; |
| |
| final int requestPath = url.indexOf('/', colonPort + 1); |
| |
| int end; |
| if (requestPath < 0) |
| end = url.length(); |
| else |
| end = requestPath; |
| |
| return Integer.parseInt(url.substring(colonPort + 1, end)); |
| } |
| |
| protected static boolean urlUsesHttps(String url) { |
| url = url.trim(); |
| return url.startsWith(HTTPS); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.internal.provider.filetransfer.AbstractRetrieveFileTransfer#supportsProtocol(java.lang.String) |
| */ |
| public static boolean supportsProtocol(String protocolString) { |
| for (int i = 0; i < supportedProtocols.length; i++) |
| if (supportedProtocols[i].equalsIgnoreCase(protocolString)) |
| return true; |
| return false; |
| } |
| |
| protected boolean isConnected() { |
| return (getMethod != null); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#doPause() |
| */ |
| protected boolean doPause() { |
| if (isPaused() || !isConnected() || isDone()) |
| return false; |
| this.paused = true; |
| return this.paused; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#doResume() |
| */ |
| protected boolean doResume() { |
| if (!isPaused() || isConnected()) |
| return false; |
| return openStreamsForResume(); |
| } |
| |
| protected void setResumeRequestHeaderValues() throws IOException { |
| if (this.bytesReceived <= 0 || this.fileLength <= this.bytesReceived) |
| throw new IOException(Messages.HttpClientRetrieveFileTransfer_RESUME_START_ERROR); |
| setRangeHeader("bytes=" + this.bytesReceived + "-"); //$NON-NLS-1$ //$NON-NLS-2$ |
| // set max-age for cache control to 0 for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=249990 |
| getMethod.addRequestHeader("Cache-Control", "max-age=0"); //$NON-NLS-1$//$NON-NLS-2$ |
| setRequestHeaderValuesFromOptions(); |
| } |
| |
| private boolean openStreamsForResume() { |
| |
| Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, this.getClass(), "openStreamsForResume"); //$NON-NLS-1$ |
| final String urlString = getRemoteFileURL().toString(); |
| this.doneFired = false; |
| |
| int code = -1; |
| |
| try { |
| initHttpClientConnectionManager(); |
| |
| CredentialsProvider credProvider = new ECFCredentialsProvider(); |
| setupAuthentication(urlString); |
| |
| setupHostAndPort(credProvider, urlString); |
| |
| getMethod = new GzipGetMethod(hostConfigHelper.getTargetRelativePath()); |
| getMethod.addRequestHeader("Connection", "Keep-Alive"); //$NON-NLS-1$ //$NON-NLS-2$ |
| getMethod.setFollowRedirects(true); |
| // Define a CredentialsProvider - found that possibility while debugging in org.apache.commons.httpclient.HttpMethodDirector.processProxyAuthChallenge(HttpMethod) |
| // Seems to be another way to select the credentials. |
| getMethod.getParams().setParameter(CredentialsProvider.PROVIDER, credProvider); |
| setResumeRequestHeaderValues(); |
| |
| Trace.trace(Activator.PLUGIN_ID, "resume=" + urlString); //$NON-NLS-1$ |
| |
| // Gzip encoding is not an option for resume |
| fireConnectStartEvent(); |
| if (checkAndHandleDone()) { |
| return false; |
| } |
| |
| connectingSockets.clear(); |
| // Actually execute get and get response code (since redirect is set to true, then |
| // redirect response code handled internally |
| if (connectJob == null) { |
| performConnect(new NullProgressMonitor()); |
| } else { |
| connectJob.schedule(); |
| connectJob.join(); |
| connectJob = null; |
| } |
| if (checkAndHandleDone()) { |
| return false; |
| } |
| |
| code = responseCode; |
| |
| responseHeaders = getResponseHeaders(); |
| |
| Trace.trace(Activator.PLUGIN_ID, "retrieve resp=" + code); //$NON-NLS-1$ |
| |
| if (code == HttpURLConnection.HTTP_PARTIAL || code == HttpURLConnection.HTTP_OK) { |
| getResumeResponseHeaderValues(); |
| setInputStream(getMethod.getResponseBodyAsUnzippedStream()); |
| this.paused = false; |
| fireReceiveResumedEvent(); |
| } else if (code == HttpURLConnection.HTTP_NOT_FOUND) { |
| getMethod.releaseConnection(); |
| throw new IncomingFileTransferException(NLS.bind("File not found: {0}", urlString), code, responseHeaders); //$NON-NLS-1$ |
| } else if (code == HttpURLConnection.HTTP_UNAUTHORIZED) { |
| getMethod.releaseConnection(); |
| throw new IncomingFileTransferException(Messages.HttpClientRetrieveFileTransfer_Unauthorized, code, responseHeaders); |
| } else if (code == HttpURLConnection.HTTP_FORBIDDEN) { |
| getMethod.releaseConnection(); |
| throw new IncomingFileTransferException("Forbidden", code, responseHeaders); //$NON-NLS-1$ |
| } else if (code == HttpURLConnection.HTTP_PROXY_AUTH) { |
| getMethod.releaseConnection(); |
| throw new IncomingFileTransferException(Messages.HttpClientRetrieveFileTransfer_Proxy_Auth_Required, code, responseHeaders); |
| } else { |
| getMethod.releaseConnection(); |
| throw new IncomingFileTransferException(NLS.bind(Messages.HttpClientRetrieveFileTransfer_ERROR_GENERAL_RESPONSE_CODE, new Integer(code)), code, responseHeaders); |
| } |
| Trace.exiting(Activator.PLUGIN_ID, DebugOptions.METHODS_EXITING, this.getClass(), "openStreamsForResume", Boolean.TRUE); //$NON-NLS-1$ |
| return true; |
| } catch (final Exception e) { |
| Trace.catching(Activator.PLUGIN_ID, DebugOptions.EXCEPTIONS_CATCHING, this.getClass(), "openStreamsForResume", e); //$NON-NLS-1$ |
| if (code == -1) { |
| if (!isDone()) { |
| setDoneException(e); |
| } |
| } else { |
| setDoneException((e instanceof IncomingFileTransferException) ? e : new IncomingFileTransferException(NLS.bind(Messages.HttpClientRetrieveFileTransfer_EXCEPTION_COULD_NOT_CONNECT, urlString), e, code, responseHeaders)); |
| } |
| fireTransferReceiveDoneEvent(); |
| Trace.exiting(Activator.PLUGIN_ID, DebugOptions.METHODS_EXITING, this.getClass(), "openStreamsForResume", Boolean.FALSE); //$NON-NLS-1$ |
| return false; |
| } |
| } |
| |
| protected void getResumeResponseHeaderValues() throws IOException { |
| if (getResponseCode() != HttpURLConnection.HTTP_PARTIAL) |
| throw new IOException(); |
| if (lastModifiedTime != getLastModifiedTimeFromHeader()) |
| throw new IOException(Messages.HttpClientRetrieveFileTransfer_EXCEPTION_FILE_MODIFIED_SINCE_LAST_ACCESS); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#getAdapter(java.lang.Class) |
| */ |
| public Object getAdapter(Class adapter) { |
| if (adapter == null) |
| return null; |
| if (adapter.equals(IFileTransferPausable.class) && isHTTP11()) |
| return this; |
| if (adapter.equals(ISocketEventSource.class)) |
| return this.socketEventSource; |
| return super.getAdapter(adapter); |
| } |
| |
| private HostConfiguration getHostConfiguration() { |
| if (hostConfigHelper == null) { |
| hostConfigHelper = new HostConfigHelper(socketEventSource, connectingSockets); |
| } |
| return hostConfigHelper.getHostConfiguration(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#setupProxy(org.eclipse.ecf.core.util.Proxy) |
| */ |
| protected void setupProxy(Proxy proxy) { |
| if (proxy.getType().equals(Proxy.Type.HTTP)) { |
| final ProxyAddress address = proxy.getAddress(); |
| getHostConfiguration().setProxy(address.getHostName(), address.getPort()); |
| } else if (proxy.getType().equals(Proxy.Type.SOCKS)) { |
| Trace.trace(Activator.PLUGIN_ID, "retrieve socksproxy=" + proxy.getAddress()); //$NON-NLS-1$ |
| proxyHelper.setupProxy(proxy); |
| } |
| } |
| |
| public static NTCredentials createNTLMCredentials(Proxy p) { |
| if (p == null) { |
| return null; |
| } |
| String un = getNTLMUserName(p); |
| String domain = getNTLMDomainName(p); |
| if (un == null || domain == null) |
| return null; |
| return new NTCredentials(un, p.getPassword(), p.getAddress().getHostName(), domain); |
| } |
| |
| protected static String getNTLMDomainName(Proxy p) { |
| String domainUsername = p.getUsername(); |
| if (domainUsername == null) |
| return null; |
| int slashloc = domainUsername.indexOf('\\'); |
| if (slashloc == -1) |
| return null; |
| return domainUsername.substring(0, slashloc); |
| } |
| |
| protected static String getNTLMUserName(Proxy p) { |
| String domainUsername = p.getUsername(); |
| if (domainUsername == null) |
| return null; |
| int slashloc = domainUsername.indexOf('\\'); |
| if (slashloc == -1) |
| return null; |
| return domainUsername.substring(slashloc + 1); |
| } |
| |
| protected void fireConnectStartEvent() { |
| Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, this.getClass(), "fireConnectStartEvent"); //$NON-NLS-1$ |
| // TODO: should the following be in super.fireReceiveStartEvent(); |
| listener.handleTransferEvent(new IFileTransferConnectStartEvent() { |
| public IFileID getFileID() { |
| return remoteFileID; |
| } |
| |
| public void cancel() { |
| HttpClientRetrieveFileTransfer.this.cancel(); |
| } |
| |
| public FileTransferJob prepareConnectJob(FileTransferJob j) { |
| return HttpClientRetrieveFileTransfer.this.prepareConnectJob(j); |
| } |
| |
| public void connectUsingJob(FileTransferJob j) { |
| HttpClientRetrieveFileTransfer.this.connectUsingJob(j); |
| } |
| |
| public String toString() { |
| final StringBuffer sb = new StringBuffer("IFileTransferConnectStartEvent["); //$NON-NLS-1$ |
| sb.append(getFileID()); |
| sb.append("]"); //$NON-NLS-1$ |
| return sb.toString(); |
| } |
| |
| public Object getAdapter(Class adapter) { |
| return HttpClientRetrieveFileTransfer.this.getAdapter(adapter); |
| } |
| }); |
| } |
| |
| protected String createConnectJobName() { |
| return getRemoteFileURL().toString() + createRangeName() + Messages.HttpClientRetrieveFileTransfer_CONNECTING_JOB_NAME; |
| } |
| |
| protected FileTransferJob prepareConnectJob(FileTransferJob cjob) { |
| if (cjob == null) { |
| // Create our own |
| cjob = new FileTransferJob(createJobName()); |
| } |
| cjob.setFileTransfer(this); |
| cjob.setFileTransferRunnable(fileConnectRunnable); |
| return cjob; |
| } |
| |
| protected void connectUsingJob(FileTransferJob cjob) { |
| Assert.isNotNull(cjob); |
| this.connectJob = cjob; |
| } |
| |
| private IFileTransferRunnable fileConnectRunnable = new IFileTransferRunnable() { |
| public IStatus performFileTransfer(IProgressMonitor monitor) { |
| return performConnect(monitor); |
| } |
| }; |
| |
| private IStatus performConnect(IProgressMonitor monitor) { |
| // there might be more ticks in the future perhaps for |
| // connect socket, certificate validation, send request, authenticate, |
| int ticks = 1; |
| monitor.beginTask(getRemoteFileURL().toString() + Messages.HttpClientRetrieveFileTransfer_CONNECTING_TASK_NAME, ticks); |
| try { |
| if (monitor.isCanceled()) |
| throw newUserCancelledException(); |
| responseCode = httpClient.executeMethod(getHostConfiguration(), getMethod); |
| Trace.trace(Activator.PLUGIN_ID, "retrieve resp=" + responseCode); //$NON-NLS-1$ |
| } catch (final Exception e) { |
| Trace.catching(Activator.PLUGIN_ID, DebugOptions.EXCEPTIONS_CATCHING, this.getClass(), "performConnect", e); //$NON-NLS-1$ |
| if (!isDone()) { |
| setDoneException(e); |
| } |
| } finally { |
| monitor.done(); |
| } |
| return Status.OK_STATUS; |
| |
| } |
| |
| protected void fireReceiveResumedEvent() { |
| Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, this.getClass(), "fireReceiveResumedEvent len=" + fileLength + ";rcvd=" + bytesReceived); //$NON-NLS-1$ //$NON-NLS-2$ |
| super.fireReceiveResumedEvent(); |
| } |
| |
| protected void fireTransferReceiveDataEvent() { |
| Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, this.getClass(), "fireTransferReceiveDataEvent len=" + fileLength + ";rcvd=" + bytesReceived); //$NON-NLS-1$ //$NON-NLS-2$ |
| super.fireTransferReceiveDataEvent(); |
| } |
| |
| protected void fireTransferReceiveDoneEvent() { |
| Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, this.getClass(), "fireTransferReceiveDoneEvent len=" + fileLength + ";rcvd=" + bytesReceived); //$NON-NLS-1$ //$NON-NLS-2$ |
| this.doneFired = true; |
| super.fireTransferReceiveDoneEvent(); |
| } |
| |
| protected void fireTransferReceivePausedEvent() { |
| Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, this.getClass(), "fireTransferReceivePausedEvent len=" + fileLength + ";rcvd=" + bytesReceived); //$NON-NLS-1$ //$NON-NLS-2$ |
| super.fireTransferReceivePausedEvent(); |
| } |
| |
| } |