From 6144b2233dff21583af97d8811100748c6a69950 Mon Sep 17 00:00:00 2001 From: David Inglis Date: Wed, 14 Jul 2004 01:26:22 +0000 Subject: [PATCH] improve build ouptut console streaming --- .../org/eclipse/cdt/core/CommandLauncher.java | 162 +++++---------- .../cdt/internal/core/ProcessClosure.java | 184 ++++++++++-------- .../ui/buildconsole/BuildConsoleManager.java | 63 +++--- .../ui/buildconsole/BuildConsolePage.java | 49 ++--- .../buildconsole/BuildConsolePartitioner.java | 119 +++++++++-- .../BuildConsolePreferencePage.java | 4 +- 6 files changed, 304 insertions(+), 277 deletions(-) diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncher.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncher.java index a37b0b0db25..0c99c318617 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncher.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CommandLauncher.java @@ -1,14 +1,11 @@ package org.eclipse.cdt.core; /* - * (c) Copyright IBM Corp. 2000, 2001. - * All Rights Reserved. + * (c) Copyright IBM Corp. 2000, 2001. All Rights Reserved. */ - + import java.io.IOException; import java.io.OutputStream; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; import java.util.Properties; import org.eclipse.cdt.internal.core.ProcessClosure; @@ -17,45 +14,43 @@ import org.eclipse.cdt.utils.spawner.ProcessFactory; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; - public class CommandLauncher { - - public final static int COMMAND_CANCELED= 1; - public final static int ILLEGAL_COMMAND= -1; - public final static int OK= 0; - + + public final static int COMMAND_CANCELED = 1; + public final static int ILLEGAL_COMMAND = -1; + public final static int OK = 0; + protected Process fProcess; protected boolean fShowCommand; protected String[] fCommandArgs; - + protected String fErrorMessage = ""; //$NON-NLS-1$ - + private String lineSeparator; - + /** - * The number of milliseconds to pause - * between polling. + * The number of milliseconds to pause between polling. */ - protected static final long DELAY = 50L; - + protected static final long DELAY = 50L; + /** - * Creates a new launcher - * Fills in stderr and stdout output to the given streams. - * Streams can be set to null, if output not required + * Creates a new launcher Fills in stderr and stdout output to the given + * streams. Streams can be set to null, if output not + * required */ public CommandLauncher() { - fProcess= null; - fShowCommand= false; + fProcess = null; + fShowCommand = false; lineSeparator = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ } - + /** * Sets if the command should be printed out first before executing */ public void showCommand(boolean show) { - fShowCommand= show; + fShowCommand = show; } - + public String getErrorMessage() { return fErrorMessage; } @@ -66,7 +61,7 @@ public class CommandLauncher { public String[] getCommandArgs() { return fCommandArgs; - } + } public Properties getEnvironment() { return EnvironmentReader.getEnvVars(); @@ -96,98 +91,56 @@ public class CommandLauncher { */ public Process execute(IPath commandPath, String[] args, String[] env, IPath changeToDirectory) { try { - // add platform specific arguments (shell invocation) - fCommandArgs= constructCommandArray(commandPath.toOSString(), args); - fProcess= ProcessFactory.getFactory().exec(fCommandArgs, env, changeToDirectory.toFile()); - fErrorMessage= ""; //$NON-NLS-1$ + // add platform specific arguments (shell invocation) + fCommandArgs = constructCommandArray(commandPath.toOSString(), args); + fProcess = ProcessFactory.getFactory().exec(fCommandArgs, env, changeToDirectory.toFile()); + fErrorMessage = ""; //$NON-NLS-1$ } catch (IOException e) { setErrorMessage(e.getMessage()); - fProcess= null; + fProcess = null; } return fProcess; } - + /** * Reads output form the process to the streams. */ public int waitAndRead(OutputStream out, OutputStream err) { if (fShowCommand) { printCommandLine(out); - } + } if (fProcess == null) { return ILLEGAL_COMMAND; } - - ProcessClosure closure= new ProcessClosure(fProcess, out, err); + + ProcessClosure closure = new ProcessClosure(fProcess, out, err); closure.runBlocking(); // a blocking call return OK; } - + /** - * Reads output form the process to the streams. A progress monitor is polled to - * test if the cancel button has been pressed. - * Destroys the process if the monitor becomes canceled - * override to implement a different way to read the process inputs + * Reads output form the process to the streams. A progress monitor is + * polled to test if the cancel button has been pressed. Destroys the + * process if the monitor becomes canceled override to implement a different + * way to read the process inputs */ public int waitAndRead(OutputStream output, OutputStream err, IProgressMonitor monitor) { if (fShowCommand) { printCommandLine(output); - } + } if (fProcess == null) { return ILLEGAL_COMMAND; } - PipedOutputStream errOutPipe = new PipedOutputStream(); - PipedOutputStream outputPipe = new PipedOutputStream(); - PipedInputStream errInPipe, inputPipe; - try { - errInPipe = new PipedInputStream(errOutPipe); - inputPipe = new PipedInputStream(outputPipe); - } catch( IOException e ) { - setErrorMessage(CCorePlugin.getResourceString("CommandLauncher.error.commandCanceled")); //$NON-NLS-1$ - return COMMAND_CANCELED; - } - - ProcessClosure closure= new ProcessClosure(fProcess, outputPipe, errOutPipe); + ProcessClosure closure = new ProcessClosure(fProcess, output, err); closure.runNonBlocking(); - byte buffer[] = new byte[1024]; - int nbytes; - int waited = 0; - boolean flushed = false; while (!monitor.isCanceled() && closure.isAlive()) { - nbytes = 0; try { - if ( errInPipe.available() > 0 ) { - nbytes = errInPipe.read(buffer); - err.write(buffer, 0, nbytes); - } - if ( inputPipe.available() > 0 ) { - nbytes = inputPipe.read(buffer); - output.write(buffer, 0, nbytes); - } - } catch( IOException e) { - } - monitor.worked(0); - if (nbytes == 0) { - //DELAY * 10 is half a second with no new input, flush anything thats waiting - if( !flushed && waited > DELAY * 10 ){ - try { - err.flush(); - output.flush(); - flushed = true; - } catch (IOException e1) { - } - waited = 0; - } - try { - waited += DELAY; - Thread.sleep(DELAY); - } catch (InterruptedException ie) { - } - } else { - flushed = false; + Thread.sleep(DELAY); + } catch (InterruptedException ie) { + // ignore } } @@ -203,48 +156,27 @@ public class CommandLauncher { try { fProcess.waitFor(); } catch (InterruptedException e) { - //System.err.println("Closure exception " +e); - //e.printStackTrace(); + // ignore } - - // Drain the pipes. - try { - while (errInPipe.available() > 0 || inputPipe.available() > 0) { - if ( errInPipe.available() > 0 ) { - nbytes = errInPipe.read(buffer); - err.write(buffer, 0, nbytes); - err.flush(); - } - if ( inputPipe.available() > 0 ) { - nbytes = inputPipe.read(buffer); - output.write(buffer, 0, nbytes); - output.flush(); - } - } - errInPipe.close(); - inputPipe.close(); - } catch (IOException e) { - } - return state; - } + } protected void printCommandLine(OutputStream os) { if (os != null) { String cmd = getCommandLine(getCommandArgs()); try { os.write(cmd.getBytes()); - os.flush(); + os.flush(); } catch (IOException e) { // ignore; } } } - + protected String getCommandLine(String[] commandArgs) { StringBuffer buf = new StringBuffer(); if (fCommandArgs != null) { - for (int i= 0; i < commandArgs.length; i++) { + for (int i = 0; i < commandArgs.length; i++) { buf.append(commandArgs[i]); buf.append(' '); } @@ -253,4 +185,4 @@ public class CommandLauncher { return buf.toString(); } -} +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/ProcessClosure.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/ProcessClosure.java index 21f4396322c..6acaa4f0526 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/ProcessClosure.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/ProcessClosure.java @@ -6,73 +6,73 @@ package org.eclipse.cdt.internal.core; */ import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.OutputStreamWriter; - /** - * Bundled state of a launched process including the threads linking the process in/output - * to console documents. + * Bundled state of a launched process including the threads linking the process + * in/output to console documents. */ public class ProcessClosure { - + /** - * Thread which continuously reads from a input stream and pushes the read data - * to an output stream which is immediately flushed afterwards. + * Thread which continuously reads from a input stream and pushes the read + * data to an output stream which is immediately flushed afterwards. */ protected static class ReaderThread extends Thread { - + private InputStream fInputStream; private OutputStream fOutputStream; private boolean fFinished = false; - private String lineSeparator; + private String lineSeparator; /* * outputStream can be null */ public ReaderThread(ThreadGroup group, String name, InputStream in, OutputStream out) { super(group, name); - fOutputStream= out; - fInputStream= in; + fOutputStream = out; + fInputStream = in; setDaemon(true); - lineSeparator = System.getProperty("line.separator"); //$NON-NLS-1$ + lineSeparator = System.getProperty("line.separator"); //$NON-NLS-1$ } - + public void run() { + byte[] buffer = new byte[1024]; + int len; try { - BufferedReader reader = new BufferedReader(new InputStreamReader(fInputStream)); - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fOutputStream)); - String line; - while ((line = reader.readLine()) != null) { - line += lineSeparator; - char[] array = line.toCharArray(); - writer.write(array, 0, array.length); - writer.flush(); + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(fInputStream)); + String line; + while ((line = reader.readLine()) != null) { + line += lineSeparator; + fOutputStream.write(line.getBytes()); + } + } catch (IOException x) { + // ignore + } finally { + try { + // writer.flush(); + fOutputStream.flush(); + } catch (IOException e) { + // ignore + } + try { + fInputStream.close(); + } catch (IOException e) { + // ignore + } } - } catch (IOException x) { - // ignore } finally { - try { - fInputStream.close(); - } catch (IOException e) { - // ignore - } - try { - fOutputStream.close(); - } catch (IOException e) { - // ignore - } - complete(); + complete(); } } - + public synchronized boolean finished() { return fFinished; } - + public synchronized void waitFor() { while (!fFinished) { try { @@ -81,57 +81,68 @@ public class ProcessClosure { } } } - + public synchronized void complete() { fFinished = true; notify(); } + + public void close() { + try { + fOutputStream.close(); + } catch (IOException e) { + // ignore + } + } } - - protected static int fCounter= 0; - + + protected static int fCounter = 0; + protected Process fProcess; protected OutputStream fOutput; protected OutputStream fError; - + protected ReaderThread fOutputReader; - protected ReaderThread fErrorReader; - + protected ReaderThread fErrorReader; + /** - * Creates a process closure and connects the launched process with - * a console document. - * @param outputStream prcess stdout is written to this stream. Can be null, if - * not interested in reading the output - * @param errorStream prcess stderr is written to this stream. Can be null, if - * not interested in reading the output + * Creates a process closure and connects the launched process with a + * console document. + * + * @param outputStream + * prcess stdout is written to this stream. Can be + * null, if not interested in reading the output + * @param errorStream + * prcess stderr is written to this stream. Can be + * null, if not interested in reading the output */ public ProcessClosure(Process process, OutputStream outputStream, OutputStream errorStream) { - fProcess= process; - fOutput= outputStream; - fError= errorStream; + fProcess = process; + fOutput = outputStream; + fError = errorStream; } - + /** * Live links the launched process with the configured in/out streams using * reader threads. */ public void runNonBlocking() { - ThreadGroup group= new ThreadGroup("CBuilder" + fCounter++); //$NON-NLS-1$ - - InputStream stdin= fProcess.getInputStream(); - InputStream stderr= fProcess.getErrorStream(); - - fOutputReader= new ReaderThread(group, "OutputReader", stdin, fOutput); //$NON-NLS-1$ - fErrorReader= new ReaderThread(group, "ErrorReader", stderr, fError); //$NON-NLS-1$ - + ThreadGroup group = new ThreadGroup("CBuilder" + fCounter++); //$NON-NLS-1$ + + InputStream stdin = fProcess.getInputStream(); + InputStream stderr = fProcess.getErrorStream(); + + fOutputReader = new ReaderThread(group, "OutputReader", stdin, fOutput); //$NON-NLS-1$ + fErrorReader = new ReaderThread(group, "ErrorReader", stderr, fError); //$NON-NLS-1$ + fOutputReader.start(); fErrorReader.start(); } - + public void runBlocking() { runNonBlocking(); - + boolean finished = false; while (!finished) { try { @@ -146,44 +157,57 @@ public class ProcessClosure { //System.err.println("Closure exception " +e); } } - + // @@@FIXME: Windows 2000 is screwed; double-check using output threads if (!fOutputReader.finished()) { fOutputReader.waitFor(); } - + if (!fErrorReader.finished()) { fErrorReader.waitFor(); } - - // it seems that thread termination and stream closing is working without + + fOutputReader.close(); + fErrorReader.close(); + // it seems that thread termination and stream closing is working + // without // any help - fProcess= null; - fOutputReader= null; - fErrorReader= null; + fProcess = null; + fOutputReader = null; + fErrorReader = null; } - - + public boolean isAlive() { if (fProcess != null) { if (fOutputReader.isAlive() || fErrorReader.isAlive()) { return true; - } else { - fProcess= null; - fOutputReader= null; - fErrorReader= null; } + fProcess = null; + fOutputReader.close(); + fErrorReader.close(); + fOutputReader = null; + fErrorReader = null; } return false; } - + /** * Forces the termination the launched process */ public void terminate() { if (fProcess != null) { fProcess.destroy(); - fProcess= null; + fProcess = null; } + if (!fOutputReader.finished()) { + fOutputReader.waitFor(); + } + if (!fErrorReader.finished()) { + fErrorReader.waitFor(); + } + fOutputReader.close(); + fErrorReader.close(); + fOutputReader = null; + fErrorReader = null; } -} +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsoleManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsoleManager.java index b10b2f6dee7..971fd08b6db 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsoleManager.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsoleManager.java @@ -53,7 +53,7 @@ public class BuildConsoleManager implements IBuildConsoleManager, IResourceChang static public final int BUILD_STREAM_TYPE_INFO = 0; static public final int BUILD_STREAM_TYPE_OUTPUT = 1; static public final int BUILD_STREAM_TYPE_ERROR = 2; - + public BuildConsoleManager() { } @@ -79,37 +79,32 @@ public class BuildConsoleManager implements IBuildConsoleManager, IResourceChang * front. */ protected void showConsole() { - CUIPlugin.getStandardDisplay().asyncExec(new Runnable() { - - public void run() { - IWorkbenchWindow window = CUIPlugin.getActiveWorkbenchWindow(); - if (window != null) { - IWorkbenchPage page = window.getActivePage(); - if (page != null) { - IViewPart consoleView = page.findView(IConsoleConstants.ID_CONSOLE_VIEW); - if (consoleView == null && BuildConsolePreferencePage.isAutoOpenConsole()) { - IWorkbenchPart activePart = page.getActivePart(); - try { - consoleView = page.showView(IConsoleConstants.ID_CONSOLE_VIEW); - } catch (PartInitException pie) { - CUIPlugin.getDefault().log(pie); - } - //restore focus stolen by the creation of the - // console - page.activate(activePart); - } else { - boolean bringToTop = shouldBringToTop(consoleView); - if (bringToTop) { - page.bringToTop(consoleView); - } - } - if (consoleView instanceof IConsoleView) { - ((IConsoleView)consoleView).display(fConsole); - } + IWorkbenchWindow window = CUIPlugin.getActiveWorkbenchWindow(); + if (window != null) { + IWorkbenchPage page = window.getActivePage(); + if (page != null) { + IViewPart consoleView = page.findView(IConsoleConstants.ID_CONSOLE_VIEW); + if (consoleView == null && BuildConsolePreferencePage.isAutoOpenConsole()) { + IWorkbenchPart activePart = page.getActivePart(); + try { + consoleView = page.showView(IConsoleConstants.ID_CONSOLE_VIEW); + } catch (PartInitException pie) { + CUIPlugin.getDefault().log(pie); + } + //restore focus stolen by the creation of the + // console + page.activate(activePart); + } else { + boolean bringToTop = shouldBringToTop(consoleView); + if (bringToTop) { + page.bringToTop(consoleView); } } + if (consoleView instanceof IConsoleView) { + ((IConsoleView)consoleView).display(fConsole); + } } - }); + } } boolean shouldBringToTop(IViewPart consoleView) { @@ -225,14 +220,14 @@ public class BuildConsoleManager implements IBuildConsoleManager, IResourceChang errorColor = newColor; } } - + public BuildConsoleStream getStream(int type) throws CoreException { - switch(type) { - case BUILD_STREAM_TYPE_ERROR: + switch (type) { + case BUILD_STREAM_TYPE_ERROR : return errorStream; - case BUILD_STREAM_TYPE_INFO: + case BUILD_STREAM_TYPE_INFO : return infoStream; - case BUILD_STREAM_TYPE_OUTPUT: + case BUILD_STREAM_TYPE_OUTPUT : return outputStream; } throw new CoreException(new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, -1, "No Such Console", null)); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePage.java index b5396d20c1d..458aadffe7e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePage.java @@ -117,20 +117,14 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope public void consoleChange(IBuildConsoleEvent event) { if (event.getType() == IBuildConsoleEvent.CONSOLE_START || event.getType() == IBuildConsoleEvent.CONSOLE_CLOSE) { if (isAvailable()) { - Display display = getControl().getDisplay(); if (event.getType() == IBuildConsoleEvent.CONSOLE_CLOSE && getProject() != event.getProject()) { return; } setProject(event.getProject()); - display.asyncExec(new Runnable() { - - public void run() { - if (isAvailable()) { - setDocument(); - getConsole().setTitle(getProject()); - } - } - }); + if (isAvailable()) { + setDocument(); + getConsole().setTitle(getProject()); + } } } } @@ -178,14 +172,14 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope * Fill the context menu * * @param menu - * menu + * menu */ protected void contextMenuAboutToShow(IMenuManager menu) { - menu.add((IAction) fGlobalActions.get(ActionFactory.COPY.getId())); - menu.add((IAction) fGlobalActions.get(ActionFactory.SELECT_ALL.getId())); + menu.add((IAction)fGlobalActions.get(ActionFactory.COPY.getId())); + menu.add((IAction)fGlobalActions.get(ActionFactory.SELECT_ALL.getId())); menu.add(new Separator("FIND")); //$NON-NLS-1$ - menu.add((IAction) fGlobalActions.get(ActionFactory.FIND.getId())); - menu.add((IAction) fGlobalActions.get(ITextEditorActionConstants.GOTO_LINE)); + menu.add((IAction)fGlobalActions.get(ActionFactory.FIND.getId())); + menu.add((IAction)fGlobalActions.get(ITextEditorActionConstants.GOTO_LINE)); menu.add(fClearOutputAction); menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } @@ -200,7 +194,7 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope final String property = event.getProperty(); if (BuildConsole.P_STREAM_COLOR.equals(property) && source instanceof BuildConsoleStream) { - BuildConsoleStream stream = (BuildConsoleStream) source; + BuildConsoleStream stream = (BuildConsoleStream)source; if (stream.getConsole().equals(getConsole()) && getControl() != null) { Display display = getControl().getDisplay(); display.asyncExec(new Runnable() { @@ -233,8 +227,7 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope action.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY)); action.setDisabledImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( ISharedImages.IMG_TOOL_COPY_DISABLED)); - action.setHoverImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( - ISharedImages.IMG_TOOL_COPY)); + action.setHoverImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY)); setGlobalAction(actionBars, ActionFactory.COPY.getId(), action); action = new TextViewerAction(getViewer(), ITextOperationTarget.SELECT_ALL); action.configureAction(ConsoleMessages.getString("BuildConsolePage.Select_&All@Ctrl+A_12"), //$NON-NLS-1$ @@ -255,14 +248,14 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope protected void updateSelectionDependentActions() { Iterator iterator = fSelectionActions.iterator(); while (iterator.hasNext()) { - updateAction((String) iterator.next()); + updateAction((String)iterator.next()); } } protected void updateAction(String actionId) { - IAction action = (IAction) fGlobalActions.get(actionId); + IAction action = (IAction)fGlobalActions.get(actionId); if (action instanceof IUpdate) { - ((IUpdate) action).update(); + ((IUpdate)action).update(); } } @@ -320,19 +313,19 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope IProject convertSelectionToProject(ISelection selection) { IProject project = null; - if (selection == null || !(selection instanceof IStructuredSelection)) { + if (selection == null || ! (selection instanceof IStructuredSelection)) { return project; } - IStructuredSelection ssel = (IStructuredSelection) selection; + IStructuredSelection ssel = (IStructuredSelection)selection; Object element = ssel.getFirstElement(); if (element instanceof IAdaptable) { - IAdaptable input = (IAdaptable) element; + IAdaptable input = (IAdaptable)element; if (input != null) { IResource resource = null; if (input instanceof IResource) { - resource = (IResource) input; + resource = (IResource)input; } else { - resource = (IResource) input.getAdapter(IResource.class); + resource = (IResource)input.getAdapter(IResource.class); } if (resource != null) { project = resource.getProject(); @@ -380,7 +373,7 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope * Sets the font for this page. * * @param font - * font + * font */ protected void setFont(Font font) { getViewer().getTextWidget().setFont(font); @@ -390,7 +383,7 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope * Sets the tab width for this page. * * @param int - * tab width + * tab width */ protected void setTabs(int tabs) { getViewer().getTextWidget().setTabs(tabs); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePartitioner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePartitioner.java index 5151f39d6c5..61d9911c142 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePartitioner.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/buildconsole/BuildConsolePartitioner.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Vector; import org.eclipse.cdt.core.ConsoleOutputStream; import org.eclipse.cdt.core.resources.IConsole; @@ -30,6 +31,7 @@ import org.eclipse.jface.text.Region; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.console.ConsolePlugin; public class BuildConsolePartitioner implements @@ -54,6 +56,55 @@ public class BuildConsolePartitioner boolean killed; BuildConsoleManager fManager; + /** + * A queue of stream entries written to standard out and standard err. + * Entries appended to the end of the queue and removed from the front. + * Intentionally a vector to obtain synchronization as entries are added and + * removed. + */ + private Vector fQueue = new Vector(5); + + private boolean fAppending; + + class StreamEntry { + + /** + * Identifier of the stream written to. + */ + private BuildConsoleStream fStream; + /** + * The text written + */ + private StringBuffer fText = null; + + StreamEntry(String text, BuildConsoleStream stream) { + fText = new StringBuffer(text); + fStream = stream; + } + + /** + * Returns the stream identifier + */ + public BuildConsoleStream getStream() { + return fStream; + } + + public void appendText(String text) { + fText.append(text); + } + + public int size() { + return fText.length(); + } + + /** + * Returns the text written + */ + public String getText() { + return fText.toString(); + } + } + public BuildConsolePartitioner(BuildConsoleManager manager) { fManager = manager; fMaxLines = BuildConsolePreferencePage.buildConsoleLines(); @@ -71,19 +122,40 @@ public class BuildConsolePartitioner * the stream to append to */ - public void appendToDocument(final String text, final BuildConsoleStream stream) { - if( text.length() == 0 ) - return; - + public void appendToDocument(String text, BuildConsoleStream stream) { + boolean addToQueue = true; + synchronized (fQueue) { + int i = fQueue.size(); + if (i > 0) { + StreamEntry entry = (StreamEntry)fQueue.get(i - 1); + // if last stream is the same and we have not exceeded our + // display write limit, append. + if (entry.getStream() == stream && entry.size() < 10000) { + entry.appendText(text); + addToQueue = false; + } + } + if (addToQueue) { + fQueue.add(new StreamEntry(text, stream)); + } + } Runnable r = new Runnable() { public void run() { - fLastStream = stream; + StreamEntry entry; try { - if (stream == null) { - fDocument.set(text); + entry = (StreamEntry)fQueue.remove(0); + } catch (ArrayIndexOutOfBoundsException e) { + return; + } + fLastStream = entry.getStream(); + System.out.println(entry.getText().length()); + try { + warnOfContentChange(fLastStream); + if (fLastStream == null) { + fDocument.set(entry.getText()); } else { - fDocument.replace(fDocument.getLength(), 0, text); + fDocument.replace(fDocument.getLength(), 0, entry.getText()); checkOverflow(); } } catch (BadLocationException e) { @@ -91,11 +163,18 @@ public class BuildConsolePartitioner } }; Display display = CUIPlugin.getStandardDisplay(); - if (display != null) { + if (addToQueue && display != null) { display.asyncExec(r); } } + private void warnOfContentChange(BuildConsoleStream stream) { + if (stream != null) { + ConsolePlugin.getDefault().getConsoleManager().warnOfContentChange(stream.getConsole()); + } + fManager.showConsole(); + } + public IDocument getDocument() { return fDocument; } @@ -285,11 +364,20 @@ public class BuildConsolePartitioner } } - public void start(IProject project) { + public void start(final IProject project) { + Display display = CUIPlugin.getStandardDisplay(); + if (display != null) { + display.asyncExec(new Runnable() { + + public void run() { + fManager.startConsoleActivity(project); + } + }); + } + if (BuildConsolePreferencePage.isClearBuildConsole()) { appendToDocument("", null); //$NON-NLS-1$ } - fManager.startConsoleActivity(project); } public class BuildOutputStream extends ConsoleOutputStream { @@ -301,19 +389,14 @@ public class BuildConsolePartitioner } public void flush() throws IOException { - if( fBuffer.length() > 0 ) - appendToDocument(readBuffer(), fStream); - fManager.showConsole(); } public void close() throws IOException { flush(); } - public synchronized void write(byte[] b, int off, int len) throws IOException { - super.write(b, off, len); - if( fBuffer.length() > 4096 ) - flush(); + public void write(byte[] b, int off, int len) throws IOException { + appendToDocument(new String(b, off, len), fStream); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/BuildConsolePreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/BuildConsolePreferencePage.java index 7ab20fabab0..657b74c00d6 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/BuildConsolePreferencePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/BuildConsolePreferencePage.java @@ -123,8 +123,8 @@ public class BuildConsolePreferencePage extends FieldEditorPreferencePage implem public static void initDefaults(IPreferenceStore prefs) { prefs.setDefault(PREF_CLEAR_CONSOLE, true); - prefs.setDefault(PREF_AUTO_OPEN_CONSOLE, false); - prefs.setDefault(PREF_CONSOLE_ON_TOP, true); + prefs.setDefault(PREF_AUTO_OPEN_CONSOLE, true); + prefs.setDefault(PREF_CONSOLE_ON_TOP, false); prefs.setDefault(PREF_BUILDCONSOLE_LINES, 500); prefs.setDefault(PREF_BUILDCONSOLE_TAB_WIDTH, 4); PreferenceConverter.setDefault(prefs, PREF_BUILDCONSOLE_OUTPUT_COLOR, new RGB(0, 0, 0));