External Execution Support 2/2

In my last post on External Execution Support I described the basic low level API for processing streams and lines. In this post I would like to present much cooler feature for running external programs (processes) in NetBeans. The whole External Execution Support is brand new and is available in trunk and (once released) in NetBeans 7.0.

So how can this API help you with that? Let's start with simple example running the ls command.

import java.util.concurrent.Callable;
import org.netbeans.api.extexecution.ExecutionDescriptor;
import org.netbeans.api.extexecution.ExecutionService;

public class CommandExample1 {

    public Integer execute() {
        Callable<Process> processCallable = new Callable<Process>() {
            public Process call() throws IOException {
                return new ProcessBuilder("/bin/ls").start();
            }
        };

        ExecutionDescriptor descriptor = new ExecutionDescriptor()
                .frontWindow(true).controllable(true);

        ExecutionService service = ExecutionService.newService(processCallable,
                descriptor, "ls command");

        Future<Integer> task = service.run();        
        return task.get();
    }
}

What actually happens when this code is executed? First of all the Callable returning the actual Process is created. The second structure is descriptor for UI representation of the process. The last thing you have to do is to create ExecutionService and run it. The returned Future represents the process and its return code. It might look complicated but it is highly customizable. The following picture shows the UI part provided by the API at runtime.

As you can see user will get the output of the process and can stop it while running or run it again. This is all provided by the ExecutionService. For example you don't have to create threads reading the streams. You don't have to care about synchronization of multiple threads and how to stop them when the process is finished.

Many UI configurations can be made via the ExecutionDescriptor. You can disable control buttons, define pre and post execution hooks or you can even use your custom InputOutput without UI representation to run the process on background and much more!

In ExecutionDescriptor you can also specify factory for InputProcessor and LineProcessor. This way you can easily process the output of the running process with all the features introduced in previous post. In the next sample we are running the ls command and printing the line number for each line. For process creation we use simple support provided by the External Execution Support.

import java.util.Collections;
import org.netbeans.api.extexecution.ExecutionDescriptor;
import org.netbeans.api.extexecution.ExecutionDescriptor.LineCovertorFactory;
import org.netbeans.api.extexecution.ExecutionService;
import org.netbeans.api.extexecution.ExternalProcessBuilder;
import org.netbeans.api.extexecution.print.LineConvertor;
import org.netbeans.api.extexecution.print.ConvertedLine;

public class CommandExample2 {

    public Integer execute() {
        ExternalProcessBuilder processBuilder = new ExternalProcessBuilder("/bin/ls");

        ExecutionDescriptor descriptor = new ExecutionDescriptor()
                .frontWindow(true).controllable(true);

        descriptor = descriptor.outConvertorFactory(new LineConvertorFactory() {
            public LineConvertor newLineConvertor() {
                return new Numbered();
            }
        });

        ExecutionService service = ExecutionService.newService(processBuilder,
                descriptor, "ls command");

        Future<Integer> task = service.run();        
        return task.get();
    }
    
    private static class Numbered implements LineConvertor {
        private int number;

        List<ConvertedLine> convert(String line) {
            List<ConvertedLine> result = Collections.singletonList(
                    ConvertedLine.forText(number + ": " + line, null));
            number++;
            return result;
        }
    }
}

Related output visible to a user is on the following picture.

With proper LineConvertor you can adapt the output as you need. With custom InputProcessor or LineProcessor you can process chars or lines without affecting them in any way. This is just simple usage - look at the API Javadoc to see what else you can do with the API. One thing you should note is that Process is fully abstract class so you can use the API for any process you are able to create not just OS related ones.

Let me know if you like it or when you have additional questions.


Comments:

Cool. Saved for future reference.
BTW, link to your last post is off. It should be
http://blogs.sun.com/phejl/entry/external_execution_support_1_2

Posted by Katsumi INOUE on February 10, 2009 at 12:58 AM CET #

Thanks! Link fixed.

Posted by Petr Hejl on February 10, 2009 at 02:55 AM CET #

Is there a way to design my own TopComponent for the display of the output?

Posted by Geertjan on February 16, 2009 at 12:55 PM CET #

I think there is a way although it is not optimized for this usecase. You have to implement your own InputOutput and use ExecutionDescriptor returned by call to ExeutionDescriptor.inputOutput(). I think scala.console implements such TopComponent.

Posted by Petr Hejl on February 16, 2009 at 03:02 PM CET #

How would it be possible to pipe output into a file? I want to run an external program and pipe the output into a temporary file, which i then want to read from inside netbeans. Using the ">" field as "addArgument" does not work though.

Posted by beberlei on July 30, 2009 at 04:31 PM CEST #

The examples don't create a I/O window as per your screens. I can see the output in this format in the IDE:
[dir command] <message>

I translated the example to use Windows dir command. This is on Netbeans 7.0 RC1

Any idea?

Posted by Javier Ortiz on March 10, 2011 at 03:02 PM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Petr is a NetBeans software engineer responsible for the Groovy & Grails support.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today