Can't Capture output sent to System.out

The following build file:

public class OutDelegate extends PrintStream {
    public OutDelegate(OutputStream s) { super(s) }
    @Delegate public PrintStream delegate = System.out;
                                                                                                                public PrintStream getDelegate() {
        return delegate;
      public void setDelegate(PrintStream s) {
        delegate = s;
  println System.out //1
System.out = new OutDelegate(System.out) // 2
println System.out // 3
  apply plugin: 'war'
    compileJava.doFirst {
    println System.out //4
    System.out = new OutDelegate(System.out)
    println System.out // 5
    project.ext.outTmp = System.out.getDelegate()
    println System.out.getDelegate(); // 6
                                                                                                                           System.out.setDelegate(new PrintStream(new FileOutputStream("build/dbFull.sql")));
                                                                               println System.out.getDelegate(); // 7
                                                                                                                           println "foo" //8
    System.out.println("bar") //9
    System.out.getDelegate().println("baz") //10
this writes to the file but of course that doesn't help.
// just to avoid further output.

Produces this output:

$ gradle war

Why is my replaced system.out not visible in the .doFirst Closure? Shouldn’t at least ‘bar’ wind up in the file? (which does get created, but turns up empty) This is terribly inconvenient because I am trying to capture the output from the liquibase plugin which unfortunately prints useful sql to standard out with no option to send it to a file. The idea is to substitute a groovy delegate class and swap out the delegate to a FileOutputStream based PrintStream during the liquibase taks… except I can’t seem to do that.

Highlighting the issues n the ouput…

the 4th line (after compilejava) doesn’t see the change made at configure time. the 7th line appears to confirm the presence of the Printstream in the delegate the 9th line should be sent to the file, not the output on the screen. the lack of a 10th line and the fact that // 10 shows up in the file proves that this is not a file creation or writing issue.

It seems that the groovy delegation pattern is not working perhaps? Any thoughts on how to get around this? (hopefully without writing a full on implementation overriding every method of PrintStream directly).


What are you trying to achieve here?

Sorry missed your reply. I am trying to create a tarball that contains the output from the liquibase gradle task. This task runs the liquibase classes. After some investigation and reading of the liquibase code, I found that liquibase itself was caching a copy of standard out, so I want to be able to redefine standard out with a wrapper that allows me redirect standard out to a file at configure time(before liquibase is loaded), and restore it afterwards. Sadly the liquibase tool does not have the option to ouput to a file (that I can find at least).

However, as shown above I am thwarted by some mechanism within gradle unrelated to liquibase whereby my assignment to System.out during configuration is ignored at task run time.

Sorry when I say “this task” above I am referring to the one I wish to write, not the proof of bug shown above, which does not contain anything relating to liquibase.