Search in sources :

Example 1 with CharSequenceInputStream

use of org.apache.commons.io.input.CharSequenceInputStream in project opennms by OpenNMS.

the class RScriptExecutor method exec.

/**
     * Executes by given script by:
     *   - Searching both the classpath and the filesystem for the path
     *   - Copying the script at the given path to a temporary file and
     *     performing variable substitution with the arguments using Freemarker.
     *   - Invoking the script with commons-exec
     *   - Converting the input table to CSV and passing this to the process via stdin
     *   - Parsing stdout, expecting CSV output, and converting this to an immutable table
     */
public RScriptOutput exec(String script, RScriptInput input) throws RScriptException {
    Preconditions.checkNotNull(script, "script argument");
    Preconditions.checkNotNull(input, "input argument");
    // Grab the script/template
    Template template;
    try {
        template = m_freemarkerConfiguration.getTemplate(script);
    } catch (IOException e) {
        throw new RScriptException("Failed to read the script.", e);
    }
    // Create a temporary file
    File scriptOnDisk;
    try {
        scriptOnDisk = File.createTempFile("Rcsript", "R");
        scriptOnDisk.deleteOnExit();
    } catch (IOException e) {
        throw new RScriptException("Failed to create a temporary file.", e);
    }
    // Perform variable substitution and write the results to the temporary file
    try (FileOutputStream fos = new FileOutputStream(scriptOnDisk);
        Writer out = new OutputStreamWriter(fos)) {
        template.process(input.getArguments(), out);
    } catch (IOException | TemplateException e) {
        scriptOnDisk.delete();
        throw new RScriptException("Failed to process the template.", e);
    }
    // Convert the input matrix to a CSV string which will be passed to the script via stdin.
    // The table may be large, so we try and avoid writing it to disk
    StringBuilder inputTableAsCsv;
    try {
        inputTableAsCsv = toCsv(input.getTable());
    } catch (IOException e) {
        scriptOnDisk.delete();
        throw new RScriptException("Failed to convert the input table to CSV.", e);
    }
    // Invoke Rscript against the script (located in a temporary file)
    CommandLine cmdLine = new CommandLine(RSCRIPT_BINARY);
    cmdLine.addArgument(scriptOnDisk.getAbsolutePath());
    // Use commons-exec to execute the process
    DefaultExecutor executor = new DefaultExecutor();
    // Use the CharSequenceInputStream in order to avoid explicitly converting
    // the StringBuilder a string and then an array of bytes.
    InputStream stdin = new CharSequenceInputStream(inputTableAsCsv, StandardCharsets.UTF_8);
    ByteArrayOutputStream stderr = new ByteArrayOutputStream();
    ByteArrayOutputStream stdout = new ByteArrayOutputStream();
    executor.setStreamHandler(new PumpStreamHandler(stdout, stderr, stdin));
    // Fail if we get a non-zero exit code
    executor.setExitValue(0);
    // Fail if the process takes too long
    ExecuteWatchdog watchdog = new ExecuteWatchdog(SCRIPT_TIMEOUT_MS);
    executor.setWatchdog(watchdog);
    // Execute
    try {
        executor.execute(cmdLine);
    } catch (IOException e) {
        scriptOnDisk.delete();
        throw new RScriptException("An error occured while executing Rscript, or the requested script.", inputTableAsCsv.toString(), stderr.toString(), stdout.toString(), e);
    }
    // Parse and return the results
    try {
        ImmutableTable<Long, String, Double> table = fromCsv(stdout.toString());
        return new RScriptOutput(table);
    } catch (Throwable t) {
        throw new RScriptException("Failed to parse the script's output.", inputTableAsCsv.toString(), stderr.toString(), stdout.toString(), t);
    } finally {
        scriptOnDisk.delete();
    }
}
Also used : CharSequenceInputStream(org.apache.commons.io.input.CharSequenceInputStream) TemplateException(freemarker.template.TemplateException) DefaultExecutor(org.apache.commons.exec.DefaultExecutor) CharSequenceInputStream(org.apache.commons.io.input.CharSequenceInputStream) InputStream(java.io.InputStream) ExecuteWatchdog(org.apache.commons.exec.ExecuteWatchdog) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) Template(freemarker.template.Template) CommandLine(org.apache.commons.exec.CommandLine) PumpStreamHandler(org.apache.commons.exec.PumpStreamHandler) FileOutputStream(java.io.FileOutputStream) OutputStreamWriter(java.io.OutputStreamWriter) File(java.io.File) OutputStreamWriter(java.io.OutputStreamWriter) Writer(java.io.Writer)

Aggregations

Template (freemarker.template.Template)1 TemplateException (freemarker.template.TemplateException)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 File (java.io.File)1 FileOutputStream (java.io.FileOutputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 OutputStreamWriter (java.io.OutputStreamWriter)1 Writer (java.io.Writer)1 CommandLine (org.apache.commons.exec.CommandLine)1 DefaultExecutor (org.apache.commons.exec.DefaultExecutor)1 ExecuteWatchdog (org.apache.commons.exec.ExecuteWatchdog)1 PumpStreamHandler (org.apache.commons.exec.PumpStreamHandler)1 CharSequenceInputStream (org.apache.commons.io.input.CharSequenceInputStream)1