package com.globant.katari.console.application;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import org.apache.commons.lang.Validate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/** This class provides the means to execute a Groovy script. It also exposes
* the application context as a script binding.
*/
public class ScriptingEngine implements ApplicationContextAware {
/** UTF-8 encoding string, default for every encoding operation. */
private static final String DEFAULT_ENCODING = "UTF-8";
/** Auto flush boolean value for stream operations. */
private static final boolean AUTO_FLUSH = true;
/** The Spring application context to be bound to the script. */
private ApplicationContext applicationContext;
/** Executes the code provided as a <code>String</code> with a Groovy shell.
* @param code The Groovy code to be executed.
* @param output The result stream produced by the script
* execution. It can be left empty if the script generates an error.
* @param error The error stream produced by the script
* execution. It will be left empty if the script doesn't generate an error.
*/
public void execute(final String code, final OutputStream output,
final OutputStream error) {
// We save the original out and error streams, as groovy will be modifying
// them.
PrintStream originalOut = System.out;
PrintStream originalErr = System.err;
PrintStream outputPrintStream = null;
PrintStream errorPrintStream = null;
try {
outputPrintStream = new PrintStream(output, AUTO_FLUSH,
DEFAULT_ENCODING);
errorPrintStream = new PrintStream(error, AUTO_FLUSH,
DEFAULT_ENCODING);
} catch (UnsupportedEncodingException cause) {
throw new RuntimeException("Couldn't create the output print streams"
+ " due to the " + DEFAULT_ENCODING + " encoding not being"
+ " supported.", cause);
}
System.setOut(outputPrintStream);
System.setErr(errorPrintStream);
Binding binding = new Binding();
binding.setProperty("applicationContext", applicationContext);
binding.setProperty("out", outputPrintStream);
binding.setProperty("err", errorPrintStream);
GroovyShell groovyShell = new GroovyShell(getClass().getClassLoader(),
binding);
Object result = null;
try {
result = groovyShell.evaluate(code);
} catch (Exception cause) {
errorPrintStream.println(cause.getMessage());
} finally {
System.setOut(originalOut);
System.setErr(originalErr);
}
if (null != result) {
outputPrintStream.println(result);
}
}
/**
* Sets the applicationContext.
* @param theApplicationContext The application context to be bound to the
* scripting shell. It can't be null.
*/
public void setApplicationContext(
final ApplicationContext theApplicationContext) {
Validate.notNull(theApplicationContext, "The application context can't be"
+ " null");
applicationContext = theApplicationContext;
}
}