If the program uses System.out or System.err (as most simple ones do) it's a bit of a pain, because output from the entire web server goes there.
You can override System.out by creating a new
PrintStream object and passing it to System.setOut() but that's going to affect everything that happens to be written for the entire webserver.
What I'd do is to create a special
OutputStream object which steared "write" attempts to some suitable cache. But it's behaviour has to depend if it's running on the thread that's executing your user program (or another thread created by the user program). (Overriding the
OutputStream is simpler than writing a complete
PrintStream.)
Then I'd permanently, one time, insert those new writers into System.
Because of multi-threading it's not enough to set the output back again after the program has run.
There's a class called
InheritableThreadLocal, which allows an object to have a different value for each thread it runs on. You can stear the write requests using that.
Before running the client program create an appropriate
OutputStream (a temporary file or memory buffer) and insert set the
InheritableThreadLocal to point to it. After the client had run (or crashed, use finally) close the stream and set the
ThreadLocal to null.
The write methods of the Streams you direct out and err to check the
ThreadLocal, and if it's not null send the data there, if it is null they send it to the default writers.