You are not logged in.

#1 2005-06-18 12:39:41

arooaroo
Member
From: London, UK
Registered: 2005-01-13
Posts: 1,268
Website

Displaying a shell from within a Java program

Hi,

For some long and twisted reason, I need to execute native programs from a Java program. Since this program is only every intended to be run on Linux, this doesn't bother me breaking the x-platform rules for Java! So, Runtime.exec() is the normal way to do this.

However, Runtime.exec() runs executes the command and then dishes basck the output once it's finished. The external program I wish to run takes a while and actually prints various pieces of feedback during its processing. I'd like to display this feedback to the user as it happens, rather than dumping it all at the end.

I can't think of anyway to do this. I've been looking for "Java shells" but they are reimplemented shells with only let you run classes on the classpath. Any ideas from the gurus around here?

Cheers

Offline

#2 2005-06-18 17:42:16

Dusty
Schwag Merchant
From: Medicine Hat, Alberta, Canada
Registered: 2004-01-18
Posts: 5,986
Website

Re: Displaying a shell from within a Java program

Uh... only thing I can suggest is taking a look at sources for JEdit's console plugin...

Dusty

Offline

#3 2005-06-18 18:34:18

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: Displaying a shell from within a Java program

can't you just use (sorry don't know the java terminology) a read-only textbox? just continually append info to it? set the background black and foreground white and it looks like a terminal 8)

Offline

#4 2005-06-18 18:59:58

iBertus
Member
From: Greenville, NC
Registered: 2004-11-04
Posts: 2,228

Re: Displaying a shell from within a Java program

maybe something like this?

NOTE: I did not test this code, just found it on the web. It may need updating b/c I'm not sure which JSDK version the author was using.

import    java.io.*;

class execInput {
    public static void main(String Argv[]) {
    try {
        String ls_str;

        Process ls_proc = Runtime.getRuntime().exec("/bin/ls -aFl");

        // get its output (your input) stream

        DataInputStream ls_in = new DataInputStream(
                                          ls_proc.getInputStream());

        try {
        while ((ls_str = ls_in.readLine()) != null) {
            System.out.println(ls_str);
        }
        } catch (IOException e) {
        System.exit(0);
        }
    } catch (IOException e1) {
        System.err.println(e1);
        System.exit(1);
    }

    System.exit(0);
    }
}

Offline

#5 2005-06-18 19:01:59

arooaroo
Member
From: London, UK
Registered: 2005-01-13
Posts: 1,268
Website

Re: Displaying a shell from within a Java program

Phrak,

I have no problem with the presentation part of things. As I tried to say in my original post, it's a matter of getting the text to append in the first place (in a regular fashion, that is!).

As an example, say I want to run ./configure via Java's Runtime.exec() method. As you all know, it tends to take a minute or two. But the problem here is that Runtime.exec doesn't complete until the command you executed completes. That means, you would see a blank screen for a minute, and then suddenly a full text dump. I was looking for a way to get this print-as-you-go, sort of thing.

Anyway, it looks like I'm making some progress. I have set up a couple of threads that keep probing the Process object that is returned by Runtime.exec() and that seems to be working (ish.)

Offline

#6 2005-06-18 19:04:28

iBertus
Member
From: Greenville, NC
Registered: 2004-11-04
Posts: 2,228

Re: Displaying a shell from within a Java program

Wow, you must have posted just a minute after me!

Offline

#7 2005-06-18 19:07:26

arooaroo
Member
From: London, UK
Registered: 2005-01-13
Posts: 1,268
Website

Re: Displaying a shell from within a Java program

iBertus, your suggested approach is the typical approach but suffers with the problem of only dumping everything at the end.

Offline

#8 2005-06-18 19:15:37

iBertus
Member
From: Greenville, NC
Registered: 2004-11-04
Posts: 2,228

Re: Displaying a shell from within a Java program

oops.. didn't think about that, sorry.

Offline

#9 2005-06-18 20:12:47

arooaroo
Member
From: London, UK
Registered: 2005-01-13
Posts: 1,268
Website

Re: Displaying a shell from within a Java program

np. Thanks for having a go anyway smile

Offline

#10 2005-06-18 21:55:52

cactus
Taco Eater
From: t͈̫̹ͨa͖͕͎̱͈ͨ͆ć̥̖̝o̫̫̼s͈̭̱̞͍̃!̰
Registered: 2004-05-25
Posts: 4,622
Website

Re: Displaying a shell from within a Java program

What I would do in python, is first fork, then open a two way pipe between the processes (maybe a file pipe). Have one process perform the command, and pipe its output to the other process. The other process can then read, in a non blocking fashion, from the pipe.
I dont believe simple threading would work, but you could try it.


"Be conservative in what you send; be liberal in what you accept." -- Postel's Law
"tacos" -- Cactus' Law
"t̥͍͎̪̪͗a̴̻̩͈͚ͨc̠o̩̙͈ͫͅs͙͎̙͊ ͔͇̫̜t͎̳̀a̜̞̗ͩc̗͍͚o̲̯̿s̖̣̤̙͌ ̖̜̈ț̰̫͓ạ̪͖̳c̲͎͕̰̯̃̈o͉ͅs̪ͪ ̜̻̖̜͕" -- -̖͚̫̙̓-̺̠͇ͤ̃ ̜̪̜ͯZ͔̗̭̞ͪA̝͈̙͖̩L͉̠̺͓G̙̞̦͖O̳̗͍

Offline

#11 2005-06-18 22:18:10

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: Displaying a shell from within a Java program

Ah ok, I didn't understand that it was the actual output that was the issue.... like cactus said, there's usually a way to make a programatic pipe... in c++ you're use "tie" to tie two streams together... and fill a stringstream up with the output from the program...
you would probably want to make like a "ThreadedExec" or some class... that exposes the tied stream...
otherwise you won't get the output until the call returns

Offline

#12 2005-06-18 22:19:45

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: Displaying a shell from within a Java program

another possibility is to execute it with "command &> /tmp/outbuffer" and have that file be constantly monitored for new lines (is there a FileWatcher interface in java like in .NET? exposes a FileChanged method?)

Offline

#13 2005-06-18 22:58:13

soniX
Member
From: Oslo, Norway
Registered: 2004-01-23
Posts: 161

Re: Displaying a shell from within a Java program

 import java.util.*;
 import java.io.*;
 
 class StreamGobbler extends Thread
 {
     InputStream is;
     String type;
     
     StreamGobbler(InputStream is, String type)
     {
         this.is = is;
         this.type = type;
     }
     
     public void run()
     {
         try
         {
             InputStreamReader isr = new InputStreamReader(is);
             BufferedReader br = new BufferedReader(isr);
             String line=null;
             while ( (line = br.readLine()) != null)
                 System.out.println(type + "> " + line);    
             } catch (IOException ioe)
               {
                 ioe.printStackTrace();  
               }
     }
 }
 
 public class GoodLinuxExec
 {
     public static void main(String args[])
     {
         if (args.length < 1)
         {
             System.out.println("USAGE: java GoodLinuxExec <cmd>");
             System.exit(1);
         }
         
         try
         {                         
             Runtime rt = Runtime.getRuntime();
             System.out.println("Execing " + args[0]);
             Process proc = rt.exec(args);
             // any error message?
             StreamGobbler errorGobbler = new 
                 StreamGobbler(proc.getErrorStream(), "ERROR");            
             
             // any output?
             StreamGobbler outputGobbler = new 
                 StreamGobbler(proc.getInputStream(), "OUTPUT");
                 
             // kick them off
             errorGobbler.start();
             outputGobbler.start();
                                     
             // any error???
             int exitVal = proc.waitFor();
             System.out.println("ExitValue: " + exitVal);        
         } catch (Throwable t)
           {
             t.printStackTrace();
           }
     }
 }

stolen from this article and adapted to suit an os which does not start with the letter W.

Offline

#14 2005-06-19 02:09:08

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: Displaying a shell from within a Java program

very nice!

Offline

#15 2005-06-19 08:21:24

sudman1
Member
From: Huntingdon, UK
Registered: 2005-02-18
Posts: 143

Re: Displaying a shell from within a Java program

If there's no user interaction, you can use the technique I used in my ABS GUI

I made a class called Run (you can get it from ssabsgui.jar) that sends application output as streams.  I used those streams like so:

...
    private void makepkg(String pkgWorkingDirectory) {
        Run run = new Run();
        String[] cmd = {"makepkg"};
        outputArea.append("# makepkg");
        //Scroll along with the output
        outputArea.setCaretPosition(outputArea.getText().length()-1);
        try {
            BufferedReader[] outputs = run.it(cmd , null , new File(pkgWorkingDirectory),true);
            String stdoutput = "";
            while (stdoutput != null) {
                String line = "    "+stdoutput+"n";
                outputArea.append(line);
                outputArea.setCaretPosition(outputArea.getText().length()-line.length());
                stdoutput = outputs[0].readLine();
            }
            String stderr = "";
            while (stderr != null) {
                String line = "    "+stderr+"n";
                outputArea.append(line);
                outputArea.setCaretPosition(outputArea.getText().length()-line.length());
                stderr = outputs[1].readLine();
            }
        } catch (Exception e) {
            System.err.println("Error running makepkg");
        }
    }
...

I run this method with the SwingWorker class from Sun so that the gui doesn't block.

It's not TRUE output in the sense that the error stream is printed AFTER the standard output, but most apps use the error stream for errors,so they should come last, right?


v/r
Suds

Offline

#16 2005-06-19 10:26:52

arooaroo
Member
From: London, UK
Registered: 2005-01-13
Posts: 1,268
Website

Re: Displaying a shell from within a Java program

soniX wrote:

stolen from this article and adapted to suit an os which does not start with the letter W.

Aye - that article was the inspiration for my current approach!

Offline

#17 2005-06-19 10:28:18

arooaroo
Member
From: London, UK
Registered: 2005-01-13
Posts: 1,268
Website

Re: Displaying a shell from within a Java program

sudman1 wrote:

If there's no user interaction, you can use the technique I used in my ABS GUI

I made a class called Run (you can get it from ssabsgui.jar) that sends application output as streams.

[snip code]

It's not TRUE output in the sense that the error stream is printed AFTER the standard output, but most apps use the error stream for errors,so they should come last, right?

Hmm... I like the look of this. I shall give it a whirl! Cheers

Offline

#18 2005-06-20 09:32:50

sudman1
Member
From: Huntingdon, UK
Registered: 2005-02-18
Posts: 143

Re: Displaying a shell from within a Java program

Let me know how it turns out.


v/r
Suds

Offline

#19 2005-06-24 09:45:31

arooaroo
Member
From: London, UK
Registered: 2005-01-13
Posts: 1,268
Website

Re: Displaying a shell from within a Java program

sudman1 wrote:

Let me know how it turns out.

Your Run class is being successully employed in my pacman front-end program smile

http://bbs.archlinux.org/viewtopic.php?t=13232

Cheers! smile

Offline

#20 2005-06-24 18:42:50

sudman1
Member
From: Huntingdon, UK
Registered: 2005-02-18
Posts: 143

Re: Displaying a shell from within a Java program

Glad to hear it! Cheers!


v/r
Suds

Offline

Board footer

Powered by FluxBB