views:

592

answers:

1

In my RCP I show the Console and want to output different categories of output (not just STDERR and STDOUT). I have looked at and used code from both:

http://stackoverflow.com/questions/720963/eclipse-console {filter_workaround}://stackoverflow.com/questions/716615/writing-to-the-eclipse-console

I go through all the actions as prescribed: find or create a console, create the view, display the view, using the ConsoleManager. I set it up so there a handful of "categories" that the logs write to, each corresponding to a different console stored in the IConsoleManager.

The problem is, output rarely/unpredictably makes it to the consoles: when each new Console is created, I write a message on it. This only appears sometimes during debugging. All the other consoles seem to be created but never written to. Unless I make everything write to STDERR (!?).

The code below is what I have done:

package com.Jasper.util;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.IConsoleView;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;

public final class Console {
 private static Console mInstance = null;

 public static enum ConsoleType { DEFAULT, STDERR, STDOUT, OTHER, ERRORS }

 private Console () { }

 /**
  * Singleton pattern to match Eclipse's console plugin's behavior.
  * @return
  */
 public static synchronized Console getInstance() {
  if (mInstance == null)
   mInstance = new Console ();

  return mInstance;
 }

 /**
  * With the given ConsoleType enum, look for an existing/open console
  * and return it, or if it does not exist, create a new one and return it.
  * @param name One of the members of the static enum defined in Console
  * @return A non null message console
  */
 private static MessageConsole findOrCreateConsole(final String name) {
  final ConsolePlugin plugin = ConsolePlugin.getDefault();
  final IConsoleManager conMan = plugin.getConsoleManager();
  final IConsole[] existing = conMan.getConsoles();

  for (final IConsole element : existing)
   if (name.toString().compareTo(element.getName()) == 0)
    return (MessageConsole) element;

  // failed to find existing console, create one:
  final MessageConsole myConsole = new MessageConsole(name.toString(), null);
  conMan.addConsoles(new IConsole[] { myConsole });

  try {
   Write (myConsole.newMessageStream(), "Initializing: " + name + "\n");
  } catch (Exception e) {
   // Platform might not be up yet, silently ignore for now...
  }

  return myConsole;
 }

 /**
  * Used for quick writes to consoles, this is not in place of std err/out.
  * If the given console does not exist it will be created.
  * 
  * @param name
  * @param msg
  */
 public static void Write (final String name, String msg) {
    MessageConsole myConsole = findOrCreateConsole (name);
    MessageConsoleStream out = myConsole.newMessageStream ();
    out.println(msg);
 }

 public static void Write (MessageConsoleStream stream, String msg) {
  try {
   stream.write(msg);
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 /**
  * Return a new output stream for a given console. If the console does
  * not exist it will be created. 
  * @param type A console type defined in Console's ConsoleType enum.
  * @return An open stream for writing to.
  */
 public static OutputStream GetOutputStream(final String type) {
  MessageConsole ib = findOrCreateConsole (type);
  IOConsoleOutputStream mcs = ib.newOutputStream(); 
  mcs.setActivateOnWrite(true);
  return mcs;
 }

 /**
  * Create consoles for STDERR and STDOUT, redirect all output
  * to the in-application console. Should only be called once.
  * 
  */
 public static void init () {
  MessageConsole outConsole = findOrCreateConsole (ConsoleType.STDOUT.toString());
  IOConsoleOutputStream outStream = outConsole.newOutputStream();
  System.setOut(new PrintStream (outStream));

  MessageConsole errConsole = findOrCreateConsole (ConsoleType.STDERR.toString());
  IOConsoleOutputStream errStream = errConsole.newOutputStream();
  System.setErr(new PrintStream (errStream));
 }

 /**
  * Alternate way to bring up the console view. Don't know
  * which one is better / the differences.
  * @param myConsole Console to show, must not be null.
  */
 public static void ShowConsole (IConsole myConsole) {
  IWorkbench workbench = PlatformUI.getWorkbench();
  IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();

  IWorkbenchPage page = window.getActivePage();
  String id = IConsoleConstants.ID_CONSOLE_VIEW;
  IConsoleView view;
  try {
   view = (IConsoleView) page.showView(id);
   view.display(myConsole);
  } catch (PartInitException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 /**
  * Show the application console. If the given console is null, attempt
  * to find an existing console and use it. If the given console is null
  * and no existing consoles exist, exit without doing anything.
  * 
  * @param myConsole An existing console.
  */
 public static void DisplayConsole (IConsole myConsole) {

  // try to grab any old console and display it if given null
  if (myConsole == null) {
   final ConsolePlugin plugin = ConsolePlugin.getDefault();
   final IConsoleManager conMan = plugin.getConsoleManager();
   final IConsole[] existing = conMan.getConsoles();

   if (existing.length == 0)
    return;

   for (final IConsole element : existing)
    myConsole = element;
  }

  ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] {myConsole});
  ConsolePlugin.getDefault().getConsoleManager().showConsoleView(myConsole);
 }

 /**
  * Show the console view with the given ConsoleType. Will not
  * create one if one does not already exist.
  * 
  * @param type Non-null enum of existing console (stdout/err probably safe)
  */
 public static void DisplayConsole (final String type) {

  final ConsolePlugin plugin = ConsolePlugin.getDefault();
  final IConsoleManager conMan = plugin.getConsoleManager();
  final IConsole[] existing = conMan.getConsoles();

  for (final IConsole element : existing)
   if (type.toString().compareTo(element.getName()) == 0) {
    ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] {element});
    ConsolePlugin.getDefault().getConsoleManager().showConsoleView(element);
    return;
   }
 }

}

Any ideas?

+1  A: 

Writing the output (stderr or stdout) maybe happening through a callback or some other thread. Do the writing to the console as follows - it may help:

public void writeToConsole(String lineToConsole) { final String lineToWrite = lineToConsole; Display.getDefault().asyncExec(new IRunnable({

public void run() { try { if (!stream.isClosed()) stream.write(lineToWrite); } catch (Exception ex) { ///if you want to - do something } )}; }

Vijay