/* * #%~ * org.overture.ide.debug * %% * Copyright (C) 2008 - 2014 Overture * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #~% */ package org.overture.ide.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.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IDebugEventSetListener; 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.jface.resource.ImageDescriptor; import org.eclipse.ui.console.ConsolePlugin; import org.eclipse.ui.console.IConsole; import org.eclipse.ui.console.IOConsole; import org.eclipse.ui.console.IOConsoleInputStream; import org.eclipse.ui.console.IOConsoleOutputStream; import org.eclipse.ui.progress.UIJob; import org.overture.ide.debug.core.VdmDebugPlugin; public class VdmDebugConsole extends IOConsole implements IDebugEventSetListener { /** * @since 2.0 */ public static final String TYPE = VdmDebugPlugin.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 VdmDebugConsole(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<IProcess> connectedProcesses; /** * @param process * @since 2.0 */ public synchronized void connect(IProcess process) { if (connectedProcesses == null) { connectedProcesses = new HashSet<IProcess>(); } if (connectedProcesses.add(process)) { final IStreamsProxy proxy = process.getStreamsProxy(); 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); } IOConsoleInputStream input = getInputStream(); if (input != null) { getInputStream().setColor(fColorProvider.getColor(IDebugUIConstants.ID_STANDARD_INPUT_STREAM)); } } private List<StreamListener> fStreamListeners = new ArrayList<StreamListener>(); /** * @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); } 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) { VdmDebugPlugin.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) { VdmDebugPlugin.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; } } /** * Notify listeners when name changes. * * @see org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse.debug.core.DebugEvent[]) */ public void handleDebugEvents(DebugEvent[] events) { for (int i = 0; i < events.length; i++) { DebugEvent event = events[i]; if (event.getSource().equals(getProcess())) { if (event.getKind() == DebugEvent.TERMINATE) { closeStreams(); DebugPlugin.getDefault().removeDebugEventListener(this); } resetName(); } } } /** * resets the name of this console to the original computed name */ private void resetName() { UIJob job = new UIJob("Activating Console") { //$NON-NLS-1$ public IStatus runInUIThread(IProgressMonitor monitor) { warnOfContentChange(); return Status.OK_STATUS; } }; job.setSystem(true); job.schedule(); } /** * send notification of a change of content in this console */ private void warnOfContentChange() { IConsole[] consoles = ConsolePlugin.getDefault().getConsoleManager().getConsoles(); for (IConsole iConsole : consoles) { if (iConsole instanceof VdmDebugConsole) { VdmDebugConsole vdmC = (VdmDebugConsole) iConsole; vdmC.activate(); } } // if (warn != null) { // ConsolePlugin.getDefault().getConsoleManager() // .warnOfContentChange(warn); // } } }