14

I wonder if there is any way I could change the default output (System.out) for the groovy script that I'm executing from my Java code.

Here is the Java code:

public void exec(File file, OutputStream output) throws Exception {
    GroovyShell shell = new GroovyShell();
    shell.evaluate(file);
}

And the sample groovy script:

def name='World'
println "Hello $name!"

Currently the execution of the method, evaluates scripts that writes "Hello World!" to the console (System.out). How can I redirect output to the OutputStream passed as a parameter?

5 Answers 5

18

Try this using Binding

public void exec(File file, OutputStream output) throws Exception {
    Binding binding = new Binding()
    binding.setProperty("out", output) 
    GroovyShell shell = new GroovyShell(binding);
    shell.evaluate(file);
}

After comments

public void exec(File file, OutputStream output) throws Exception {
    Binding binding = new Binding()
    binding.setProperty("out", new PrintStream(output)) 
    GroovyShell shell = new GroovyShell(binding);
    shell.evaluate(file);
}

Groovy Script

def name='World'
out << "Hello $name!"
Sign up to request clarification or add additional context in comments.

8 Comments

That would work, but I'd like to redirect any output written to the standard output. Especially by built-in functions such us println().
You were about right. The solution is to wrap the output int the java.io.PrintStream and pass as "out" property to the shell!
yay!, my first bronze badge! Happy it work it out! How did you wrap the output?
Congrats! Simply use new PrintStream(output) and pass as "out" property to binding.
Really? binding.setProperty takes an OutputStream and somehow works without calling .write??
|
3

How about using javax.script.ScriptEngine? You can specify its writer.

ScriptEngine engine = new ScriptEngineManager().getEngineByName("Groovy");
PrintWriter writer = new PrintWriter(new StringWriter());
engine.getContext().setWriter(writer);
engine.getContext().setErrorWriter(writer);
engine.eval("println 'HELLO'")

Comments

3

Use SystemOutputInterceptor class. You can start intercepting output before script evaluation and stop after.

def output = "";
def interceptor = new SystemOutputInterceptor({ output += it; false});
interceptor.start()
println("Hello")
interceptor.stop()

Comments

2

I suspect you could do this quite nicely by overwriting the println method in your GroovyShell's metaClass. The following works in Groovy Console:

StringBuilder b = new StringBuilder()

this.metaClass.println = {
    b.append(it)
    System.out.println it
}

println "Hello, world!"
System.out.println b.toString()

output:

Hello, world!
Hello, world!

Comments

0

System.setOut() is just what you need.

1 Comment

I'm afraid System.setOut is too heavyweight :) It changes the output globally for the entire JVM and this is not something that I wanted to do :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.