I am attempting to make a Java program in which a user can select any .class
or .jar
file from their computer. My program will then pop up a JInternalFrame
with a JEditorPane
in it as the console, capturing any console output from the user's program. Note that I do not want to capture just System.err or System.out calls, but ALL PrintStream calls that go to the console.
(individual question from IDE-Style program running )
You can catch everything that is printed through System.out
using System.setOut
like this:
import java.io.*;
class SystemOutLogging {
public static void main(String[] args) throws IOException,
ClassNotFoundException {
final PrintStream original = System.out;
System.setOut(new PrintStream("programlog.txt") {
public void println(String str) {
process(str + "\n");
}
public void print(String str) {
process(str);
}
private void process(String str) {
// Fill some JEditorPane
original.println("Program printed: \"" + str + "\"");
}
});
System.out.print("Hello ");
System.out.println(" World");
}
}
Prints:
Program printed: "Hello "
Program printed: " World
"
(There is a System.setErr
and System.setIn
that works similarly.)
If you want to catch stuff that the "subprogram" prints through System.out.println
you're in trouble, because System.out
is a static so if you launch multiple "subprograms" you'll end up with a mess (since you can't hand a separate System
class to each subprogram).
In a situation like this, I honestly think it would be a better idea to launch a separate process through ProcessBuilder. The standard input / output streams of the resulting process could easily be logged.
(p.s. When I think about it, you could probably check the current thread group in the println
implementation, and from that decide which subprogram that actually invoked the println
method)
If you're starting the user's .jar file using Runtime.exec(), you'll get a Process object. That Object will allow you access to the launched processes System.out, System.in and System.err streams.
See: http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Process.html
You can take read from the err and out streams, and append to your JEditorPane using the usual setText type methods.