package org.eclipse.dltk.debug.ui;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IFlushableStreamMonitor;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.console.IConsoleColorProvider;
import org.eclipse.dltk.launching.process.IScriptProcess;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleOutputStream;
public class ScriptDebugConsole extends IOConsole {
/**
* @since 2.0
*/
public static final String TYPE = DLTKDebugUIPlugin.PLUGIN_ID
+ ".ScriptDebugConsoleType"; //$NON-NLS-1$
private final ILaunch launch;
private final IConsoleColorProvider fColorProvider;
public ILaunch getLaunch() {
return launch;
}
/**
* @since 2.0
*/
public IProcess getProcess() {
final IProcess[] processes = launch.getProcesses();
if (processes.length != 0) {
return processes[0];
} else {
return null;
}
}
/**
* @since 2.0
*/
public ScriptDebugConsole(ILaunch launch, String name,
ImageDescriptor imageDescriptor, String encoding,
IConsoleColorProvider colorProvider) {
super(name, TYPE, imageDescriptor, encoding, true);
this.launch = launch;
this.fColorProvider = colorProvider;
this.addPatternMatchListener(new ScriptDebugConsoleTraceTracker());
}
@Override
public void matcherFinished() {
super.matcherFinished();
}
@Override
public void partitionerFinished() {
super.partitionerFinished();
}
/*
* Increase visibility
*/
@Override
protected void setName(String name) {
super.setName(name);
}
@Override
protected void dispose() {
closeStreams();
disposeStreams();
super.dispose();
}
private Set<IScriptProcess> connectedProcesses;
/**
* @param process
* @since 2.0
*/
public synchronized void connect(IScriptProcess process) {
if (connectedProcesses == null) {
connectedProcesses = new HashSet<>();
}
if (connectedProcesses.add(process)) {
final IStreamsProxy proxy = process.getScriptStreamsProxy();
if (proxy == null) {
return;
}
connect(proxy);
}
}
/**
* @since 2.0
*/
public void connect(final IStreamsProxy proxy) {
IStreamMonitor streamMonitor = proxy.getErrorStreamMonitor();
if (streamMonitor != null) {
connect(streamMonitor, IDebugUIConstants.ID_STANDARD_ERROR_STREAM);
}
streamMonitor = proxy.getOutputStreamMonitor();
if (streamMonitor != null) {
connect(streamMonitor, IDebugUIConstants.ID_STANDARD_OUTPUT_STREAM);
}
}
private List<StreamListener> fStreamListeners = new ArrayList<>();
/**
* @param streamMonitor
* @param idStandardErrorStream
*/
private void connect(IStreamMonitor streamMonitor,
String streamIdentifier) {
synchronized (streamMonitor) {
IOConsoleOutputStream stream = newOutputStream();
stream.setColor(fColorProvider.getColor(streamIdentifier));
StreamListener listener = new StreamListener(streamMonitor, stream);
fStreamListeners.add(listener);
}
}
/**
* cleanup method to close all of the open stream to this console
*/
private synchronized void closeStreams() {
for (StreamListener listener : fStreamListeners) {
listener.closeStream();
}
}
/**
* disposes of the listeners for each of the stream associated with this
* console
*/
private synchronized void disposeStreams() {
for (StreamListener listener : fStreamListeners) {
listener.dispose();
}
}
/**
* This class listens to a specified IO stream
*/
private class StreamListener implements IStreamListener {
private IOConsoleOutputStream fStream;
private IStreamMonitor fStreamMonitor;
private boolean fFlushed = false;
private boolean fListenerRemoved = false;
public StreamListener(IStreamMonitor monitor,
IOConsoleOutputStream stream) {
this.fStream = stream;
this.fStreamMonitor = monitor;
fStreamMonitor.addListener(this);
// fix to bug 121454. Ensure that output to fast processes is
// processed.
streamAppended(null, monitor);
}
@Override
public void streamAppended(String text, IStreamMonitor monitor) {
String encoding = getEncoding();
if (fFlushed) {
try {
if (fStream != null) {
if (encoding == null)
fStream.write(text);
else
fStream.write(text.getBytes(encoding));
}
} catch (IOException e) {
DLTKDebugUIPlugin.log(e);
}
} else {
String contents = null;
synchronized (fStreamMonitor) {
fFlushed = true;
contents = fStreamMonitor.getContents();
if (fStreamMonitor instanceof IFlushableStreamMonitor) {
IFlushableStreamMonitor m = (IFlushableStreamMonitor) fStreamMonitor;
m.flushContents();
m.setBuffered(false);
}
}
try {
if (contents != null && contents.length() > 0) {
if (fStream != null) {
fStream.write(contents);
}
}
} catch (IOException e) {
DLTKDebugUIPlugin.log(e);
}
}
}
public void closeStream() {
if (fStreamMonitor == null) {
return;
}
synchronized (fStreamMonitor) {
fStreamMonitor.removeListener(this);
if (!fFlushed) {
String contents = fStreamMonitor.getContents();
streamAppended(contents, fStreamMonitor);
}
fListenerRemoved = true;
}
}
public void dispose() {
if (!fListenerRemoved) {
closeStream();
}
fStreamMonitor = null;
fStream = null;
}
}
}