Jan 14 2009

Launching a Java program inside an Eclipse plug-in (and capture its output)

Category: Eclipse OpenGL Pack, Pluginsramon @ 9:43 am

A few days ago I got involved in the development of a new OpenGL plug-in for Eclipse: Eclipse OpenGL Pack.

My first task is to create some window where the OpenGL capabilities of the current system are shown. Something similar to what NetBeans OpenGL pack does (i.e. this screenshot).

One of the features that I like about the plug-in is that new OpenGL bindings can be added (through extensions points), so there’s no only one binding like NetBeans OpenGL pack.

Unfortunately, at the same time this feature means some more “headaches” for developing the plug-in. It means that we don’t know what library the developer will choose to use OpenGL.

We decided that an option, in order to retrieve the OpenGL characteristics of the system, is to run a small Java program inside the plug-in with one of the OpenGL bindings (selected by user) to ask for extensions, capabilities, maximum values and similar things.

It sounds easy: run a java program inside the plug-in. I started to investigate in the Plug-in Developer Guide in the Eclipse Help, I ended up in the Launching Program topic… My first impression wasn’t good, so I searched deeply and a good candidate was the topic Launching Java Application (actually that was exactly what I wanted) where I found what look like an article about Launching Java Applications Programmatically with examples about how doing such task.

After some hours spent trying to figure out how it works and how it should be used, finally I got some code that did what I wanted: run an small program (included in the plug-in) with custom classpath (It took a while to find how to retrieve the classpath to use the current plug-in classes) without leaving traces to the Eclipse Running history (IDebugUIConstants.ATTR_PRIVATE).

One of the problems about deciding to launch a Java Program was how to capture the OpenGL information that it’s going to retrieve in order to show it in the plug-in window. I decided that the first thing that I’m going to try is to print such information in the standard output.

So I needed to capture the output using some of the classes used in the article.

In the article is mentioned as a tip:
“You can also launch a configuration via the API ILaunchConfiguration.launch(String mode, IProgressMonitor monitor). This avoids saving editors and building the workspace, but it requires you to provide a progress monitor.”
The progress monitor is not needed (it can be null).
The launch method returns an ILaunch object which can be used to retrieve the output in some way like:

ILaunch launch = config.launch( mode, null );
IProcess processes[] = launch.getProcesses();
for( int i = 0; i < processes.length; i++ ) {
IProcess process = processes[ i ];
System.out.println("Output for process " + config.getName() + ":");
System.out.println("is Terminated: " + process.isTerminated());
System.out.println(process.getStreamsProxy()
.getOutputStreamMonitor().getContents());
System.out.println(process.getStreamsProxy()
.getErrorStreamMonitor().getContents());
}

The problem is that the above code doesn't print any output (neither standard nor error) but the output is printed in the Eclipse console where the plug-in is running. That made me suspicious that Eclipse is capturing the output to present it in the Console view before I could get it through the StreamsProxy objects.

After some more time (and investigation) I came to the conclusion that what the article describes is far too complex to just run a Java Application. And actually it is! because the article describes how to create a Launch Configuration entry (what you can see in the Run Configurations dialog from the Run menu).

I started again my search (this time using google, not eclipse help search feature) and found an entry in the The Official Eclipse FAQ titled “FAQ How do I launch a Java program?“. Eureka!! That’s it! the first approach is exactly what I’ve been looking for, simple, clean and understandable. I modified it a little bit because my run is not associated with any project. So the code with printing the output looks like:

private void launchTest(String main, String[] cp) throws CoreException{
try {
IVMInstall vm = JavaRuntime.getDefaultVMInstall();
IVMRunner vmr = vm.getVMRunner(ILaunchManager.RUN_MODE);
VMRunnerConfiguration config =
new VMRunnerConfiguration(main, cp);
ILaunch launch = new Launch(null,
ILaunchManager.RUN_MODE, null);
vmr.run(config, launch, null);
IProcess processes[] = launch.getProcesses();
for( int i = 0; i < processes.length; i++ ) {
IProcess process = processes[ i ];
System.out.println("is Terminated: " + process.isTerminated());
System.out.println(process.getStreamsProxy()
.getOutputStreamMonitor().getContents());
System.out.println(process.getStreamsProxy()
.getErrorStreamMonitor().getContents());
}
} catch( CoreException e ) {
throw e;
}
}

I hope that this is post helps somebody else who found himself/herself in the same situation.

pixelstats trackingpixel

6 Responses to “Launching a Java program inside an Eclipse plug-in (and capture its output)”

  1. bruce says:

    hi Ramon,

    i used your sample code, but i still could not get the output of the program.

    i checked “process.getStreamsProxy()
    .getOutputStreamMonitor().getContents()” eqauls “”

    • ramon says:

      Hi,
      I guess that you checked that the program finished.
      Have you checked if your output goes to the console in Eclipse?
      Is there any way that I can take a quick look at the code you’re using? Paste it here as a comment if you want.
      I used similar code to the above one in the method launchJavaApplication in eclipse-opengl project.

  2. bruce says:

    Actually, the program i want to lunch is a service “Selenium server”.

    try {
    String serverDir=”";
    URL relativeURL = Platform.getBundle(NewRadiumProjectWizard.PLUGIN_ID).getEntry(”/server”);
    URL localURL = Platform.asLocalURL(relativeURL);
    serverDir = localURL.getPath();

    String[] cp ={serverDir + File.separatorChar + “selenium-server-1.0-20081010.jar”};
    IVMInstall vm = JavaRuntime.getDefaultVMInstall();
    IVMRunner vmr = vm.getVMRunner(ILaunchManager.RUN_MODE);
    VMRunnerConfiguration config = new VMRunnerConfiguration(”org.openqa.selenium.server.SeleniumServer”, cp);
    config.setWorkingDirectory(serverDir);
    String [] args = {”-singleWindow”,”-userExtensions”,”user-extensions.js”,”-firefoxProfileTemplate”,”FirefoxProfile”};
    config.setProgramArguments(args);
    ILaunch launch = new Launch(null,
    ILaunchManager.RUN_MODE, null);
    vmr.run(config, launch, null);
    IProcess processes[] = launch.getProcesses();
    for( int i = 0; i < processes.length; i++ ) {
    IProcess process = processes[ i ];
    System.out.println(”is Terminated: ” + process.isTerminated());
    System.out.println(process.getStreamsProxy()
    .getOutputStreamMonitor().getContents());
    System.out.println(process.getStreamsProxy()
    .getErrorStreamMonitor().getContents());
    }

    } catch( Exception e ) {
    e.printStackTrace();
    }

  3. bruce says:

    actually i want to implement that start and stop the program (a service ) by the toolbar buttons, and also show the program’s output in the console.

    it’s just like the Tomcat plugin.

  4. ramon says:

    Hi Bruce,
    what I understand from your comments is that you want the Selenium server to be started/stopped by your plug-in.
    if you check the link that I talk about in my post: Launching Java Applications Programmatically, you’ll see that the example is about launching a Tomcat server.
    Anyway, I created a simple eclipse plug-in using the “Hello world” example, which launches the selenium server and prints the output in the console where the plug-in is installed: runProgramTest.tar.gz
    It doesn’t capture the output as is printed directly to the console, it doesn’t either stop the server. It can be stopped by the user by pressing the “Stop” red button in the console view. But I guess you can call the “launch.terminate()”. Check the launch method in the SampleAction class from the runProgramTest code.

  5. bruce says:

    this’s what i need, thanks much.

Leave a Reply