diff --git a/team/bundles/org.eclipse.team.core/META-INF/MANIFEST.MF b/team/bundles/org.eclipse.team.core/META-INF/MANIFEST.MF index c563e3b9c3f..7c0997e0e1f 100644 --- a/team/bundles/org.eclipse.team.core/META-INF/MANIFEST.MF +++ b/team/bundles/org.eclipse.team.core/META-INF/MANIFEST.MF @@ -76,12 +76,6 @@ Export-Package: org.eclipse.team.core; org.eclipse.team.cvs.ui, org.eclipse.team.ui, org.eclipse.team.tests.core", - org.eclipse.team.internal.core.streams; - x-friends:="org.eclipse.team.cvs.core, - org.eclipse.team.cvs.ssh2, - org.eclipse.team.cvs.ui, - org.eclipse.team.ui, - org.eclipse.team.tests.core", org.eclipse.team.internal.core.subscribers; x-friends:="org.eclipse.team.cvs.core, org.eclipse.team.cvs.ssh2, diff --git a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java index 4ca8fa91ccc..84f5b39acd2 100644 --- a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java +++ b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/Messages.java @@ -49,11 +49,6 @@ public class Messages extends NLS { public static String SubscriberDiffTreeEventHandler_0; public static String Team_readError; - public static String PollingInputStream_readTimeout; - public static String PollingInputStream_closeTimeout; - public static String PollingOutputStream_writeTimeout; - public static String PollingOutputStream_closeTimeout; - public static String TimeoutOutputStream_cannotWriteToStream; public static String RemoteSyncElement_delimit; public static String RemoteSyncElement_insync; diff --git a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties index 3c4d13e9527..183308cb640 100644 --- a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties +++ b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/messages.properties @@ -34,12 +34,6 @@ RepositoryProvider_toString={0}:{1} Team_readError=An error occurred reading the state file ''{0}'' -PollingInputStream_readTimeout=Timeout while reading from input stream -PollingInputStream_closeTimeout=Timeout while closing input stream -PollingOutputStream_writeTimeout=Timeout while writing to output stream -PollingOutputStream_closeTimeout=Timeout while closing output stream -TimeoutOutputStream_cannotWriteToStream=Cannot write to output stream - RemoteSyncElement_delimit=[{0}] RemoteSyncElement_insync=in-sync RemoteSyncElement_conflicting=conflicting diff --git a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/CRLFtoLFInputStream.java b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/CRLFtoLFInputStream.java deleted file mode 100644 index b75d537d950..00000000000 --- a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/CRLFtoLFInputStream.java +++ /dev/null @@ -1,171 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.team.internal.core.streams; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; - -/** - * Converts CR/LFs in the underlying input stream to LF. - * - * Supports resuming partially completed operations after an InterruptedIOException - * if the underlying stream does. Check the bytesTransferred field to determine how - * much of the operation completed; conversely, at what point to resume. - */ -public class CRLFtoLFInputStream extends FilterInputStream { - private boolean pendingByte = false; - private int lastByte = -1; - - /** - * Creates a new filtered input stream. - * @param in the underlying input stream - */ - public CRLFtoLFInputStream(InputStream in) { - super(in); - } - - /** - * Wraps the underlying stream's method. - * Translates CR/LF sequences to LFs transparently. - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public int read() throws IOException { - if (! pendingByte) { - lastByte = in.read(); // ok if this throws - pendingByte = true; // remember the byte in case we throw an exception later on - } - if (lastByte == '\r') { - lastByte = in.read(); // ok if this throws - if (lastByte != '\n') { - if (lastByte == -1) { - pendingByte = false; - } - return '\r'; // leaves the byte pending for later - } - } - pendingByte = false; - return lastByte; - } - - /** - * Wraps the underlying stream's method. - * Translates CR/LF sequences to LFs transparently. - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred may be non-zero - * @throws IOException if an i/o error occurs - */ - @Override - public int read(byte[] buffer, int off, int len) throws IOException { - // handle boundary cases cleanly - if (len == 0) { - return 0; - } else if (len == 1) { - int b = read(); - if (b == -1) { - return -1; - } - buffer[off] = (byte) b; - return 1; - } - // read some bytes from the stream - // prefix with pending byte from last read if any - int count = 0; - if (pendingByte) { - buffer[off] = (byte) lastByte; - pendingByte = false; - count = 1; - } - InterruptedIOException iioe = null; - try { - len = in.read(buffer, off + count, len - count); - if (len == -1) { - return (count == 0) ? -1 : count; - } - } catch (InterruptedIOException e) { - len = e.bytesTransferred; - iioe = e; - } - count += len; - // strip out CR's in CR/LF pairs - // pendingByte will be true iff previous byte was a CR - int j = off; - for (int i = off; i < off + count; ++i) { // invariant: j <= i - lastByte = buffer[i]; - if (lastByte == '\r') { - if (pendingByte) { - buffer[j++] = '\r'; // write out orphan CR - } else { - pendingByte = true; - } - } else { - if (pendingByte) { - if (lastByte != '\n') { - buffer[j++] = '\r'; // if LF, don't write the CR - } - pendingByte = false; - } - buffer[j++] = (byte) lastByte; - } - } - if (iioe != null) { - iioe.bytesTransferred = j - off; - throw iioe; - } - return j - off; - } - - /** - * Calls read() to skip the specified number of bytes - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred may be non-zero - * @throws IOException if an i/o error occurs - */ - @Override - public long skip(long count) throws IOException { - int actualCount = 0; // assumes count < Integer.MAX_INT - try { - while (count-- > 0 && read() != -1) { - actualCount++; // skip the specified number of bytes - } - return actualCount; - } catch (InterruptedIOException e) { - e.bytesTransferred = actualCount; - throw e; - } - } - - /** - * Wraps the underlying stream's method. - * Returns the number of bytes that can be read without blocking; accounts for - * possible translation of CR/LF sequences to LFs in these bytes. - * @throws IOException if an i/o error occurs - */ - @Override - public int available() throws IOException { - return in.available() / 2; // we can guarantee at least this amount after contraction - } - - /** - * Mark is not supported by the wrapper even if the underlying stream does, returns false. - */ - @Override - public boolean markSupported() { - return false; - } -} diff --git a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/LFtoCRLFInputStream.java b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/LFtoCRLFInputStream.java deleted file mode 100644 index a36b8edb1a4..00000000000 --- a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/LFtoCRLFInputStream.java +++ /dev/null @@ -1,160 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.team.internal.core.streams; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; - -/** - * Converts LFs in the underlying input stream to CR/LF. - * - * Supports resuming partially completed operations after an InterruptedIOException - * if the underlying stream does. Check the bytesTransferred field to determine how - * much of the operation completed; conversely, at what point to resume. - */ -public class LFtoCRLFInputStream extends FilterInputStream { - private boolean mustReturnLF = false; - - /** - * Creates a new filtered input stream. - * @param in the underlying input stream - */ - public LFtoCRLFInputStream(InputStream in) { - super(in); - } - - /** - * Wraps the underlying stream's method. - * Translates LFs to CR/LF sequences transparently. - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public int read() throws IOException { - if (mustReturnLF) { - mustReturnLF = false; - return '\n'; - } - int b = in.read(); // ok if this throws - if (b == '\n') { - mustReturnLF = true; - b = '\r'; - } - return b; - } - - /** - * Wraps the underlying stream's method. - * Translates LFs to CR/LF sequences transparently. - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred may be non-zero - * @throws IOException if an i/o error occurs - */ - @Override - public int read(byte[] buffer, int off, int len) throws IOException { - // handle boundary cases cleanly - if (len == 0) { - return 0; - } else if (len == 1) { - int b = read(); - if (b == -1) { - return -1; - } - buffer[off] = (byte) b; - return 1; - } - // prefix with remembered \n from last read, but don't expand it a second time - int count = 0; - if (mustReturnLF) { - mustReturnLF = false; - buffer[off++] = '\n'; - --len; - count = 1; - if (len < 2) { - return count; // is there still enough room to expand more? - } - } - // read some bytes from the stream into the back half of the buffer - // this guarantees that there is always room to expand - len /= 2; - int j = off + len; - InterruptedIOException iioe = null; - try { - len = in.read(buffer, j, len); - if (len == -1) { - return (count == 0) ? -1 : count; - } - } catch (InterruptedIOException e) { - len = e.bytesTransferred; - iioe = e; - } - count += len; - // copy bytes from the middle to the front of the array, expanding LF->CR/LF - while (len-- > 0) { - byte b = buffer[j++]; - if (b == '\n') { - buffer[off++] = '\r'; - count++; - } - buffer[off++] = b; - } - if (iioe != null) { - iioe.bytesTransferred = count; - throw iioe; - } - return count; - } - - /** - * Calls read() to skip the specified number of bytes - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred may be non-zero - * @throws IOException if an i/o error occurs - */ - @Override - public long skip(long count) throws IOException { - int actualCount = 0; // assumes count < Integer.MAX_INT - try { - while (count-- > 0 && read() != -1) { - actualCount++; // skip the specified number of bytes - } - return actualCount; - } catch (InterruptedIOException e) { - e.bytesTransferred = actualCount; - throw e; - } - } - - /** - * Wraps the underlying stream's method. - * Returns the number of bytes that can be read without blocking; accounts for - * possible translation of LFs to CR/LF sequences in these bytes. - * @throws IOException if an i/o error occurs - */ - @Override - public int available() throws IOException { - return in.available(); // we can guarantee at least this amount after expansion - } - - /** - * Mark is not supported by the wrapper even if the underlying stream does, returns false. - */ - @Override - public boolean markSupported() { - return false; - } -} diff --git a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingInputStream.java b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingInputStream.java deleted file mode 100644 index 22a8a951223..00000000000 --- a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingInputStream.java +++ /dev/null @@ -1,236 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.team.internal.core.streams; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.team.internal.core.Messages; -import org.eclipse.team.internal.core.Policy; -import org.eclipse.team.internal.core.TeamPlugin; - -/** - * Polls a progress monitor periodically and handles timeouts over extended durations. - * For this class to be effective, a high numAttempts should be specified, and the - * underlying stream should time out frequently on reads (every second or so). - * - * Supports resuming partially completed operations after an InterruptedIOException - * if the underlying stream does. Check the bytesTransferred field to determine how - * much of the operation completed; conversely, at what point to resume. - */ -public class PollingInputStream extends FilterInputStream { - private final int numAttempts; - private final IProgressMonitor monitor; - private boolean cancellable; - - /** - * Creates a new polling input stream. - * @param in the underlying input stream - * @param numAttempts the number of attempts before issuing an InterruptedIOException, - * if 0, retries indefinitely until canceled - * @param monitor the progress monitor to be polled for cancellation - */ - public PollingInputStream(InputStream in, int numAttempts, IProgressMonitor monitor) { - super(in); - this.numAttempts = numAttempts; - this.monitor = monitor; - this.cancellable = true; - } - - /** - * Wraps the underlying stream's method. - * It may be important to wait for an input stream to be closed because it - * holds an implicit lock on a system resource (such as a file) while it is - * open. Closing a stream may take time if the underlying stream is still - * servicing a previous request. - * @throws OperationCanceledException if the progress monitor is canceled - * @throws InterruptedIOException if the underlying operation times out numAttempts times - */ - @Override - public void close() throws InterruptedIOException { - int attempts = 0; - try { - readPendingInput(); - } catch (IOException e) { - // We shouldn't get an exception when we're getting the available input. - // If we do, just log it so we can close. - TeamPlugin.log(IStatus.ERROR, e.getMessage(), e); - } finally { - boolean stop = false; - while (!stop) { - try { - if (in != null) { - in.close(); - } - stop = true; - } catch (InterruptedIOException e) { - if (checkCancellation()) { - throw new OperationCanceledException(); - } - if (++attempts == numAttempts) { - throw new InterruptedIOException(Messages.PollingInputStream_closeTimeout); - } - if (Policy.DEBUG_STREAMS) { - System.out.println("close retry=" + attempts); //$NON-NLS-1$ - } - } catch (IOException e) { - // ignore it - see https://bugs.eclipse.org/bugs/show_bug.cgi?id=203423#c10 - } - } - } - } - - /** - * Wraps the underlying stream's method. - * @return the next byte of data, or -1 if the end of the stream is reached. - * @throws OperationCanceledException if the progress monitor is canceled - * @throws InterruptedIOException if the underlying operation times out numAttempts times - * and no data was received, bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public int read() throws IOException { - int attempts = 0; - for (;;) { - if (checkCancellation()) { - throw new OperationCanceledException(); - } - try { - return in.read(); - } catch (InterruptedIOException e) { - if (++attempts == numAttempts) { - throw new InterruptedIOException(Messages.PollingInputStream_readTimeout); - } - if (Policy.DEBUG_STREAMS) { - System.out.println("read retry=" + attempts); //$NON-NLS-1$ - } - } - } - } - - /** - * Wraps the underlying stream's method. - * @param buffer - the buffer into which the data is read. - * @param off - the start offset of the data. - * @param len - the maximum number of bytes read. - * @return the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached. - * @throws OperationCanceledException if the progress monitor is canceled - * @throws InterruptedIOException if the underlying operation times out numAttempts times - * and no data was received, bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public int read(byte[] buffer, int off, int len) throws IOException { - int attempts = 0; - for (;;) { - if (checkCancellation()) { - throw new OperationCanceledException(); - } - try { - return in.read(buffer, off, len); - } catch (InterruptedIOException e) { - if (e.bytesTransferred != 0) { - return e.bytesTransferred; // keep partial transfer - } - if (++attempts == numAttempts) { - throw new InterruptedIOException(Messages.PollingInputStream_readTimeout); - } - if (Policy.DEBUG_STREAMS) { - System.out.println("read retry=" + attempts); //$NON-NLS-1$ - } - } - } - } - - /** - * Wraps the underlying stream's method. - * @param count - the number of bytes to be skipped. - * @return the actual number of bytes skipped. - * @throws OperationCanceledException if the progress monitor is canceled - * @throws InterruptedIOException if the underlying operation times out numAttempts times - * and no data was received, bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public long skip(long count) throws IOException { - int attempts = 0; - for (;;) { - if (checkCancellation()) { - throw new OperationCanceledException(); - } - try { - return in.skip(count); - } catch (InterruptedIOException e) { - if (e.bytesTransferred != 0) { - return e.bytesTransferred; // keep partial transfer - } - if (++attempts == numAttempts) { - throw new InterruptedIOException(Messages.PollingInputStream_readTimeout); - } - if (Policy.DEBUG_STREAMS) { - System.out.println("read retry=" + attempts); //$NON-NLS-1$ - } - } - } - } - - /** - * Reads any pending input from the input stream so that - * the stream can savely be closed. - */ - protected void readPendingInput() throws IOException { - byte[] buffer= new byte[2048]; - while (true) { - int available = in.available(); - if (available < 1) { - break; - } - if (available > buffer.length) { - available = buffer.length; - } - if (in.read(buffer, 0, available) < 1) { - break; - } - } - } - - /** - * Called to set whether cancellation will be checked by this stream. Turning cancellation checking - * off can be very useful for protecting critical portions of a protocol that shouldn't be interrupted. - * For example, it is often necessary to protect login sequences. - * @param cancellable a flag controlling whether this stream will check for cancellation. - */ - public void setIsCancellable(boolean cancellable) { - this.cancellable = cancellable; - } - - /** - * Checked whether the monitor for this stream has been cancelled. If the cancellable - * flag is false then the monitor is never cancelled. - * @return true if the monitor has been cancelled and false - * otherwise. - */ - private boolean checkCancellation() { - if(cancellable) { - return monitor.isCanceled(); - } else { - return false; - } - } -} diff --git a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingOutputStream.java b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingOutputStream.java deleted file mode 100644 index dbc52edf110..00000000000 --- a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/PollingOutputStream.java +++ /dev/null @@ -1,216 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.team.internal.core.streams; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.io.OutputStream; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.OperationCanceledException; -import org.eclipse.team.internal.core.Messages; -import org.eclipse.team.internal.core.Policy; - -/** - * Polls a progress monitor periodically and handles timeouts over extended durations. - * For this class to be effective, a high numAttempts should be specified, and the - * underlying stream should time out frequently on writes (every second or so). - * - * Supports resuming partially completed operations after an InterruptedIOException - * if the underlying stream does. Check the bytesTransferred field to determine how - * much of the operation completed; conversely, at what point to resume. - */ -public class PollingOutputStream extends FilterOutputStream { - private final int numAttempts; - private final IProgressMonitor monitor; - private boolean cancellable; - - /** - * Creates a new polling output stream. - * @param out the underlying output stream - * @param numAttempts the number of attempts before issuing an InterruptedIOException, - * if 0, retries indefinitely until canceled - * @param monitor the progress monitor to be polled for cancellation - */ - public PollingOutputStream(OutputStream out, int numAttempts, IProgressMonitor monitor) { - super(out); - this.numAttempts = numAttempts; - this.monitor = monitor; - this.cancellable = true; - } - - /** - * Wraps the underlying stream's method. - * @throws OperationCanceledException if the progress monitor is canceled - * @throws InterruptedIOException if the underlying operation times out numAttempts times - * and no data was sent, bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public void write(int b) throws IOException { - int attempts = 0; - for (;;) { - if (checkCancellation()) { - throw new OperationCanceledException(); - } - try { - out.write(b); - return; - } catch (InterruptedIOException e) { - if (++attempts == numAttempts) { - throw new InterruptedIOException(Messages.PollingOutputStream_writeTimeout); - } - if (Policy.DEBUG_STREAMS) { - System.out.println("write retry=" + attempts); //$NON-NLS-1$ - } - } - } - } - - /** - * Wraps the underlying stream's method. - * @throws OperationCanceledException if the progress monitor is canceled - * @throws InterruptedIOException if the underlying operation times out numAttempts times, - * bytesTransferred will reflect the number of bytes sent - * @throws IOException if an i/o error occurs - */ - @Override - public void write(byte[] buffer, int off, int len) throws IOException { - int count = 0; - int attempts = 0; - for (;;) { - if (checkCancellation()) { - throw new OperationCanceledException(); - } - try { - out.write(buffer, off, len); - return; - } catch (InterruptedIOException e) { - int amount = e.bytesTransferred; - if (amount != 0) { // keep partial transfer - len -= amount; - if (len <= 0) { - return; - } - off += amount; - count += amount; - attempts = 0; // made some progress, don't time out quite yet - } - if (++attempts == numAttempts) { - e = new InterruptedIOException(Messages.PollingOutputStream_writeTimeout); - e.bytesTransferred = count; - throw e; - } - if (Policy.DEBUG_STREAMS) { - System.out.println("write retry=" + attempts); //$NON-NLS-1$ - } - } - } - } - - /** - * Wraps the underlying stream's method. - * @throws OperationCanceledException if the progress monitor is canceled - * @throws InterruptedIOException if the underlying operation times out numAttempts times, - * bytesTransferred will reflect the number of bytes sent - * @throws IOException if an i/o error occurs - */ - @Override - public void flush() throws IOException { - int count = 0; - int attempts = 0; - for (;;) { - if (checkCancellation()) { - throw new OperationCanceledException(); - } - try { - out.flush(); - return; - } catch (InterruptedIOException e) { - int amount = e.bytesTransferred; - if (amount != 0) { // keep partial transfer - count += amount; - attempts = 0; // made some progress, don't time out quite yet - } - if (++attempts == numAttempts) { - e = new InterruptedIOException(Messages.PollingOutputStream_writeTimeout); - e.bytesTransferred = count; - throw e; - } - if (Policy.DEBUG_STREAMS) { - System.out.println("write retry=" + attempts); //$NON-NLS-1$ - } - } - } - } - - /** - * Calls flush() then close() on the underlying stream. - * @throws OperationCanceledException if the progress monitor is canceled - * @throws InterruptedIOException if the underlying operation times out numAttempts times, - * bytesTransferred will reflect the number of bytes sent during the flush() - * @throws IOException if an i/o error occurs - */ - @Override - public void close() throws IOException { - int attempts = numAttempts - 1; // fail fast if flush() does times out - try { - out.flush(); - attempts = 0; - } finally { - boolean stop = false; - while (!stop) { - try { - out.close(); - stop = true; - } catch (InterruptedIOException e) { - if (checkCancellation()) { - throw new OperationCanceledException(); - } - if (++attempts == numAttempts) { - throw new InterruptedIOException(Messages.PollingOutputStream_closeTimeout); - } - if (Policy.DEBUG_STREAMS) { - System.out.println("close retry=" + attempts); //$NON-NLS-1$ - } - } - } - } - } - - /** - * Called to set whether cancellation will be checked by this stream. Turning cancellation checking - * off can be very useful for protecting critical portions of a protocol that shouldn't be interrupted. - * For example, it is often necessary to protect login sequences. - * @param cancellable a flag controlling whether this stream will check for cancellation. - */ - public void setIsCancellable(boolean cancellable) { - this.cancellable = cancellable; - } - - /** - * Checked whether the monitor for this stream has been cancelled. If the cancellable - * flag is false then the monitor is never cancelled. - * @return true if the monitor has been cancelled and false - * otherwise. - */ - private boolean checkCancellation() { - if(cancellable) { - return monitor.isCanceled(); - } else { - return false; - } - } -} diff --git a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/ProgressMonitorInputStream.java b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/ProgressMonitorInputStream.java deleted file mode 100644 index b02fb3a7205..00000000000 --- a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/ProgressMonitorInputStream.java +++ /dev/null @@ -1,149 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.team.internal.core.streams; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; - -import org.eclipse.core.runtime.IProgressMonitor; - -/** - * Updates a progress monitor as bytes are read from the input stream. - * Also starts a background thread to provide responsive cancellation on read(). - * - * Supports resuming partially completed operations after an InterruptedIOException - * if the underlying stream does. Check the bytesTransferred field to determine how - * much of the operation completed; conversely, at what point to resume. - */ -public abstract class ProgressMonitorInputStream extends FilterInputStream { - private final IProgressMonitor monitor; - private final int updateIncrement; - private final long bytesTotal; - private long bytesRead = 0; - private long lastUpdate = -1; - private long nextUpdate = 0; - - /** - * Creates a progress monitoring input stream. - * @param in the underlying input stream - * @param bytesTotal the number of bytes to read in total (passed to updateMonitor()) - * @param updateIncrement the number of bytes read between updates - * @param monitor the progress monitor - */ - public ProgressMonitorInputStream(InputStream in, long bytesTotal, int updateIncrement, IProgressMonitor monitor) { - super(in); - this.bytesTotal = bytesTotal; - this.updateIncrement = updateIncrement; - this.monitor = monitor; - update(true); - } - - protected abstract void updateMonitor(long bytesRead, long size, IProgressMonitor monitor); - - /** - * Wraps the underlying stream's method. - * Updates the progress monitor to the final number of bytes read. - * @throws IOException if an i/o error occurs - */ - @Override - public void close() throws IOException { - try { - in.close(); - } finally { - update(true); - } - } - - /** - * Wraps the underlying stream's method. - * Updates the progress monitor if the next update increment has been reached. - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public int read() throws IOException { - int b = in.read(); - if (b != -1) { - bytesRead += 1; - update(false); - } - return b; - } - - /** - * Wraps the underlying stream's method. - * Updates the progress monitor if the next update increment has been reached. - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred may be non-zero - * @throws IOException if an i/o error occurs - */ - @Override - public int read(byte[] buffer, int offset, int length) throws IOException { - try { - int count = in.read(buffer, offset, length); - if (count != -1) { - bytesRead += count; - update(false); - } - return count; - } catch (InterruptedIOException e) { - bytesRead += e.bytesTransferred; - update(false); - throw e; - } - } - - /** - * Wraps the underlying stream's method. - * Updates the progress monitor if the next update increment has been reached. - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred may be non-zero - * @throws IOException if an i/o error occurs - */ - @Override - public long skip(long amount) throws IOException { - try { - long count = in.skip(amount); - bytesRead += count; - update(false); - return count; - } catch (InterruptedIOException e) { - bytesRead += e.bytesTransferred; - update(false); - throw e; - } - } - - /** - * Mark is not supported by the wrapper even if the underlying stream does, returns false. - */ - @Override - public boolean markSupported() { - return false; - } - - private void update(boolean now) { - if (bytesRead >= nextUpdate || now) { - nextUpdate = bytesRead - (bytesRead % updateIncrement); - if (nextUpdate != lastUpdate) { - updateMonitor(nextUpdate, bytesTotal, monitor); - } - lastUpdate = nextUpdate; - nextUpdate += updateIncrement; - } - } -} diff --git a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/SizeConstrainedInputStream.java b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/SizeConstrainedInputStream.java deleted file mode 100644 index 9bc2a1b2616..00000000000 --- a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/SizeConstrainedInputStream.java +++ /dev/null @@ -1,161 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.team.internal.core.streams; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; - -import org.eclipse.core.runtime.OperationCanceledException; - -/** - * Simulates a stream that represents only a portion of the underlying stream. - * Will report EOF when this portion has been fully read and prevent further reads. - * The underlying stream is not closed on close(), but the remaining unread input - * may optionally be skip()'d. - * - * Supports resuming partially completed operations after an InterruptedIOException - * if the underlying stream does. Check the bytesTransferred field to determine how - * much of the operation completed; conversely, at what point to resume. - */ -public class SizeConstrainedInputStream extends FilterInputStream { - private final boolean discardOnClose; - private long bytesRemaining; - - /** - * Creates a size constrained input stream. - * @param in the underlying input stream, never actually closed by this filter - * @param size the maximum number of bytes of the underlying input stream that - * can be read through this filter - * @param discardOnClose if true, discards remaining unread bytes on close() - */ - public SizeConstrainedInputStream(InputStream in, long size, boolean discardOnClose) { - super(in); - this.bytesRemaining = size; - this.discardOnClose = discardOnClose; - } - - /** - * Prevents further reading from the stream but does not close the underlying stream. - * If discardOnClose, skip()'s over any remaining unread bytes in the constrained region. - * @throws IOException if an i/o error occurs - */ - @Override - public void close() throws IOException { - try { - if (discardOnClose) { - while (bytesRemaining != 0 && skip(bytesRemaining) != 0) { - ; - } - } - } catch (OperationCanceledException e) { - // The receiver is likely wrapping a PollingInputStream which could throw - // an OperationCanceledException on a skip. - // Since we're closing, just ignore the cancel and let the caller check the monitor - } finally { - bytesRemaining = 0; - } - } - - /** - * Wraps the underlying stream's method. - * Simulates an end-of-file condition if the end of the constrained region has been reached. - * @throws IOException if an i/o error occurs - */ - @Override - public int available() throws IOException { - int amount = in.available(); - if (amount > bytesRemaining) { - amount = (int) bytesRemaining; - } - return amount; - } - - /** - * Wraps the underlying stream's method. - * Simulates an end-of-file condition if the end of the constrained region has been reached. - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public int read() throws IOException { - if (bytesRemaining == 0) { - return -1; - } - int b = in.read(); - if (b != -1) { - bytesRemaining -= 1; - } - return b; - } - - /** - * Wraps the underlying stream's method. - * Simulates an end-of-file condition if the end of the constrained region has been reached. - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred may be non-zero - * @throws IOException if an i/o error occurs - */ - @Override - public int read(byte[] buffer, int offset, int length) throws IOException { - if (length > bytesRemaining) { - if (bytesRemaining == 0) { - return -1; - } - length = (int) bytesRemaining; - } - try { - int count = in.read(buffer, offset, length); - if (count != -1) { - bytesRemaining -= count; - } - return count; - } catch (InterruptedIOException e) { - bytesRemaining -= e.bytesTransferred; - throw e; - } - } - - /** - * Wraps the underlying stream's method. - * Simulates an end-of-file condition if the end of the constrained region has been reached. - * @throws InterruptedIOException if the operation was interrupted before all of the - * bytes specified have been skipped, bytesTransferred may be non-zero - * @throws IOException if an i/o error occurs - */ - @Override - public long skip(long amount) throws IOException { - if (amount > bytesRemaining) { - amount = bytesRemaining; - } - try { - long count = in.skip(amount); - bytesRemaining -= count; - return count; - } catch (InterruptedIOException e) { - bytesRemaining -= e.bytesTransferred; - throw e; - } - } - - /** - * Mark is not supported by the wrapper even if the underlying stream does, returns false. - */ - @Override - public boolean markSupported() { - return false; - } -} diff --git a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/TimeoutInputStream.java b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/TimeoutInputStream.java deleted file mode 100644 index 39b5485cf7e..00000000000 --- a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/TimeoutInputStream.java +++ /dev/null @@ -1,365 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.team.internal.core.streams; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; - -import org.eclipse.team.internal.core.Policy; - -/** - * Wraps an input stream that blocks indefinitely to simulate timeouts on read(), - * skip(), and close(). The resulting input stream is buffered and supports - * retrying operations that failed due to an InterruptedIOException. - * - * Supports resuming partially completed operations after an InterruptedIOException - * REGARDLESS of whether the underlying stream does unless the underlying stream itself - * generates InterruptedIOExceptions in which case it must also support resuming. - * Check the bytesTransferred field to determine how much of the operation completed; - * conversely, at what point to resume. - */ -public class TimeoutInputStream extends FilterInputStream { - // unsynchronized variables - private final long readTimeout; // read() timeout in millis - private final long closeTimeout; // close() timeout in millis, or -1 - - // requests for the thread (synchronized) - private boolean closeRequested = false; // if true, close requested - - // responses from the thread (synchronized) - private Thread thread; // if null, thread has terminated - private byte[] iobuffer; // circular buffer - private int head = 0; // points to first unread byte - private int length = 0; // number of remaining unread bytes - private IOException ioe = null; // if non-null, contains a pending exception - private boolean waitingForClose = false; // if true, thread is waiting for close() - - private boolean growWhenFull = false; // if true, buffer will grow when it is full - - /** - * Creates a timeout wrapper for an input stream. - * @param in the underlying input stream - * @param bufferSize the buffer size in bytes; should be large enough to mitigate - * Thread synchronization and context switching overhead - * @param readTimeout the number of milliseconds to block for a read() or skip() before - * throwing an InterruptedIOException; 0 blocks indefinitely - * @param closeTimeout the number of milliseconds to block for a close() before throwing - * an InterruptedIOException; 0 blocks indefinitely, -1 closes the stream in the background - */ - public TimeoutInputStream(InputStream in, int bufferSize, long readTimeout, long closeTimeout) { - super(in); - this.readTimeout = readTimeout; - this.closeTimeout = closeTimeout; - this.iobuffer = new byte[bufferSize]; - thread = new Thread((Runnable) this::runThread, "TimeoutInputStream");//$NON-NLS-1$ - thread.setDaemon(true); - thread.start(); - } - - public TimeoutInputStream(InputStream in, int bufferSize, long readTimeout, long closeTimeout, boolean growWhenFull) { - this(in, bufferSize, readTimeout, closeTimeout); - this.growWhenFull = growWhenFull; - } - - /** - * Wraps the underlying stream's method. - * It may be important to wait for a stream to actually be closed because it - * holds an implicit lock on a system resoure (such as a file) while it is - * open. Closing a stream may take time if the underlying stream is still - * servicing a previous request. - * @throws InterruptedIOException if the timeout expired - * @throws IOException if an i/o error occurs - */ - @Override - public void close() throws IOException { - Thread oldThread; - synchronized (this) { - if (thread == null) { - return; - } - oldThread = thread; - closeRequested = true; - thread.interrupt(); - checkError(); - } - if (closeTimeout == -1) { - return; - } - try { - oldThread.join(closeTimeout); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); // we weren't expecting to be interrupted - } - synchronized (this) { - checkError(); - if (thread != null) { - throw new InterruptedIOException(); - } - } - } - - /** - * Returns the number of unread bytes in the buffer. - * @throws IOException if an i/o error occurs - */ - @Override - public synchronized int available() throws IOException { - if (length == 0) { - checkError(); - } - return length > 0 ? length : 0; - } - - /** - * Reads a byte from the stream. - * @throws InterruptedIOException if the timeout expired and no data was received, - * bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public synchronized int read() throws IOException { - if (! syncFill()) { - return -1; // EOF reached - } - int b = iobuffer[head++] & 255; - if (head == iobuffer.length) { - head = 0; - } - length--; - notify(); - return b; - } - - /** - * Reads multiple bytes from the stream. - * @throws InterruptedIOException if the timeout expired and no data was received, - * bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public synchronized int read(byte[] buffer, int off, int len) throws IOException { - if (! syncFill()) { - return -1; // EOF reached - } - int pos = off; - if (len > length) { - len = length; - } - while (len-- > 0) { - buffer[pos++] = iobuffer[head++]; - if (head == iobuffer.length) { - head = 0; - } - length--; - } - notify(); - return pos - off; - } - - /** - * Skips multiple bytes in the stream. - * @throws InterruptedIOException if the timeout expired before all of the - * bytes specified have been skipped, bytesTransferred may be non-zero - * @throws IOException if an i/o error occurs - */ - @Override - public synchronized long skip(long count) throws IOException { - long amount = 0; - try { - do { - if (! syncFill()) { - break; // EOF reached - } - int skip = (int) Math.min(count - amount, length); - head = (head + skip) % iobuffer.length; - length -= skip; - amount += skip; - } while (amount < count); - } catch (InterruptedIOException e) { - e.bytesTransferred = (int) amount; // assumes amount < Integer.MAX_INT - throw e; - } - notify(); - return amount; - } - - /** - * Mark is not supported by the wrapper even if the underlying stream does, returns false. - */ - @Override - public boolean markSupported() { - return false; - } - - /** - * Waits for the buffer to fill if it is empty and the stream has not reached EOF. - * @return true if bytes are available, false if EOF has been reached - * @throws InterruptedIOException if EOF not reached but no bytes are available - */ - private boolean syncFill() throws IOException { - if (length != 0) { - return true; - } - checkError(); // check errors only after we have read all remaining bytes - if (waitingForClose) { - return false; - } - notify(); - try { - wait(readTimeout); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); // we weren't expecting to be interrupted - } - if (length != 0) { - return true; - } - checkError(); // check errors only after we have read all remaining bytes - if (waitingForClose) { - return false; - } - throw new InterruptedIOException(); - } - - /** - * If an exception is pending, throws it. - */ - private void checkError() throws IOException { - if (ioe != null) { - IOException e = ioe; - ioe = null; - throw e; - } - } - - /** - * Runs the thread in the background. - */ - private void runThread() { - try { - readUntilDone(); - } catch (IOException e) { - synchronized (this) { ioe = e; } - } finally { - waitUntilClosed(); - try { - in.close(); - } catch (IOException e) { - synchronized (this) { ioe = e; } - } finally { - synchronized (this) { - thread = null; - notify(); - } - } - } - } - - /** - * Waits until we have been requested to close the stream. - */ - private synchronized void waitUntilClosed() { - waitingForClose = true; - notify(); - while (! closeRequested) { - try { - wait(); - } catch (InterruptedException e) { - closeRequested = true; // alternate quit signal - } - } - } - - /** - * Reads bytes into the buffer until EOF, closed, or error. - */ - private void readUntilDone() throws IOException { - for (;;) { - int off, len; - synchronized (this) { - while (isBufferFull()) { - if (closeRequested) { - return; // quit signal - } - waitForRead(); - } - off = (head + length) % iobuffer.length; - len = ((head > off) ? head : iobuffer.length) - off; - } - int count; - try { - // the i/o operation might block without releasing the lock, - // so we do this outside of the synchronized block - count = in.read(iobuffer, off, len); - if (count == -1) { - return; // EOF encountered - } - } catch (InterruptedIOException e) { - count = e.bytesTransferred; // keep partial transfer - } - synchronized (this) { - length += count; - notify(); - } - } - } - - /* - * Wait for a read when the buffer is full (with the implication - * that space will become available in the buffer after the read - * takes place). - */ - private synchronized void waitForRead() { - try { - if (growWhenFull) { - // wait a second before growing to let reads catch up - wait(readTimeout); - } else { - wait(); - } - } catch (InterruptedException e) { - closeRequested = true; // alternate quit signal - } - // If the buffer is still full, give it a chance to grow - if (growWhenFull && isBufferFull()) { - growBuffer(); - } - } - - private synchronized void growBuffer() { - int newSize = 2 * iobuffer.length; - if (newSize > iobuffer.length) { - if (Policy.DEBUG_STREAMS) { - System.out.println("InputStream growing to " + newSize + " bytes"); //$NON-NLS-1$ //$NON-NLS-2$ - } - byte[] newBuffer = new byte[newSize]; - int pos = 0; - int len = length; - while (len-- > 0) { - newBuffer[pos++] = iobuffer[head++]; - if (head == iobuffer.length) { - head = 0; - } - } - iobuffer = newBuffer; - head = 0; - // length instance variable was not changed by this method - } - } - - private boolean isBufferFull() { - return length == iobuffer.length; - } -} diff --git a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/TimeoutOutputStream.java b/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/TimeoutOutputStream.java deleted file mode 100644 index 190c805f37d..00000000000 --- a/team/bundles/org.eclipse.team.core/src/org/eclipse/team/internal/core/streams/TimeoutOutputStream.java +++ /dev/null @@ -1,310 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.team.internal.core.streams; - -import java.io.BufferedOutputStream; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.io.OutputStream; - -import org.eclipse.team.internal.core.Messages; - -/** - * Wraps an output stream that blocks indefinitely to simulate timeouts on write(), - * flush(), and close(). The resulting output stream is buffered and supports - * retrying operations that failed due to an InterruptedIOException. - * - * Supports resuming partially completed operations after an InterruptedIOException - * REGARDLESS of whether the underlying stream does unless the underlying stream itself - * generates InterruptedIOExceptions in which case it must also support resuming. - * Check the bytesTransferred field to determine how much of the operation completed; - * conversely, at what point to resume. - */ -public class TimeoutOutputStream extends FilterOutputStream { - // unsynchronized variables - private final long writeTimeout; // write() timeout in millis - private final long closeTimeout; // close() timeout in millis, or -1 - - // requests for the thread (synchronized) - private final byte[] iobuffer; // circular buffer - private int head = 0; // points to first unwritten byte - private int length = 0; // number of remaining unwritten bytes - private boolean closeRequested = false; // if true, close requested - private boolean flushRequested = false; // if true, flush requested - - // responses from the thread (synchronized) - private Thread thread; - private boolean waitingForClose = false; // if true, the thread is waiting for close() - private IOException ioe = null; - - /** - * Creates a timeout wrapper for an output stream. - * @param out the underlying input stream - * @param bufferSize the buffer size in bytes; should be large enough to mitigate - * Thread synchronization and context switching overhead - * @param writeTimeout the number of milliseconds to block for a write() or flush() before - * throwing an InterruptedIOException; 0 blocks indefinitely - * @param closeTimeout the number of milliseconds to block for a close() before throwing - * an InterruptedIOException; 0 blocks indefinitely, -1 closes the stream in the background - */ - public TimeoutOutputStream(OutputStream out, int bufferSize, long writeTimeout, long closeTimeout) { - super(new BufferedOutputStream(out, bufferSize)); - this.writeTimeout = writeTimeout; - this.closeTimeout = closeTimeout; - this.iobuffer = new byte[bufferSize]; - thread = new Thread((Runnable) this::runThread, "TimeoutOutputStream");//$NON-NLS-1$ - thread.setDaemon(true); - thread.start(); - } - - /** - * Wraps the underlying stream's method. - * It may be important to wait for a stream to actually be closed because it - * holds an implicit lock on a system resoure (such as a file) while it is - * open. Closing a stream may take time if the underlying stream is still - * servicing a previous request. - * @throws InterruptedIOException if the timeout expired, bytesTransferred will - * reflect the number of bytes flushed from the buffer - * @throws IOException if an i/o error occurs - */ - @Override - public void close() throws IOException { - Thread oldThread; - synchronized (this) { - if (thread == null) { - return; - } - oldThread = thread; - closeRequested = true; - thread.interrupt(); - checkError(); - } - if (closeTimeout == -1) { - return; - } - try { - oldThread.join(closeTimeout); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); // we weren't expecting to be interrupted - } - synchronized (this) { - checkError(); - if (thread != null) { - throw new InterruptedIOException(); - } - } - } - - /** - * Writes a byte to the stream. - * @throws InterruptedIOException if the timeout expired and no data was sent, - * bytesTransferred will be zero - * @throws IOException if an i/o error occurs - */ - @Override - public synchronized void write(int b) throws IOException { - syncCommit(true); - iobuffer[(head + length) % iobuffer.length] = (byte) b; - length++; - notify(); - } - - /** - * Writes multiple bytes to the stream. - * @throws InterruptedIOException if the timeout expired, bytesTransferred will - * reflect the number of bytes sent - * @throws IOException if an i/o error occurs - */ - @Override - public synchronized void write(byte[] buffer, int off, int len) throws IOException { - int amount = 0; - try { - do { - syncCommit(true); - while (amount < len && length != iobuffer.length) { - iobuffer[(head + length) % iobuffer.length] = buffer[off++]; - length++; - amount++; - } - } while (amount < len); - } catch (InterruptedIOException e) { - e.bytesTransferred = amount; - throw e; - } - notify(); - } - - /** - * Flushes the stream. - * @throws InterruptedIOException if the timeout expired, bytesTransferred will - * reflect the number of bytes flushed from the buffer - * @throws IOException if an i/o error occurs - */ - @Override - public synchronized void flush() throws IOException { - int oldLength = length; - flushRequested = true; - try { - syncCommit(false); - } catch (InterruptedIOException e) { - e.bytesTransferred = oldLength - length; - throw e; - } - notify(); - } - - /** - * Waits for the buffer to drain if it is full. - * @param partial if true, waits until the buffer is partially empty, else drains it entirely - * @throws InterruptedIOException if the buffer could not be drained as requested - */ - private void syncCommit(boolean partial) throws IOException { - checkError(); // check errors before allowing the addition of new bytes - if (partial && length != iobuffer.length || length == 0) { - return; - } - if (waitingForClose) { - throw new IOException(Messages.TimeoutOutputStream_cannotWriteToStream); - } - notify(); - try { - wait(writeTimeout); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); // we weren't expecting to be interrupted - } - checkError(); // check errors before allowing the addition of new bytes - if (partial && length != iobuffer.length || length == 0) { - return; - } - throw new InterruptedIOException(); - } - - /** - * If an exception is pending, throws it. - */ - private void checkError() throws IOException { - if (ioe != null) { - IOException e = ioe; - ioe = null; - throw e; - } - } - - /** - * Runs the thread in the background. - */ - private void runThread() { - try { - writeUntilDone(); - } catch (IOException e) { - synchronized (this) { ioe = e; } - } finally { - waitUntilClosed(); - try { - out.close(); - } catch (IOException e) { - synchronized (this) { ioe = e; } - } finally { - synchronized (this) { - thread = null; - notify(); - } - } - } - } - - /** - * Waits until we have been requested to close the stream. - */ - private synchronized void waitUntilClosed() { - waitingForClose = true; - notify(); - while (! closeRequested) { - try { - wait(); - } catch (InterruptedException e) { - closeRequested = true; // alternate quit signal - } - } - } - - /** - * Writes bytes from the buffer until closed and buffer is empty - */ - private void writeUntilDone() throws IOException { - int bytesUntilFlush = -1; // if > 0, then we will flush after that many bytes have been written - for (;;) { - int off, len; - synchronized (this) { - for (;;) { - if (closeRequested && length == 0) { - return; // quit signal - } - if (length != 0 || flushRequested) { - break; - } - try { - wait(); - } catch (InterruptedException e) { - closeRequested = true; // alternate quit signal - } - } - off = head; - len = iobuffer.length - head; - if (len > length) { - len = length; - } - if (flushRequested && bytesUntilFlush < 0) { - flushRequested = false; - bytesUntilFlush = length; - } - } - - // If there are bytes to be written, write them - if (len != 0) { - // write out all remaining bytes from the buffer before flushing - try { - // the i/o operation might block without releasing the lock, - // so we do this outside of the synchronized block - out.write(iobuffer, off, len); - } catch (InterruptedIOException e) { - len = e.bytesTransferred; - } - } - - // If there was a pending flush, do it - if (bytesUntilFlush >= 0) { - bytesUntilFlush -= len; - if (bytesUntilFlush <= 0) { - // flush the buffer now - try { - out.flush(); - } catch (InterruptedIOException e) { - } - bytesUntilFlush = -1; // might have been 0 - } - } - - // If bytes were written, update the circular buffer - if (len != 0) { - synchronized (this) { - head = (head + len) % iobuffer.length; - length -= len; - notify(); - } - } - } - } -} diff --git a/team/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/AllTeamTests.java b/team/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/AllTeamTests.java index 8030468e172..94aa760a7a0 100644 --- a/team/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/AllTeamTests.java +++ b/team/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/AllTeamTests.java @@ -24,7 +24,6 @@ RefreshSubscriberParticipantJobProgressTests.class, // RepositoryProviderTests.class, // StorageMergerTests.class, // - StreamTests.class, // UserMappingTest.class, // }) public class AllTeamTests { diff --git a/team/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/StreamTests.java b/team/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/StreamTests.java deleted file mode 100644 index 455967df4e5..00000000000 --- a/team/tests/org.eclipse.team.tests.core/src/org/eclipse/team/tests/core/StreamTests.java +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.team.tests.core; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; - -import org.eclipse.team.internal.core.streams.CRLFtoLFInputStream; -import org.eclipse.team.internal.core.streams.LFtoCRLFInputStream; -import org.junit.jupiter.api.Test; - -public class StreamTests { - - @Test - public void testCRLFtoLFInputStream() throws IOException { - testCRLFtoLFTranslation("", ""); - testCRLFtoLFTranslation("a", "a"); - testCRLFtoLFTranslation("abc", "abc"); - testCRLFtoLFTranslation("\n", "\n"); - testCRLFtoLFTranslation("\r", "\r"); - testCRLFtoLFTranslation("\r\n", "\n"); - testCRLFtoLFTranslation("x\r\r\n\rx", "x\r\n\rx"); - testCRLFtoLFTranslation("The \r\n quick brown \n fox \r\n\n\r\r\n jumped \n\n over \r\n the \n lazy dog.\r\n", - "The \n quick brown \n fox \n\n\r\n jumped \n\n over \n the \n lazy dog.\n"); - } - - private void testCRLFtoLFTranslation(String pre, String post) throws IOException { - ByteArrayInputStream bin = new ByteArrayInputStream(pre.getBytes()); - InputStream in = new CRLFtoLFInputStream(bin); - InputStream inExpected = new ByteArrayInputStream(post.getBytes()); - assertStreamEquals(inExpected, in); - } - - @Test - public void testLFtoCRLFInputStream() throws IOException { - testLFtoCRLFTranslation("", ""); - testLFtoCRLFTranslation("a", "a"); - testLFtoCRLFTranslation("abc", "abc"); - testLFtoCRLFTranslation("\n", "\r\n"); - testLFtoCRLFTranslation("\r", "\r"); - testLFtoCRLFTranslation("\r\n", "\r\r\n"); - testLFtoCRLFTranslation("x\r\r\n\rx", "x\r\r\r\n\rx"); - testLFtoCRLFTranslation("The \r\n quick brown \n fox \r\n\n\r\r\n jumped \n\n over \r\n the \n lazy dog.\r\n", - "The \r\r\n quick brown \r\n fox \r\r\n\r\n\r\r\r\n jumped \r\n\r\n over \r\r\n the \r\n lazy dog.\r\r\n"); - } - - private void testLFtoCRLFTranslation(String pre, String post) throws IOException { - ByteArrayInputStream bin = new ByteArrayInputStream(pre.getBytes()); - InputStream in = new LFtoCRLFInputStream(bin); - InputStream inExpected = new ByteArrayInputStream(post.getBytes()); - assertStreamEquals(inExpected, in); - } - - private void assertStreamEquals(InputStream in1, InputStream in2) throws IOException { - try { - for (;;) { - int byte1 = in1.read(); - int byte2 = in2.read(); - assertEquals(byte1, byte2, "Streams not equal"); - if (byte1 == -1) break; - } - } finally { - in1.close(); - in2.close(); - } - } -}