1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

improve build ouptut console streaming

This commit is contained in:
David Inglis 2004-07-14 01:26:22 +00:00
parent 425adf04b8
commit 6144b2233d
6 changed files with 304 additions and 277 deletions

View file

@ -1,14 +1,11 @@
package org.eclipse.cdt.core; package org.eclipse.cdt.core;
/* /*
* (c) Copyright IBM Corp. 2000, 2001. * (c) Copyright IBM Corp. 2000, 2001. All Rights Reserved.
* All Rights Reserved.
*/ */
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Properties; import java.util.Properties;
import org.eclipse.cdt.internal.core.ProcessClosure; import org.eclipse.cdt.internal.core.ProcessClosure;
@ -17,12 +14,11 @@ import org.eclipse.cdt.utils.spawner.ProcessFactory;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
public class CommandLauncher { public class CommandLauncher {
public final static int COMMAND_CANCELED= 1; public final static int COMMAND_CANCELED = 1;
public final static int ILLEGAL_COMMAND= -1; public final static int ILLEGAL_COMMAND = -1;
public final static int OK= 0; public final static int OK = 0;
protected Process fProcess; protected Process fProcess;
protected boolean fShowCommand; protected boolean fShowCommand;
@ -33,19 +29,18 @@ public class CommandLauncher {
private String lineSeparator; private String lineSeparator;
/** /**
* The number of milliseconds to pause * The number of milliseconds to pause between polling.
* between polling.
*/ */
protected static final long DELAY = 50L; protected static final long DELAY = 50L;
/** /**
* Creates a new launcher * Creates a new launcher Fills in stderr and stdout output to the given
* Fills in stderr and stdout output to the given streams. * streams. Streams can be set to <code>null</code>, if output not
* Streams can be set to <code>null</code>, if output not required * required
*/ */
public CommandLauncher() { public CommandLauncher() {
fProcess= null; fProcess = null;
fShowCommand= false; fShowCommand = false;
lineSeparator = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ lineSeparator = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
} }
@ -53,7 +48,7 @@ public class CommandLauncher {
* Sets if the command should be printed out first before executing * Sets if the command should be printed out first before executing
*/ */
public void showCommand(boolean show) { public void showCommand(boolean show) {
fShowCommand= show; fShowCommand = show;
} }
public String getErrorMessage() { public String getErrorMessage() {
@ -97,12 +92,12 @@ public class CommandLauncher {
public Process execute(IPath commandPath, String[] args, String[] env, IPath changeToDirectory) { public Process execute(IPath commandPath, String[] args, String[] env, IPath changeToDirectory) {
try { try {
// add platform specific arguments (shell invocation) // add platform specific arguments (shell invocation)
fCommandArgs= constructCommandArray(commandPath.toOSString(), args); fCommandArgs = constructCommandArray(commandPath.toOSString(), args);
fProcess= ProcessFactory.getFactory().exec(fCommandArgs, env, changeToDirectory.toFile()); fProcess = ProcessFactory.getFactory().exec(fCommandArgs, env, changeToDirectory.toFile());
fErrorMessage= ""; //$NON-NLS-1$ fErrorMessage = ""; //$NON-NLS-1$
} catch (IOException e) { } catch (IOException e) {
setErrorMessage(e.getMessage()); setErrorMessage(e.getMessage());
fProcess= null; fProcess = null;
} }
return fProcess; return fProcess;
} }
@ -119,16 +114,16 @@ public class CommandLauncher {
return ILLEGAL_COMMAND; return ILLEGAL_COMMAND;
} }
ProcessClosure closure= new ProcessClosure(fProcess, out, err); ProcessClosure closure = new ProcessClosure(fProcess, out, err);
closure.runBlocking(); // a blocking call closure.runBlocking(); // a blocking call
return OK; return OK;
} }
/** /**
* Reads output form the process to the streams. A progress monitor is polled to * Reads output form the process to the streams. A progress monitor is
* test if the cancel button has been pressed. * polled to test if the cancel button has been pressed. Destroys the
* Destroys the process if the monitor becomes canceled * process if the monitor becomes canceled override to implement a different
* override to implement a different way to read the process inputs * way to read the process inputs
*/ */
public int waitAndRead(OutputStream output, OutputStream err, IProgressMonitor monitor) { public int waitAndRead(OutputStream output, OutputStream err, IProgressMonitor monitor) {
if (fShowCommand) { if (fShowCommand) {
@ -139,55 +134,13 @@ public class CommandLauncher {
return ILLEGAL_COMMAND; return ILLEGAL_COMMAND;
} }
PipedOutputStream errOutPipe = new PipedOutputStream(); ProcessClosure closure = new ProcessClosure(fProcess, output, err);
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);
closure.runNonBlocking(); closure.runNonBlocking();
byte buffer[] = new byte[1024];
int nbytes;
int waited = 0;
boolean flushed = false;
while (!monitor.isCanceled() && closure.isAlive()) { while (!monitor.isCanceled() && closure.isAlive()) {
nbytes = 0;
try { try {
if ( errInPipe.available() > 0 ) { Thread.sleep(DELAY);
nbytes = errInPipe.read(buffer); } catch (InterruptedException ie) {
err.write(buffer, 0, nbytes); // ignore
}
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;
} }
} }
@ -203,29 +156,8 @@ public class CommandLauncher {
try { try {
fProcess.waitFor(); fProcess.waitFor();
} catch (InterruptedException e) { } catch (InterruptedException e) {
//System.err.println("Closure exception " +e); // ignore
//e.printStackTrace();
} }
// 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; return state;
} }
@ -244,7 +176,7 @@ public class CommandLauncher {
protected String getCommandLine(String[] commandArgs) { protected String getCommandLine(String[] commandArgs) {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
if (fCommandArgs != null) { 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(commandArgs[i]);
buf.append(' '); buf.append(' ');
} }

View file

@ -6,23 +6,20 @@ package org.eclipse.cdt.internal.core;
*/ */
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter;
/** /**
* Bundled state of a launched process including the threads linking the process in/output * Bundled state of a launched process including the threads linking the process
* to console documents. * in/output to console documents.
*/ */
public class ProcessClosure { public class ProcessClosure {
/** /**
* Thread which continuously reads from a input stream and pushes the read data * Thread which continuously reads from a input stream and pushes the read
* to an output stream which is immediately flushed afterwards. * data to an output stream which is immediately flushed afterwards.
*/ */
protected static class ReaderThread extends Thread { protected static class ReaderThread extends Thread {
@ -35,36 +32,39 @@ public class ProcessClosure {
*/ */
public ReaderThread(ThreadGroup group, String name, InputStream in, OutputStream out) { public ReaderThread(ThreadGroup group, String name, InputStream in, OutputStream out) {
super(group, name); super(group, name);
fOutputStream= out; fOutputStream = out;
fInputStream= in; fInputStream = in;
setDaemon(true); setDaemon(true);
lineSeparator = System.getProperty("line.separator"); //$NON-NLS-1$ lineSeparator = System.getProperty("line.separator"); //$NON-NLS-1$
} }
public void run() { public void run() {
byte[] buffer = new byte[1024];
int len;
try { try {
BufferedReader reader = new BufferedReader(new InputStreamReader(fInputStream)); try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fOutputStream)); BufferedReader reader = new BufferedReader(new InputStreamReader(fInputStream));
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
line += lineSeparator; line += lineSeparator;
char[] array = line.toCharArray(); fOutputStream.write(line.getBytes());
writer.write(array, 0, array.length); }
writer.flush(); } 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 { } finally {
try {
fInputStream.close();
} catch (IOException e) {
// ignore
}
try {
fOutputStream.close();
} catch (IOException e) {
// ignore
}
complete(); complete();
} }
} }
@ -86,9 +86,17 @@ public class ProcessClosure {
fFinished = true; fFinished = true;
notify(); 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 Process fProcess;
@ -99,17 +107,20 @@ public class ProcessClosure {
protected ReaderThread fErrorReader; protected ReaderThread fErrorReader;
/** /**
* Creates a process closure and connects the launched process with * Creates a process closure and connects the launched process with a
* a console document. * console document.
* @param outputStream prcess stdout is written to this stream. Can be <code>null</code>, if *
* not interested in reading the output * @param outputStream
* @param errorStream prcess stderr is written to this stream. Can be <code>null</code>, if * prcess stdout is written to this stream. Can be
* not interested in reading the output * <code>null</code>, if not interested in reading the output
* @param errorStream
* prcess stderr is written to this stream. Can be
* <code>null</code>, if not interested in reading the output
*/ */
public ProcessClosure(Process process, OutputStream outputStream, OutputStream errorStream) { public ProcessClosure(Process process, OutputStream outputStream, OutputStream errorStream) {
fProcess= process; fProcess = process;
fOutput= outputStream; fOutput = outputStream;
fError= errorStream; fError = errorStream;
} }
/** /**
@ -117,13 +128,13 @@ public class ProcessClosure {
* reader threads. * reader threads.
*/ */
public void runNonBlocking() { public void runNonBlocking() {
ThreadGroup group= new ThreadGroup("CBuilder" + fCounter++); //$NON-NLS-1$ ThreadGroup group = new ThreadGroup("CBuilder" + fCounter++); //$NON-NLS-1$
InputStream stdin= fProcess.getInputStream(); InputStream stdin = fProcess.getInputStream();
InputStream stderr= fProcess.getErrorStream(); InputStream stderr = fProcess.getErrorStream();
fOutputReader= new ReaderThread(group, "OutputReader", stdin, fOutput); //$NON-NLS-1$ fOutputReader = new ReaderThread(group, "OutputReader", stdin, fOutput); //$NON-NLS-1$
fErrorReader= new ReaderThread(group, "ErrorReader", stderr, fError); //$NON-NLS-1$ fErrorReader = new ReaderThread(group, "ErrorReader", stderr, fError); //$NON-NLS-1$
fOutputReader.start(); fOutputReader.start();
fErrorReader.start(); fErrorReader.start();
@ -156,23 +167,26 @@ public class ProcessClosure {
fErrorReader.waitFor(); 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 // any help
fProcess= null; fProcess = null;
fOutputReader= null; fOutputReader = null;
fErrorReader= null; fErrorReader = null;
} }
public boolean isAlive() { public boolean isAlive() {
if (fProcess != null) { if (fProcess != null) {
if (fOutputReader.isAlive() || fErrorReader.isAlive()) { if (fOutputReader.isAlive() || fErrorReader.isAlive()) {
return true; return true;
} else {
fProcess= null;
fOutputReader= null;
fErrorReader= null;
} }
fProcess = null;
fOutputReader.close();
fErrorReader.close();
fOutputReader = null;
fErrorReader = null;
} }
return false; return false;
} }
@ -183,7 +197,17 @@ public class ProcessClosure {
public void terminate() { public void terminate() {
if (fProcess != null) { if (fProcess != null) {
fProcess.destroy(); fProcess.destroy();
fProcess= null; fProcess = null;
} }
if (!fOutputReader.finished()) {
fOutputReader.waitFor();
}
if (!fErrorReader.finished()) {
fErrorReader.waitFor();
}
fOutputReader.close();
fErrorReader.close();
fOutputReader = null;
fErrorReader = null;
} }
} }

View file

@ -79,37 +79,32 @@ public class BuildConsoleManager implements IBuildConsoleManager, IResourceChang
* front. * front.
*/ */
protected void showConsole() { protected void showConsole() {
CUIPlugin.getStandardDisplay().asyncExec(new Runnable() { IWorkbenchWindow window = CUIPlugin.getActiveWorkbenchWindow();
if (window != null) {
public void run() { IWorkbenchPage page = window.getActivePage();
IWorkbenchWindow window = CUIPlugin.getActiveWorkbenchWindow(); if (page != null) {
if (window != null) { IViewPart consoleView = page.findView(IConsoleConstants.ID_CONSOLE_VIEW);
IWorkbenchPage page = window.getActivePage(); if (consoleView == null && BuildConsolePreferencePage.isAutoOpenConsole()) {
if (page != null) { IWorkbenchPart activePart = page.getActivePart();
IViewPart consoleView = page.findView(IConsoleConstants.ID_CONSOLE_VIEW); try {
if (consoleView == null && BuildConsolePreferencePage.isAutoOpenConsole()) { consoleView = page.showView(IConsoleConstants.ID_CONSOLE_VIEW);
IWorkbenchPart activePart = page.getActivePart(); } catch (PartInitException pie) {
try { CUIPlugin.getDefault().log(pie);
consoleView = page.showView(IConsoleConstants.ID_CONSOLE_VIEW); }
} catch (PartInitException pie) { //restore focus stolen by the creation of the
CUIPlugin.getDefault().log(pie); // console
} page.activate(activePart);
//restore focus stolen by the creation of the } else {
// console boolean bringToTop = shouldBringToTop(consoleView);
page.activate(activePart); if (bringToTop) {
} else { page.bringToTop(consoleView);
boolean bringToTop = shouldBringToTop(consoleView);
if (bringToTop) {
page.bringToTop(consoleView);
}
}
if (consoleView instanceof IConsoleView) {
((IConsoleView)consoleView).display(fConsole);
}
} }
} }
if (consoleView instanceof IConsoleView) {
((IConsoleView)consoleView).display(fConsole);
}
} }
}); }
} }
boolean shouldBringToTop(IViewPart consoleView) { boolean shouldBringToTop(IViewPart consoleView) {
@ -227,12 +222,12 @@ public class BuildConsoleManager implements IBuildConsoleManager, IResourceChang
} }
public BuildConsoleStream getStream(int type) throws CoreException { public BuildConsoleStream getStream(int type) throws CoreException {
switch(type) { switch (type) {
case BUILD_STREAM_TYPE_ERROR: case BUILD_STREAM_TYPE_ERROR :
return errorStream; return errorStream;
case BUILD_STREAM_TYPE_INFO: case BUILD_STREAM_TYPE_INFO :
return infoStream; return infoStream;
case BUILD_STREAM_TYPE_OUTPUT: case BUILD_STREAM_TYPE_OUTPUT :
return outputStream; return outputStream;
} }
throw new CoreException(new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, -1, "No Such Console", null)); //$NON-NLS-1$ throw new CoreException(new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, -1, "No Such Console", null)); //$NON-NLS-1$

View file

@ -117,20 +117,14 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope
public void consoleChange(IBuildConsoleEvent event) { public void consoleChange(IBuildConsoleEvent event) {
if (event.getType() == IBuildConsoleEvent.CONSOLE_START || event.getType() == IBuildConsoleEvent.CONSOLE_CLOSE) { if (event.getType() == IBuildConsoleEvent.CONSOLE_START || event.getType() == IBuildConsoleEvent.CONSOLE_CLOSE) {
if (isAvailable()) { if (isAvailable()) {
Display display = getControl().getDisplay();
if (event.getType() == IBuildConsoleEvent.CONSOLE_CLOSE && getProject() != event.getProject()) { if (event.getType() == IBuildConsoleEvent.CONSOLE_CLOSE && getProject() != event.getProject()) {
return; return;
} }
setProject(event.getProject()); setProject(event.getProject());
display.asyncExec(new Runnable() { if (isAvailable()) {
setDocument();
public void run() { 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 * Fill the context menu
* *
* @param menu * @param menu
* menu * menu
*/ */
protected void contextMenuAboutToShow(IMenuManager menu) { protected void contextMenuAboutToShow(IMenuManager menu) {
menu.add((IAction) fGlobalActions.get(ActionFactory.COPY.getId())); menu.add((IAction)fGlobalActions.get(ActionFactory.COPY.getId()));
menu.add((IAction) fGlobalActions.get(ActionFactory.SELECT_ALL.getId())); menu.add((IAction)fGlobalActions.get(ActionFactory.SELECT_ALL.getId()));
menu.add(new Separator("FIND")); //$NON-NLS-1$ menu.add(new Separator("FIND")); //$NON-NLS-1$
menu.add((IAction) fGlobalActions.get(ActionFactory.FIND.getId())); menu.add((IAction)fGlobalActions.get(ActionFactory.FIND.getId()));
menu.add((IAction) fGlobalActions.get(ITextEditorActionConstants.GOTO_LINE)); menu.add((IAction)fGlobalActions.get(ITextEditorActionConstants.GOTO_LINE));
menu.add(fClearOutputAction); menu.add(fClearOutputAction);
menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
} }
@ -200,7 +194,7 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope
final String property = event.getProperty(); final String property = event.getProperty();
if (BuildConsole.P_STREAM_COLOR.equals(property) && source instanceof BuildConsoleStream) { 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) { if (stream.getConsole().equals(getConsole()) && getControl() != null) {
Display display = getControl().getDisplay(); Display display = getControl().getDisplay();
display.asyncExec(new Runnable() { 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.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
action.setDisabledImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( action.setDisabledImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
ISharedImages.IMG_TOOL_COPY_DISABLED)); ISharedImages.IMG_TOOL_COPY_DISABLED));
action.setHoverImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( action.setHoverImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
ISharedImages.IMG_TOOL_COPY));
setGlobalAction(actionBars, ActionFactory.COPY.getId(), action); setGlobalAction(actionBars, ActionFactory.COPY.getId(), action);
action = new TextViewerAction(getViewer(), ITextOperationTarget.SELECT_ALL); action = new TextViewerAction(getViewer(), ITextOperationTarget.SELECT_ALL);
action.configureAction(ConsoleMessages.getString("BuildConsolePage.Select_&All@Ctrl+A_12"), //$NON-NLS-1$ 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() { protected void updateSelectionDependentActions() {
Iterator iterator = fSelectionActions.iterator(); Iterator iterator = fSelectionActions.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
updateAction((String) iterator.next()); updateAction((String)iterator.next());
} }
} }
protected void updateAction(String actionId) { protected void updateAction(String actionId) {
IAction action = (IAction) fGlobalActions.get(actionId); IAction action = (IAction)fGlobalActions.get(actionId);
if (action instanceof IUpdate) { 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 convertSelectionToProject(ISelection selection) {
IProject project = null; IProject project = null;
if (selection == null || !(selection instanceof IStructuredSelection)) { if (selection == null || ! (selection instanceof IStructuredSelection)) {
return project; return project;
} }
IStructuredSelection ssel = (IStructuredSelection) selection; IStructuredSelection ssel = (IStructuredSelection)selection;
Object element = ssel.getFirstElement(); Object element = ssel.getFirstElement();
if (element instanceof IAdaptable) { if (element instanceof IAdaptable) {
IAdaptable input = (IAdaptable) element; IAdaptable input = (IAdaptable)element;
if (input != null) { if (input != null) {
IResource resource = null; IResource resource = null;
if (input instanceof IResource) { if (input instanceof IResource) {
resource = (IResource) input; resource = (IResource)input;
} else { } else {
resource = (IResource) input.getAdapter(IResource.class); resource = (IResource)input.getAdapter(IResource.class);
} }
if (resource != null) { if (resource != null) {
project = resource.getProject(); project = resource.getProject();
@ -380,7 +373,7 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope
* Sets the font for this page. * Sets the font for this page.
* *
* @param font * @param font
* font * font
*/ */
protected void setFont(Font font) { protected void setFont(Font font) {
getViewer().getTextWidget().setFont(font); getViewer().getTextWidget().setFont(font);
@ -390,7 +383,7 @@ public class BuildConsolePage extends Page implements ISelectionListener, IPrope
* Sets the tab width for this page. * Sets the tab width for this page.
* *
* @param int * @param int
* tab width * tab width
*/ */
protected void setTabs(int tabs) { protected void setTabs(int tabs) {
getViewer().getTextWidget().setTabs(tabs); getViewer().getTextWidget().setTabs(tabs);

View file

@ -12,6 +12,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Vector;
import org.eclipse.cdt.core.ConsoleOutputStream; import org.eclipse.cdt.core.ConsoleOutputStream;
import org.eclipse.cdt.core.resources.IConsole; 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.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.console.ConsolePlugin;
public class BuildConsolePartitioner public class BuildConsolePartitioner
implements implements
@ -54,6 +56,55 @@ public class BuildConsolePartitioner
boolean killed; boolean killed;
BuildConsoleManager fManager; 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) { public BuildConsolePartitioner(BuildConsoleManager manager) {
fManager = manager; fManager = manager;
fMaxLines = BuildConsolePreferencePage.buildConsoleLines(); fMaxLines = BuildConsolePreferencePage.buildConsoleLines();
@ -71,19 +122,40 @@ public class BuildConsolePartitioner
* the stream to append to * the stream to append to
*/ */
public void appendToDocument(final String text, final BuildConsoleStream stream) { public void appendToDocument(String text, BuildConsoleStream stream) {
if( text.length() == 0 ) boolean addToQueue = true;
return; 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() { Runnable r = new Runnable() {
public void run() { public void run() {
fLastStream = stream; StreamEntry entry;
try { try {
if (stream == null) { entry = (StreamEntry)fQueue.remove(0);
fDocument.set(text); } catch (ArrayIndexOutOfBoundsException e) {
return;
}
fLastStream = entry.getStream();
System.out.println(entry.getText().length());
try {
warnOfContentChange(fLastStream);
if (fLastStream == null) {
fDocument.set(entry.getText());
} else { } else {
fDocument.replace(fDocument.getLength(), 0, text); fDocument.replace(fDocument.getLength(), 0, entry.getText());
checkOverflow(); checkOverflow();
} }
} catch (BadLocationException e) { } catch (BadLocationException e) {
@ -91,11 +163,18 @@ public class BuildConsolePartitioner
} }
}; };
Display display = CUIPlugin.getStandardDisplay(); Display display = CUIPlugin.getStandardDisplay();
if (display != null) { if (addToQueue && display != null) {
display.asyncExec(r); display.asyncExec(r);
} }
} }
private void warnOfContentChange(BuildConsoleStream stream) {
if (stream != null) {
ConsolePlugin.getDefault().getConsoleManager().warnOfContentChange(stream.getConsole());
}
fManager.showConsole();
}
public IDocument getDocument() { public IDocument getDocument() {
return fDocument; 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()) { if (BuildConsolePreferencePage.isClearBuildConsole()) {
appendToDocument("", null); //$NON-NLS-1$ appendToDocument("", null); //$NON-NLS-1$
} }
fManager.startConsoleActivity(project);
} }
public class BuildOutputStream extends ConsoleOutputStream { public class BuildOutputStream extends ConsoleOutputStream {
@ -301,19 +389,14 @@ public class BuildConsolePartitioner
} }
public void flush() throws IOException { public void flush() throws IOException {
if( fBuffer.length() > 0 )
appendToDocument(readBuffer(), fStream);
fManager.showConsole();
} }
public void close() throws IOException { public void close() throws IOException {
flush(); flush();
} }
public synchronized void write(byte[] b, int off, int len) throws IOException { public void write(byte[] b, int off, int len) throws IOException {
super.write(b, off, len); appendToDocument(new String(b, off, len), fStream);
if( fBuffer.length() > 4096 )
flush();
} }
} }

View file

@ -123,8 +123,8 @@ public class BuildConsolePreferencePage extends FieldEditorPreferencePage implem
public static void initDefaults(IPreferenceStore prefs) { public static void initDefaults(IPreferenceStore prefs) {
prefs.setDefault(PREF_CLEAR_CONSOLE, true); prefs.setDefault(PREF_CLEAR_CONSOLE, true);
prefs.setDefault(PREF_AUTO_OPEN_CONSOLE, false); prefs.setDefault(PREF_AUTO_OPEN_CONSOLE, true);
prefs.setDefault(PREF_CONSOLE_ON_TOP, true); prefs.setDefault(PREF_CONSOLE_ON_TOP, false);
prefs.setDefault(PREF_BUILDCONSOLE_LINES, 500); prefs.setDefault(PREF_BUILDCONSOLE_LINES, 500);
prefs.setDefault(PREF_BUILDCONSOLE_TAB_WIDTH, 4); prefs.setDefault(PREF_BUILDCONSOLE_TAB_WIDTH, 4);
PreferenceConverter.setDefault(prefs, PREF_BUILDCONSOLE_OUTPUT_COLOR, new RGB(0, 0, 0)); PreferenceConverter.setDefault(prefs, PREF_BUILDCONSOLE_OUTPUT_COLOR, new RGB(0, 0, 0));