diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/FileReader.java')
-rw-r--r-- | bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/FileReader.java | 502 |
1 files changed, 0 insertions, 502 deletions
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/FileReader.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/FileReader.java deleted file mode 100644 index fcc92c214..000000000 --- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/FileReader.java +++ /dev/null @@ -1,502 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2010 Cloudsmith 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: - * Cloudsmith Inc - initial API and implementation - * IBM Corporation - ongoing development - * Sonatype Inc - ongoing development - ******************************************************************************/ -package org.eclipse.equinox.internal.p2.repository; - -import java.io.*; -import java.net.SocketTimeoutException; -import java.net.URI; -import java.util.Date; -import org.eclipse.core.runtime.*; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.ecf.core.security.IConnectContext; -import org.eclipse.ecf.filetransfer.*; -import org.eclipse.ecf.filetransfer.events.*; -import org.eclipse.ecf.filetransfer.identity.*; -import org.eclipse.ecf.filetransfer.service.IRetrieveFileTransferFactory; -import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; -import org.eclipse.osgi.util.NLS; - -/** - * FileReader is an ECF FileTransferJob implementation. - */ -public final class FileReader extends FileTransferJob implements IFileTransferListener { - /** - * Class used to suppress warnings about a job being blocked by another job. - * Since we are running a job that will always be blocked by another job that - * is actually performing the transfer, these messages are unnecessary and ugly. - */ - static class SuppressBlockedMonitor extends SubProgressMonitor { - public SuppressBlockedMonitor(IProgressMonitor monitor, int ticks) { - super(monitor, ticks); - } - - public void setBlocked(IStatus reason) { - //do nothing - } - - public void clearBlocked() { - //do nothing - } - } - - private static IFileReaderProbe testProbe; - private boolean closeStreamWhenFinished = false; - private Exception exception; - private FileInfo fileInfo; - private long lastProgressCount; - private long lastStatsCount; - protected IProgressMonitor theMonitor; - private OutputStream theOutputStream; - private ProgressStatistics statistics; - private final int connectionRetryCount; - private final long connectionRetryDelay; - private final IConnectContext connectContext; - private URI requestUri; - protected IFileTransferConnectStartEvent connectEvent; - private Job cancelJob; - private boolean monitorStarted; - - /** - * Create a new FileReader that will retry failed connection attempts and sleep some amount of time between each - * attempt. - */ - public FileReader(IConnectContext aConnectContext) { - super(Messages.FileTransport_reader); // job label - - // Hide this job. - setSystem(true); - setUser(false); - connectionRetryCount = RepositoryPreferences.getConnectionRetryCount(); - connectionRetryDelay = RepositoryPreferences.getConnectionMsRetryDelay(); - connectContext = aConnectContext; - } - - public FileInfo getLastFileInfo() { - return fileInfo; - } - - /** - * A job to handle cancelation when trying to establish a socket connection. - * At this point we don't have a transfer job running yet, so we need a separate - * job to monitor for cancelation. - */ - protected class CancelHandler extends Job { - private boolean done = false; - - protected CancelHandler() { - super(Messages.FileTransport_cancelCheck); - setSystem(true); - } - - public IStatus run(IProgressMonitor jobMonitor) { - while (!done && !jobMonitor.isCanceled()) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - return Status.CANCEL_STATUS; - } - if (theMonitor != null && theMonitor.isCanceled()) - if (connectEvent != null) - connectEvent.cancel(); - } - return Status.OK_STATUS; - } - - protected void canceling() { - //wake up from sleep in run method - Thread t = getThread(); - if (t != null) - t.interrupt(); - } - - } - - public synchronized void handleTransferEvent(IFileTransferEvent event) { - if (event instanceof IFileTransferConnectStartEvent) { - // keep the connect event to be able to cancel the transfer - connectEvent = (IFileTransferConnectStartEvent) event; - cancelJob = new CancelHandler(); - //schedule with a delay to avoid the overhead of an extra job on a fast connection - cancelJob.schedule(500); - } else if (event instanceof IIncomingFileTransferReceiveStartEvent) { - //we no longer need the cancel handler because we are about to fork the transfer job - if (cancelJob != null) - cancelJob.cancel(); - IIncomingFileTransfer source = ((IIncomingFileTransferEvent) event).getSource(); - try { - FileInfo fi = new FileInfo(); - Date lastModified = source.getRemoteLastModified(); - if (lastModified != null) - fi.setLastModified(lastModified.getTime()); - fi.setName(source.getRemoteFileName()); - fi.setSize(source.getFileLength()); - fileInfo = fi; - - ((IIncomingFileTransferReceiveStartEvent) event).receive(theOutputStream, this); - } catch (IOException e) { - exception = e; - return; - } - long fileLength = source.getFileLength(); - ProgressStatistics stats = new ProgressStatistics(requestUri, source.getRemoteFileName(), fileLength); - setStatistics(stats); - - if (theMonitor != null) { - theMonitor.beginTask(null, 1000); - monitorStarted = true; - theMonitor.subTask(stats.report()); - lastStatsCount = 0; - lastProgressCount = 0; - } - onStart(source); - } else if (event instanceof IIncomingFileTransferReceiveDataEvent) { - IIncomingFileTransfer source = ((IIncomingFileTransferEvent) event).getSource(); - if (theMonitor != null) { - if (theMonitor.isCanceled()) { - source.cancel(); - return; - } - - long br = source.getBytesReceived(); - long count = br - lastStatsCount; - lastStatsCount = br; - ProgressStatistics stats = getStatistics(); - if (stats != null) { - stats.increase(count); - fileInfo.setAverageSpeed(stats.getAverageSpeed()); - if (stats.shouldReport()) { - count = br - lastProgressCount; - lastProgressCount = br; - theMonitor.subTask(stats.report()); - theMonitor.worked((int) (1000 * count / stats.getTotal())); - } - } - } - onData(source); - } else if (event instanceof IIncomingFileTransferReceiveDoneEvent) { - if (closeStreamWhenFinished) - hardClose(theOutputStream); - - if (exception == null) - exception = ((IIncomingFileTransferReceiveDoneEvent) event).getException(); - onDone(((IIncomingFileTransferReceiveDoneEvent) event).getSource()); - } - } - - public InputStream read(URI url, final IProgressMonitor monitor) throws CoreException, FileNotFoundException, AuthenticationFailedException, JREHttpClientRequiredException { - final PipedInputStream input = new PipedInputStream(); - PipedOutputStream output; - try { - output = new PipedOutputStream(input); - } catch (IOException e) { - throw RepositoryStatusHelper.wrap(e); - } - RepositoryTracing.debug("Downloading {0}", url); //$NON-NLS-1$ - - sendRetrieveRequest(url, output, null, true, monitor); - - return new InputStream() { - public int available() throws IOException { - checkException(); - return input.available(); - } - - public void close() throws IOException { - hardClose(input); - checkException(); - } - - public void mark(int readlimit) { - input.mark(readlimit); - } - - public boolean markSupported() { - return input.markSupported(); - } - - public int read() throws IOException { - checkException(); - return input.read(); - } - - public int read(byte b[]) throws IOException { - checkException(); - return input.read(b); - } - - public int read(byte b[], int off, int len) throws IOException { - checkException(); - return input.read(b, off, len); - } - - public void reset() throws IOException { - checkException(); - input.reset(); - } - - public long skip(long n) throws IOException { - checkException(); - return input.skip(n); - } - - private void checkException() throws IOException { - if (getException() == null) - return; - - IOException e; - Throwable t = RepositoryStatusHelper.unwind(getException()); - if (t instanceof IOException) - e = (IOException) t; - else { - if (t instanceof UserCancelledException) { - Throwable cause = t; - t = new OperationCanceledException(t.getMessage()); - t.initCause(cause); - } - e = new IOException(t.getMessage()); - e.initCause(t); - } - throw e; - } - }; - } - - public void readInto(URI uri, OutputStream anOutputStream, IProgressMonitor monitor) // - throws CoreException, FileNotFoundException, AuthenticationFailedException, JREHttpClientRequiredException { - readInto(uri, anOutputStream, -1, monitor); - } - - public boolean belongsTo(Object family) { - return family == this; - } - - public void readInto(URI uri, OutputStream anOutputStream, long startPos, IProgressMonitor monitor) // - throws CoreException, FileNotFoundException, AuthenticationFailedException, JREHttpClientRequiredException { - if (monitor == null) - monitor = new NullProgressMonitor(); - try { - sendRetrieveRequest(uri, anOutputStream, (startPos != -1 ? new DownloadRange(startPos) : null), false, monitor); - Job.getJobManager().join(this, new SuppressBlockedMonitor(monitor, 0)); - if (monitor.isCanceled() && connectEvent != null) - connectEvent.cancel(); - // check and throw exception if received in callback - checkException(uri, connectionRetryCount); - } catch (InterruptedException e) { - monitor.setCanceled(true); - throw new OperationCanceledException(); - } finally { - // kill the cancelJob, if there is one - if (cancelJob != null) { - cancelJob.cancel(); - cancelJob = null; - } - // If monitor was never started, make sure it is balanced - if (!monitorStarted) - monitor.beginTask(null, 1); - monitorStarted = false; - monitor.done(); - } - } - - protected void sendRetrieveRequest(URI uri, OutputStream outputStream, DownloadRange range, boolean closeStreamOnFinish, // - IProgressMonitor monitor) throws CoreException, FileNotFoundException, AuthenticationFailedException, JREHttpClientRequiredException { - - IRetrieveFileTransferFactory factory = Activator.getDefault().getRetrieveFileTransferFactory(); - if (factory == null) { - throw RepositoryStatusHelper.fromMessage(Messages.ecf_configuration_error); - } - IRetrieveFileTransferContainerAdapter adapter = factory.newInstance(); - - adapter.setConnectContextForAuthentication(connectContext); - - this.exception = null; - this.closeStreamWhenFinished = closeStreamOnFinish; - this.fileInfo = null; - this.statistics = null; - this.lastProgressCount = 0L; - this.lastStatsCount = 0L; - this.theMonitor = monitor; - this.monitorStarted = false; - this.theOutputStream = outputStream; - this.requestUri = uri; - - for (int retryCount = 0;; retryCount++) { - if (monitor != null && monitor.isCanceled()) - throw new OperationCanceledException(); - - try { - IFileID fileID = FileIDFactory.getDefault().createFileID(adapter.getRetrieveNamespace(), uri.toString()); - if (range != null) - adapter.sendRetrieveRequest(fileID, range, this, null); - else - adapter.sendRetrieveRequest(fileID, this, null); - } catch (IncomingFileTransferException e) { - exception = e; - } catch (FileCreateException e) { - exception = e; - } catch (Throwable t) { - if (exception != null) - exception.printStackTrace(); - } - if (checkException(uri, retryCount)) - break; - } - } - - /** - * Utility method to check exception condition and determine if retry should be done. - * If there was an exception it is translated into one of the specified exceptions and thrown. - * - * @param uri the URI being read - used for logging purposes - * @param attemptCounter - the current attempt number (start with 0) - * @return true if the exception is an IOException and attemptCounter < connectionRetryCount, false otherwise - * @throws CoreException - * @throws FileNotFoundException - * @throws AuthenticationFailedException - */ - private boolean checkException(URI uri, int attemptCounter) throws CoreException, FileNotFoundException, AuthenticationFailedException, JREHttpClientRequiredException { - // note that 'exception' could have been captured in a callback - if (exception != null) { - // check if HTTP client needs to be changed - RepositoryStatusHelper.checkJREHttpClientRequired(exception); - - // if this is an 'authentication failure' - it is not meaningful to continue - RepositoryStatusHelper.checkPermissionDenied(exception); - - // if this is a 'file not found' - it is not meaningful to continue - RepositoryStatusHelper.checkFileNotFound(exception, uri); - - Throwable t = RepositoryStatusHelper.unwind(exception); - if (t instanceof CoreException) - throw RepositoryStatusHelper.unwindCoreException((CoreException) t); - - // not meaningful to try 'timeout again' - if a server is that busy, we - // need to wait for quite some time before retrying- it is not likely it is - // just a temporary network thing. - if (t instanceof SocketTimeoutException) - throw RepositoryStatusHelper.wrap(t); - - if (t instanceof IOException && attemptCounter < connectionRetryCount) { - // TODO: Retry only certain exceptions or filter out - // some exceptions not worth retrying - // - exception = null; - try { - LogHelper.log(new Status(IStatus.WARNING, Activator.ID, NLS.bind(Messages.connection_to_0_failed_on_1_retry_attempt_2, new String[] {uri.toString(), t.getMessage(), String.valueOf(attemptCounter)}), t)); - - Thread.sleep(connectionRetryDelay); - return false; - } catch (InterruptedException e) { - /* ignore */ - } - } - throw RepositoryStatusHelper.wrap(exception); - } - return true; - } - - protected Exception getException() { - return exception; - } - - /** - * Closes input and output streams - * @param aStream - */ - public static void hardClose(Object aStream) { - if (aStream != null) { - try { - if (aStream instanceof OutputStream) - ((OutputStream) aStream).close(); - else if (aStream instanceof InputStream) - ((InputStream) aStream).close(); - } catch (IOException e) { /* ignore */ - } - } - } - - private static class DownloadRange implements IFileRangeSpecification { - - private long startPosition; - - public DownloadRange(long startPos) { - startPosition = startPos; - } - - public long getEndPosition() { - return -1; - } - - public long getStartPosition() { - return startPosition; - } - - } - - private void onDone(IIncomingFileTransfer source) { - if (testProbe != null) - testProbe.onDone(this, source, theMonitor); - } - - private void onStart(IIncomingFileTransfer source) { - if (testProbe != null) - testProbe.onStart(this, source, theMonitor); - } - - private void onData(IIncomingFileTransfer source) { - if (testProbe != null) - testProbe.onData(this, source, theMonitor); - } - - /** - * Sets a testing probe that can intercept events on the file reader for testing purposes. - * This method should only ever be called from automated test suites. - */ - public static void setTestProbe(IFileReaderProbe probe) { - testProbe = probe; - } - - /** - * Sets the progress statistics. This method is synchronized because the field - * is accessed from both the transfer thread and the thread initiating the transfer - * and we need to ensure field values are consistent across threads. - * - * @param statistics the statistics to set, or <code>null</code> - */ - private synchronized void setStatistics(ProgressStatistics statistics) { - this.statistics = statistics; - } - - /** - * Returns the progress statistics. This method is synchronized because the field - * is accessed from both the transfer thread and the thread initiating the transfer - * and we need to ensure field values are consistent across threads. - * - * @return the statistics, or <code>null</code> - */ - private synchronized ProgressStatistics getStatistics() { - return statistics; - } - - /** - * An interface to allow automated tests to hook into file reader events - * @see #setTestProbe - */ - public interface IFileReaderProbe { - public void onStart(FileReader reader, IIncomingFileTransfer source, IProgressMonitor monitor); - - public void onData(FileReader reader, IIncomingFileTransfer source, IProgressMonitor monitor); - - public void onDone(FileReader reader, IIncomingFileTransfer source, IProgressMonitor monitor); - } -} |