Skip to content
Snippets Groups Projects
Commit 8e886de3 authored by Emmanuel Bourg's avatar Emmanuel Bourg
Browse files

New upstream version 4.17

parent a04fddac
No related branches found
Tags upstream/4.17
No related merge requests found
Showing
with 574 additions and 120 deletions
......@@ -14,7 +14,7 @@
<parent>
<artifactId>eclipse.platform.debug</artifactId>
<groupId>eclipse.platform.debug</groupId>
<version>4.16.0-SNAPSHOT</version>
<version>4.17.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.core</groupId>
<artifactId>org.eclipse.core.externaltools</artifactId>
......
......@@ -14,7 +14,7 @@
<parent>
<artifactId>eclipse.platform.debug</artifactId>
<groupId>eclipse.platform.debug</groupId>
<version>4.16.0-SNAPSHOT</version>
<version>4.17.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.core</groupId>
<artifactId>org.eclipse.core.variables</artifactId>
......
......@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.debug.core; singleton:=true
Bundle-Version: 3.15.100.qualifier
Bundle-Version: 3.16.0.qualifier
Bundle-ClassPath: .
Bundle-Activator: org.eclipse.debug.core.DebugPlugin
Bundle-Vendor: %providerName
......@@ -12,7 +12,7 @@ Export-Package: org.eclipse.debug.core,
org.eclipse.debug.core.model,
org.eclipse.debug.core.sourcelookup,
org.eclipse.debug.core.sourcelookup.containers,
org.eclipse.debug.internal.core;x-friends:="org.eclipse.debug.ui,org.eclipse.debug.tests,org.eclipse.debug.examples.mixedmode,org.eclipse.jdt.launching",
org.eclipse.debug.internal.core;x-friends:="org.eclipse.debug.ui,org.eclipse.debug.tests,org.eclipse.debug.examples.mixedmode,org.eclipse.jdt.launching,org.eclipse.ui.console",
org.eclipse.debug.internal.core.commands;x-friends:="org.eclipse.debug.ui",
org.eclipse.debug.internal.core.groups;x-friends:="org.eclipse.debug.ui",
org.eclipse.debug.internal.core.groups.observer;x-internal:=true,
......
/*******************************************************************************
* Copyright (c) 2020 Paul Pazderski 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:
* Paul Pazderski - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.core;
import org.eclipse.debug.core.model.IBinaryStreamMonitor;
/**
* A stream listener is notified of changes to a binary stream monitor.
* <p>
* Clients may implement this interface.
* </p>
*
* @see IBinaryStreamMonitor
* @see IStreamListener
* @since 3.16
*/
public interface IBinaryStreamListener {
/**
* Notifies this listener that data has been appended to the given stream
* monitor.
*
* @param data the content appended; not <code>null</code>
* @param monitor the stream monitor to which content was appended
*/
void streamAppended(byte[] data, IBinaryStreamMonitor monitor);
}
/*******************************************************************************
* Copyright (c) 2020 Paul Pazderski 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:
* Paul Pazderski - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.core.model;
import org.eclipse.debug.core.IBinaryStreamListener;
/**
* A variant of {@link IStreamMonitor} which does not touch the received content
* and pass it as bytes instead of strings.
* <p>
* A stream monitor manages the contents of the stream a process is writing to,
* and notifies registered listeners of changes in the stream.
* </p>
* <p>
* Clients may implement this interface. Generally, a client that provides an
* implementation of the {@link IBinaryStreamsProxy} interface must also provide
* an implementation of this interface.
* </p>
*
* @see org.eclipse.debug.core.model.IStreamsProxy
* @see org.eclipse.debug.core.model.IFlushableStreamMonitor
* @since 3.16
*/
public interface IBinaryStreamMonitor extends IFlushableStreamMonitor {
/**
* Adds the given listener to this stream monitor's registered listeners.
* Has no effect if an identical listener is already registered.
*
* @param listener the listener to add
*/
void addBinaryListener(IBinaryStreamListener listener);
/**
* Returns the entire current contents of the stream. An empty array is
* returned if the stream is empty.
* <p>
* Note: the current content is influenced by the buffering mechanism.
* </p>
*
* @return the stream contents as array
* @see #isBuffered()
* @see #flushContents()
*/
byte[] getData();
/**
* Removes the given listener from this stream monitor's registered listeners.
* Has no effect if the listener is not already registered.
*
* @param listener the listener to remove
*/
void removeBinaryListener(IBinaryStreamListener listener);
}
/*******************************************************************************
* Copyright (c) 2020 Paul Pazderski 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:
* Paul Pazderski - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.core.model;
import java.io.IOException;
/**
* A variant of {@link IStreamsProxy} which does not touch the proxied content
* and pass it as bytes instead of strings.
* <p>
* A streams proxy acts as proxy between the streams of a process and interested
* clients. This abstraction allows implementations of <code>IProcess</code> to
* handle I/O related to the standard input, output, and error streams
* associated with a process.
* </p>
* <p>
* Clients implementing the <code>IProcess</code> interface for a process which
* produce or consumes binary content should consider to implement this
* interface instead of just {@link IStreamsProxy}.
* </p>
*
* @see IProcess
* @see IStreamsProxy
* @since 3.16
*/
public interface IBinaryStreamsProxy extends IStreamsProxy2 {
/**
* Returns a monitor for the error stream of this proxy's process, or
* <code>null</code> if not supported.
* <p>
* The monitor is connected to the error stream of the associated process.
* </p>
* <p>
* In contrast to {@link #getErrorStreamMonitor()} which will decode the
* stream content to strings, the {@link IBinaryStreamMonitor} will provide
* the raw stream data.
* </p>
*
* @return an error stream monitor, or <code>null</code> if none
*/
IBinaryStreamMonitor getBinaryErrorStreamMonitor();
/**
* Returns a monitor for the output stream of this proxy's process, or
* <code>null</code> if not supported.
* <p>
* The monitor is connected to the output stream of the associated process.
* </p>
* <p>
* In contrast to {@link #getOutputStreamMonitor()} which will decode the
* stream content to strings, the {@link IBinaryStreamMonitor} will provide
* the raw stream data.
* </p>
*
* @return an output stream monitor, or <code>null</code> if none
*/
IBinaryStreamMonitor getBinaryOutputStreamMonitor();
/**
* Writes the given data to the output stream connected to the standard
* input stream of this proxy's process.
*
* @param data the data to be written
* @exception IOException when an error occurs writing to the underlying
* <code>OutputStream</code>.
*/
default void write(byte[] data) throws IOException {
write(data, 0, data.length);
}
/**
* Writes the given data to the output stream connected to the standard
* input stream of this proxy's process.
*
* @param data the data to be written
* @param offset start offset in the data
* @param length number of bytes to write
* @exception IOException when an error occurs writing to the underlying
* <code>OutputStream</code>.
*/
void write(byte[] data, int offset, int length) throws IOException;
}
......@@ -43,12 +43,12 @@ import org.eclipse.debug.core.DebugPlugin;
* markerType="com.example.BreakpointMarker"&gt;
* &lt;/breakpoint&gt;
* &lt;/extension&gt;
* &lt;extension point="org.eclipse.core.resources.markers"&gt;
* &lt;marker
* &lt;extension
* point="org.eclipse.core.resources.markers"
* id="com.example.BreakpointMarker"
* super type="org.eclipse.debug.core.breakpointMarker"
* attribute name ="exampleAttribute"&gt;
* &lt;/marker&gt;
* name="Example Breakpoint"&gt;
* &lt;super type="org.eclipse.debug.core.breakpointMarker"/&gt;
* &lt;attribute name="exampleAttribute"/&gt;
* &lt;/extension&gt;
* </pre>
* <p>
......
......@@ -22,6 +22,8 @@ package org.eclipse.debug.core.model;
* Clients may implement this interface.
* </p>
* @since 2.1
* @see IStreamMonitor
* @see IBinaryStreamMonitor
*/
public interface IFlushableStreamMonitor extends IStreamMonitor {
......
......@@ -27,6 +27,7 @@ import org.eclipse.debug.core.IStreamListener;
* </p>
* @see org.eclipse.debug.core.model.IStreamsProxy
* @see org.eclipse.debug.core.model.IFlushableStreamMonitor
* @see org.eclipse.debug.core.model.IBinaryStreamMonitor
*/
public interface IStreamMonitor {
/**
......
......@@ -27,6 +27,7 @@ import java.io.IOException;
* provide an implementation of this interface.
* </p>
* @see IProcess
* @see IBinaryStreamsProxy
*/
public interface IStreamsProxy {
/**
......
......@@ -763,7 +763,7 @@ public class BreakpointManager implements IBreakpointManager, IResourceChangeLis
}
};
getWorkspace().run(runnable, null, 0, null);
addBreakpoints(fAdded.toArray(new IBreakpoint[fAdded.size()]), false);
addBreakpoints(fAdded.toArray(new IBreakpoint[fAdded.size()]), true);
} catch (CoreException e) {
DebugPlugin.log(e);
}
......
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corporation and others.
* Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
......@@ -10,6 +10,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
* Paul Pazderski - Bug 558463: add handling of raw stream content instead of strings
*******************************************************************************/
package org.eclipse.debug.internal.core;
......@@ -22,11 +23,10 @@ import java.util.Vector;
import org.eclipse.debug.core.DebugPlugin;
/**
* Writes to the input stream of a system process,
* queueing output if the stream is blocked.
* Writes to the input stream of a system process, queuing output if the stream
* is blocked.
*
* The input stream monitor writes to system in via
* an output stream.
* The input stream monitor writes to system in via an output stream.
*/
public class InputStreamMonitor {
......@@ -34,14 +34,17 @@ public class InputStreamMonitor {
* The stream which is being written to (connected to system in).
*/
private OutputStream fStream;
/**
* The queue of output.
*/
private Vector<String> fQueue;
private Vector<byte[]> fQueue;
/**
* The thread which writes to the stream.
*/
private Thread fThread;
/**
* A lock for ensuring that writes to the queue are contiguous
*/
......@@ -101,8 +104,25 @@ public class InputStreamMonitor {
* @param text text to append
*/
public void write(String text) {
synchronized(fLock) {
fQueue.add(text);
synchronized (fLock) {
fQueue.add(fCharset == null ? text.getBytes() : text.getBytes(fCharset));
fLock.notifyAll();
}
}
/**
* Appends the given binary data to the stream, or queues the text to be
* written at a later time if the stream is blocked.
*
* @param data data to append; not <code>null</code>
* @param offset start offset in data
* @param length number of bytes in data
*/
public void write(byte[] data, int offset, int length) {
synchronized (fLock) {
byte[] copy = new byte[length];
System.arraycopy(data, offset, copy, 0, length);
fQueue.add(copy);
fLock.notifyAll();
}
}
......@@ -151,14 +171,10 @@ public class InputStreamMonitor {
*/
protected void writeNext() {
while (!fQueue.isEmpty() && !fClosed) {
String text = fQueue.firstElement();
byte[] data = fQueue.firstElement();
fQueue.removeElementAt(0);
try {
if (fCharset != null) {
fStream.write(text.getBytes(fCharset));
} else {
fStream.write(text.getBytes());
}
fStream.write(data);
fStream.flush();
} catch (IOException e) {
DebugPlugin.log(e);
......@@ -180,7 +196,8 @@ public class InputStreamMonitor {
* Closes the output stream attached to the standard input stream of this
* monitor's process.
*
* @exception IOException if an exception occurs closing the input stream
* @exception IOException if an exception occurs closing the input stream or
* stream is already closed
*/
public void closeInputStream() throws IOException {
if (!fClosed) {
......
......@@ -987,7 +987,7 @@ public class LaunchConfiguration extends PlatformObject implements ILaunchConfig
/*
* Get Preferred delegate with all fallbacks
*
*
*/
public ILaunchConfigurationDelegate getPreferredLaunchDelegate(String mode) throws CoreException {
Set<String> modes = getModes();
......
......@@ -896,7 +896,7 @@ public class LaunchConfigurationInfo {
String strAttr1 = null;
String strAttr2 = null;
if (fgIsSun14x) {
if(attr2 instanceof String & attr1 instanceof String) {
if(attr2 instanceof String && attr1 instanceof String) {
// this is a hack for bug 110215, on SUN 1.4.x, \r
// is stripped off when the stream is written to the
// DOM
......
......@@ -1630,7 +1630,7 @@ public class LaunchManager extends PlatformObject implements ILaunchManager, IRe
LaunchDelegate delegate = getLaunchDelegateExtension(typeid, delegateid, modeset);
if (delegate != null) {
//take type id, modeset, delegate and create entry
if(!IInternalDebugCoreConstants.EMPTY_STRING.equals(typeid) & modeset != null) {
if(!IInternalDebugCoreConstants.EMPTY_STRING.equals(typeid) && modeset != null) {
fPreferredDelegates.add(new PreferredDelegate(delegate, typeid, modeset));
}
}
......
/*******************************************************************************
* Copyright (c) 2000, 2013 IBM Corporation and others.
* Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
......@@ -16,11 +16,13 @@ package org.eclipse.debug.internal.core;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.debug.core.IBinaryStreamListener;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IBinaryStreamMonitor;
import org.eclipse.debug.core.model.IBinaryStreamsProxy;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.debug.core.model.IStreamsProxy2;
public class NullStreamsProxy implements IStreamsProxy2 {
public class NullStreamsProxy implements IBinaryStreamsProxy {
private NullStreamMonitor outputStreamMonitor;
private NullStreamMonitor errorStreamMonitor;
......@@ -48,7 +50,21 @@ public class NullStreamsProxy implements IStreamsProxy2 {
public void write(String input) throws IOException {
}
private class NullStreamMonitor implements IStreamMonitor {
@Override
public IBinaryStreamMonitor getBinaryErrorStreamMonitor() {
return errorStreamMonitor;
}
@Override
public IBinaryStreamMonitor getBinaryOutputStreamMonitor() {
return outputStreamMonitor;
}
@Override
public void write(byte[] data, int offset, int length) throws IOException {
}
private class NullStreamMonitor implements IBinaryStreamMonitor {
private InputStream fStream;
public NullStreamMonitor(InputStream stream) {
......@@ -80,8 +96,34 @@ public class NullStreamsProxy implements IStreamsProxy2 {
return ""; //$NON-NLS-1$
}
@Override
public void flushContents() {
}
@Override
public void setBuffered(boolean buffer) {
}
@Override
public boolean isBuffered() {
return false;
}
@Override
public void removeListener(IStreamListener listener) {
}
@Override
public void addBinaryListener(IBinaryStreamListener listener) {
}
@Override
public byte[] getData() {
return new byte[0];
}
@Override
public void removeBinaryListener(IBinaryStreamListener listener) {
}
}
}
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corporation and others.
* Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
......@@ -11,13 +11,14 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Paul Pazderski - Bug 545769: fixed rare UTF-8 character corruption bug
* Paul Pazderski - Bug 558463: add handling of raw stream content instead of strings
*******************************************************************************/
package org.eclipse.debug.internal.core;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicBoolean;
......@@ -25,58 +26,69 @@ import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBinaryStreamListener;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IFlushableStreamMonitor;
import org.eclipse.debug.core.model.IBinaryStreamMonitor;
/**
* Monitors the output stream of a system process and notifies
* listeners of additions to the stream.
*
* The output stream monitor reads system out (or err) via
* and input stream.
* Monitors the output stream of a system process and notifies listeners of
* additions to the stream.
* <p>
* The output stream monitor reads system out (or err) via and input stream.
*/
public class OutputStreamMonitor implements IFlushableStreamMonitor {
public class OutputStreamMonitor implements IBinaryStreamMonitor {
/**
* The size of the read buffer.
*/
private static final int BUFFER_SIZE = 8192;
/**
* The stream being monitored (connected system out or err).
*/
private InputStream fStream;
/**
* A collection of listeners
* A collection of listeners interested in decoded content.
*/
private ListenerList<IStreamListener> fListeners = new ListenerList<>();
/**
* Whether content is being buffered
* A collection of listeners interested in the raw content.
*/
private boolean fBuffered = true;
private ListenerList<IBinaryStreamListener> fBinaryListeners = new ListenerList<>();
/**
* The local copy of the stream contents
* The buffered stream content since last flush. Value of <code>null</code>
* indicates disabled buffering.
*
* @see #isBuffered()
*/
private StringBuilder fContents;
private ByteArrayOutputStream fContents;
/**
* The thread which reads from the stream
* Decoder used for the buffered content. This is required to keep the state
* of an incomplete character.
*/
private Thread fThread;
private StreamDecoder fBufferedDecoder;
private String fCachedDecodedContents;
/**
* The size of the read buffer
* The thread which reads from the stream
*/
private static final int BUFFER_SIZE= 8192;
private Thread fThread;
/**
* Whether or not this monitor has been killed.
* When the monitor is killed, it stops reading
* from the stream immediately.
* Whether or not this monitor has been killed. When the monitor is killed,
* it stops reading from the stream immediately.
*/
private boolean fKilled= false;
private boolean fKilled = false;
private long lastSleep;
private Charset fCharset;
private StreamDecoder fDecoder;
private final AtomicBoolean fDone;
/**
......@@ -84,13 +96,15 @@ public class OutputStreamMonitor implements IFlushableStreamMonitor {
* out or err).
*
* @param stream input stream to read from
* @param charset stream charset or <code>null</code> for system default
* @param charset stream charset or <code>null</code> for system default;
* unused if only the binary interface is used
*/
public OutputStreamMonitor(InputStream stream, Charset charset) {
fStream = new BufferedInputStream(stream, 8192);
fCharset = charset;
fContents= new StringBuilder();
fDecoder = new StreamDecoder(charset == null ? Charset.defaultCharset() : charset);
fDone = new AtomicBoolean(false);
setBuffered(true);
}
/**
......@@ -112,35 +126,97 @@ public class OutputStreamMonitor implements IFlushableStreamMonitor {
fListeners.add(listener);
}
@Override
public synchronized void addBinaryListener(IBinaryStreamListener listener) {
fBinaryListeners.add(listener);
}
/**
* Causes the monitor to close all
* communications between it and the
* Causes the monitor to close all communications between it and the
* underlying stream by waiting for the thread to terminate.
*/
protected void close() {
if (fThread != null) {
Thread thread= fThread;
fThread= null;
Thread thread = fThread;
fThread = null;
try {
thread.join();
} catch (InterruptedException ie) {
}
fListeners = new ListenerList<>();
fBinaryListeners = new ListenerList<>();
}
}
/**
* Notifies the listeners that text has
* been appended to the stream.
* @param text the text that was appended to the stream
* Notifies the listeners that content has been appended to the stream. Will
* notify both, binary and text listeners.
*
* @param data that has been appended; not <code>null</code>
* @param offset start of valid data
* @param length number of valid bytes
*/
private void fireStreamAppended(String text) {
getNotifier().notifyAppend(text);
private void fireStreamAppended(final byte[] data, int offset, int length) {
if (!fListeners.isEmpty()) {
StringBuilder sb = new StringBuilder();
fDecoder.decode(sb, data, offset, length);
final String text = sb.toString();
for (final IStreamListener listener : fListeners) {
SafeRunner.run(new ISafeRunnable() {
@Override
public void run() throws Exception {
listener.streamAppended(text, OutputStreamMonitor.this);
}
@Override
public void handleException(Throwable exception) {
DebugPlugin.log(exception);
}
});
}
}
if (!fBinaryListeners.isEmpty()) {
final byte[] validData;
if (offset > 0 || length < data.length) {
validData = new byte[length];
System.arraycopy(data, offset, validData, 0, length);
} else {
validData = data;
}
for (final IBinaryStreamListener listener : fBinaryListeners) {
SafeRunner.run(new ISafeRunnable() {
@Override
public void run() throws Exception {
listener.streamAppended(validData, OutputStreamMonitor.this);
}
@Override
public void handleException(Throwable exception) {
DebugPlugin.log(exception);
}
});
}
}
}
@Override
public synchronized String getContents() {
return fContents.toString();
if (!isBuffered()) {
return ""; //$NON-NLS-1$
}
if (fCachedDecodedContents != null) {
return fCachedDecodedContents;
}
StringBuilder sb = new StringBuilder();
byte[] data = getData();
fBufferedDecoder.decode(sb, data, 0, data.length);
fCachedDecodedContents = sb.toString();
return fCachedDecodedContents;
}
@Override
public synchronized byte[] getData() {
return isBuffered() ? fContents.toByteArray() : new byte[0];
}
private void read() {
......@@ -154,30 +230,29 @@ public class OutputStreamMonitor implements IFlushableStreamMonitor {
/**
* Continually reads from the stream.
* <p>
* This method, along with the <code>startReading</code>
* method is used to allow <code>OutputStreamMonitor</code>
* to implement <code>Runnable</code> without publicly
* exposing a <code>run</code> method.
* This method, along with the {@link #startMonitoring()} method is used to
* allow {@link OutputStreamMonitor} to implement {@link Runnable} without
* publicly exposing a {@link Runnable#run()} method.
*/
private void internalRead() {
lastSleep = System.currentTimeMillis();
long currentTime = lastSleep;
char[] chars = new char[BUFFER_SIZE];
byte[] buffer = new byte[BUFFER_SIZE];
int read = 0;
try (InputStreamReader reader = (fCharset == null ? new InputStreamReader(fStream) : new InputStreamReader(fStream, fCharset))) {
try {
while (read >= 0) {
try {
if (fKilled) {
break;
}
read = reader.read(chars);
read = fStream.read(buffer);
if (read > 0) {
String text = new String(chars, 0, read);
synchronized (this) {
if (isBuffered()) {
fContents.append(text);
fCachedDecodedContents = null;
fContents.write(buffer, 0, read);
}
fireStreamAppended(text);
fireStreamAppended(buffer, 0, read);
}
}
} catch (IOException ioe) {
......@@ -204,13 +279,17 @@ public class OutputStreamMonitor implements IFlushableStreamMonitor {
}
}
}
} catch (IOException e) {
DebugPlugin.log(e);
} finally {
try {
fStream.close();
} catch (IOException e) {
DebugPlugin.log(e);
}
}
}
protected void kill() {
fKilled= true;
fKilled = true;
}
@Override
......@@ -218,6 +297,11 @@ public class OutputStreamMonitor implements IFlushableStreamMonitor {
fListeners.remove(listener);
}
@Override
public synchronized void removeBinaryListener(IBinaryStreamListener listener) {
fBinaryListeners.remove(listener);
}
/**
* Starts a thread which reads from the stream
*/
......@@ -233,57 +317,37 @@ public class OutputStreamMonitor implements IFlushableStreamMonitor {
@Override
public synchronized void setBuffered(boolean buffer) {
fBuffered = buffer;
if (isBuffered() != buffer) {
fCachedDecodedContents = null;
if (buffer) {
fContents = new ByteArrayOutputStream();
fBufferedDecoder = new StreamDecoder(fCharset == null ? Charset.defaultCharset() : fCharset);
} else {
fContents = null;
fBufferedDecoder = null;
}
}
}
@Override
public synchronized void flushContents() {
fContents.setLength(0);
if (isBuffered()) {
fCachedDecodedContents = null;
fContents.reset();
}
}
@Override
public synchronized boolean isBuffered() {
return fBuffered;
}
private ContentNotifier getNotifier() {
return new ContentNotifier();
return fContents != null;
}
/**
* @return {@code true} if reading the underlying stream is done.
* {@code false} if reading the stream has not started or is not done.
* {@code false} if reading the stream has not started or is not
* done.
*/
public boolean isReadingDone() {
return fDone.get();
}
class ContentNotifier implements ISafeRunnable {
private IStreamListener fListener;
private String fText;
@Override
public void handleException(Throwable exception) {
DebugPlugin.log(exception);
}
@Override
public void run() throws Exception {
fListener.streamAppended(fText, OutputStreamMonitor.this);
}
public void notifyAppend(String text) {
if (text == null) {
return;
}
fText = text;
for (IStreamListener iStreamListener : fListeners) {
fListener = iStreamListener;
SafeRunner.run(this);
}
fListener = null;
fText = null;
}
}
}
/*******************************************************************************
* Copyright (c) 2017 Andreas Loth 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:
* Andreas Loth - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.internal.core;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
/**
* Wraps CharsetDecoder to decode a byte stream statefully to characters.
*
* @since 3.7 org.eclipse.ui.console
*/
public class StreamDecoder {
// For more context see https://bugs.eclipse.org/bugs/show_bug.cgi?id=507664
static private final int BUFFER_SIZE = 4096;
private final CharsetDecoder decoder;
private final ByteBuffer inputBuffer;
private final CharBuffer outputBuffer;
private boolean finished;
public StreamDecoder(Charset charset) {
this.decoder = charset.newDecoder();
this.decoder.onMalformedInput(CodingErrorAction.REPLACE);
this.decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
this.inputBuffer = ByteBuffer.allocate(StreamDecoder.BUFFER_SIZE);
this.inputBuffer.flip();
this.outputBuffer = CharBuffer.allocate(StreamDecoder.BUFFER_SIZE);
this.finished = false;
}
private void consume(StringBuilder consumer) {
this.outputBuffer.flip();
consumer.append(this.outputBuffer);
this.outputBuffer.clear();
}
private void internalDecode(StringBuilder consumer, byte[] buffer, int offset, int length) {
assert (offset >= 0);
assert (length >= 0);
int position = offset;
int end = offset + length;
assert (end <= buffer.length);
boolean finishedReading = false;
do {
CoderResult result = this.decoder.decode(this.inputBuffer, this.outputBuffer, false);
if (result.isOverflow()) {
this.consume(consumer);
} else if (result.isUnderflow()) {
this.inputBuffer.compact();
int remaining = this.inputBuffer.remaining();
assert (remaining > 0);
int read = Math.min(remaining, end - position);
if (read > 0) {
this.inputBuffer.put(buffer, position, read);
position += read;
} else {
finishedReading = true;
}
this.inputBuffer.flip();
} else {
assert false;
}
} while (!finishedReading);
}
public void decode(StringBuilder consumer, byte[] buffer, int offset, int length) {
this.internalDecode(consumer, buffer, offset, length);
this.consume(consumer);
}
public void finish(StringBuilder consumer) {
if (this.finished) {
return;
}
this.finished = true;
CoderResult result;
result = this.decoder.decode(this.inputBuffer, this.outputBuffer, true);
assert (result.isOverflow() || result.isUnderflow());
do {
result = this.decoder.flush(this.outputBuffer);
if (result.isOverflow()) {
this.consume(consumer);
} else {
assert result.isUnderflow();
}
} while (!result.isUnderflow());
this.consume(consumer);
}
}
/*******************************************************************************
* Copyright (c) 2000, 2013 IBM Corporation and others.
* Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
......@@ -17,15 +17,19 @@ package org.eclipse.debug.internal.core;
import java.io.IOException;
import java.nio.charset.Charset;
import org.eclipse.debug.core.model.IBinaryStreamMonitor;
import org.eclipse.debug.core.model.IBinaryStreamsProxy;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.debug.core.model.IStreamsProxy2;
/**
* Standard implementation of a streams proxy for IStreamsProxy.
* Standard implementation of a streams proxy for {@link IStreamsProxy},
* {@link IStreamsProxy2} and {@link IBinaryStreamsProxy}.
* <p>
* Will use the same monitor instances for binary and string stream handling.
*/
public class StreamsProxy implements IStreamsProxy, IStreamsProxy2 {
public class StreamsProxy implements IBinaryStreamsProxy {
/**
* The monitor for the output stream (connected to standard out of the process)
*/
......@@ -155,4 +159,22 @@ public class StreamsProxy implements IStreamsProxy, IStreamsProxy2 {
}
@Override
public IBinaryStreamMonitor getBinaryErrorStreamMonitor() {
return fErrorMonitor;
}
@Override
public IBinaryStreamMonitor getBinaryOutputStreamMonitor() {
return fOutputMonitor;
}
@Override
public void write(byte[] data, int offset, int length) throws IOException {
if (!isClosed(false)) {
fInputMonitor.write(data, offset, length);
} else {
throw new IOException();
}
}
}
# To force a version qualifier update add the bug here
Bug 566471 - I20200828-0150 - Comparator Errors Found
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment