extensions/net.sf.basedb.reggie/trunk/src/net/sf/basedb/reggie/script/ScriptDefinition.java

Code
Comments
Other
Rev Date Author Line
6036 02 Nov 20 nicklas 1 package net.sf.basedb.reggie.script;
6036 02 Nov 20 nicklas 2
6036 02 Nov 20 nicklas 3 import java.io.ByteArrayOutputStream;
6036 02 Nov 20 nicklas 4 import java.io.File;
6036 02 Nov 20 nicklas 5 import java.util.Arrays;
6036 02 Nov 20 nicklas 6 import java.util.Date;
6036 02 Nov 20 nicklas 7
6036 02 Nov 20 nicklas 8 import org.slf4j.LoggerFactory;
6036 02 Nov 20 nicklas 9
6036 02 Nov 20 nicklas 10 import net.sf.basedb.core.InvalidDataException;
6036 02 Nov 20 nicklas 11 import net.sf.basedb.core.signal.SignalException;
6036 02 Nov 20 nicklas 12 import net.sf.basedb.reggie.Reggie;
6036 02 Nov 20 nicklas 13 import net.sf.basedb.util.FileCopyRunnable;
6036 02 Nov 20 nicklas 14 import net.sf.basedb.util.FileUtil;
7080 27 Mar 23 nicklas 15 import net.sf.basedb.util.extensions.logging.ExtensionsLog;
7080 27 Mar 23 nicklas 16 import net.sf.basedb.util.extensions.logging.ExtensionsLogger;
6036 02 Nov 20 nicklas 17
6036 02 Nov 20 nicklas 18 public abstract class ScriptDefinition 
6036 02 Nov 20 nicklas 19 {
6036 02 Nov 20 nicklas 20
7080 27 Mar 23 nicklas 21   private static final ExtensionsLogger logger = 
7080 27 Mar 23 nicklas 22     ExtensionsLog.getLogger("net.sf.basedb.reggie", true).wrap(LoggerFactory.getLogger(ScriptDefinition.class));
6036 02 Nov 20 nicklas 23   
6036 02 Nov 20 nicklas 24   /**
6036 02 Nov 20 nicklas 25     Check user-input with this method before adding it to R script as a parameter
6036 02 Nov 20 nicklas 26     to make sure it doesn't contain any rough characters. Currently we play it safe
6036 02 Nov 20 nicklas 27     and only allow letter, digits, dot, underscore, space and hyphen.
6036 02 Nov 20 nicklas 28   */
6036 02 Nov 20 nicklas 29   public static String checkValidScriptParameter(String param)
6036 02 Nov 20 nicklas 30   {
6036 02 Nov 20 nicklas 31     if (param != null && !param.matches("[a-zA-Z0-9._\\- ]+"))
6036 02 Nov 20 nicklas 32     {
6036 02 Nov 20 nicklas 33       throw new InvalidDataException("Parameter may only contain [a-zA-Z0-9._- ]: " + param);
6036 02 Nov 20 nicklas 34     }
6036 02 Nov 20 nicklas 35     return param;
6036 02 Nov 20 nicklas 36   }
6036 02 Nov 20 nicklas 37
6036 02 Nov 20 nicklas 38   private String workDir;
6036 02 Nov 20 nicklas 39
6036 02 Nov 20 nicklas 40   
6036 02 Nov 20 nicklas 41   protected ScriptDefinition()
6036 02 Nov 20 nicklas 42   {}
6036 02 Nov 20 nicklas 43   
6036 02 Nov 20 nicklas 44   
6036 02 Nov 20 nicklas 45   /**
6036 02 Nov 20 nicklas 46     Path to the working directory. If not set before
6036 02 Nov 20 nicklas 47     running the R script, a random temporary directory
6036 02 Nov 20 nicklas 48     will be created.
6036 02 Nov 20 nicklas 49   */
6036 02 Nov 20 nicklas 50   public void setWorkDir(String workDir)
6036 02 Nov 20 nicklas 51   {
6036 02 Nov 20 nicklas 52     this.workDir = workDir;
6036 02 Nov 20 nicklas 53   }
6036 02 Nov 20 nicklas 54   
6036 02 Nov 20 nicklas 55   /**
6036 02 Nov 20 nicklas 56     Get the path to the working directory.
6036 02 Nov 20 nicklas 57     @since 4.20
6036 02 Nov 20 nicklas 58   */
6036 02 Nov 20 nicklas 59   public String getWorkDir()
6036 02 Nov 20 nicklas 60   {
6036 02 Nov 20 nicklas 61     return workDir;
6036 02 Nov 20 nicklas 62   }
6036 02 Nov 20 nicklas 63   
6036 02 Nov 20 nicklas 64   /**
6036 02 Nov 20 nicklas 65     Remove all files in the working directory.
6036 02 Nov 20 nicklas 66   */
6036 02 Nov 20 nicklas 67   public void removeWorkDir()
6036 02 Nov 20 nicklas 68   {
6036 02 Nov 20 nicklas 69     if (workDir != null)
6036 02 Nov 20 nicklas 70     {
6036 02 Nov 20 nicklas 71       FileUtil.deleteTempDirectory(new File(workDir));
6036 02 Nov 20 nicklas 72       workDir = null;
6036 02 Nov 20 nicklas 73     }
6036 02 Nov 20 nicklas 74   }
6036 02 Nov 20 nicklas 75   
6036 02 Nov 20 nicklas 76   
6036 02 Nov 20 nicklas 77   protected <R extends ScriptResult> R run(R result, String... cmd)
6036 02 Nov 20 nicklas 78   {
6036 02 Nov 20 nicklas 79     try
6036 02 Nov 20 nicklas 80     {
6036 02 Nov 20 nicklas 81       File dir = null;
6036 02 Nov 20 nicklas 82       if (workDir != null)
6036 02 Nov 20 nicklas 83       {
6036 02 Nov 20 nicklas 84         dir = new File(workDir);
6036 02 Nov 20 nicklas 85         if (!dir.isDirectory()) dir = null;
6036 02 Nov 20 nicklas 86       }
6036 02 Nov 20 nicklas 87       
6036 02 Nov 20 nicklas 88       if (dir == null)
6036 02 Nov 20 nicklas 89       {
6056 13 Nov 20 nicklas 90         TemporaryWorkDir tmp = TemporaryWorkDir.create(getClass().getSimpleName()+"-"+Reggie.CONVERTER_DATE_TO_STRING.convert(new Date())+"-", ".tmp", result);
6036 02 Nov 20 nicklas 91         result.setTmpWorkDir(tmp);
6036 02 Nov 20 nicklas 92         dir = tmp.getWorkDir();
6036 02 Nov 20 nicklas 93       }
6036 02 Nov 20 nicklas 94       else
6036 02 Nov 20 nicklas 95       {
6036 02 Nov 20 nicklas 96         result.setWorkDir(dir);
6036 02 Nov 20 nicklas 97       }
6036 02 Nov 20 nicklas 98       
6036 02 Nov 20 nicklas 99       if (logger.isDebugEnabled())
6036 02 Nov 20 nicklas 100       {
6036 02 Nov 20 nicklas 101         logger.debug("Running script: " + Arrays.asList(cmd));
6036 02 Nov 20 nicklas 102         logger.debug("Working directory: " + dir);
6036 02 Nov 20 nicklas 103       }
6036 02 Nov 20 nicklas 104       
6036 02 Nov 20 nicklas 105       ProcessBuilder builder = new ProcessBuilder(cmd);
6036 02 Nov 20 nicklas 106       builder.directory(dir);
6036 02 Nov 20 nicklas 107       result.loadFilesToWorkDir();
6036 02 Nov 20 nicklas 108       
6036 02 Nov 20 nicklas 109       Process proc = builder.start();
6036 02 Nov 20 nicklas 110       
6036 02 Nov 20 nicklas 111       // Collect stdout and stderr output
6036 02 Nov 20 nicklas 112       ByteArrayOutputStream stdout = new ByteArrayOutputStream();
6036 02 Nov 20 nicklas 113       ByteArrayOutputStream stderr = new ByteArrayOutputStream();
6036 02 Nov 20 nicklas 114       
6036 02 Nov 20 nicklas 115       new Thread(new FileCopyRunnable(proc.getInputStream(), stdout)).start();
6036 02 Nov 20 nicklas 116       new Thread(new FileCopyRunnable(proc.getErrorStream(), stderr)).start();
6036 02 Nov 20 nicklas 117     
6036 02 Nov 20 nicklas 118       int exitValue = proc.waitFor();
6036 02 Nov 20 nicklas 119       
6036 02 Nov 20 nicklas 120       result.setStdout(stdout.toString("UTF-8"));
6036 02 Nov 20 nicklas 121       result.setStderr(stderr.toString("UTF-8"));
6036 02 Nov 20 nicklas 122       result.setExitStatus(exitValue);
6036 02 Nov 20 nicklas 123       result.cleanupWorkDir();
6036 02 Nov 20 nicklas 124       if (logger.isDebugEnabled())
6036 02 Nov 20 nicklas 125       {
6036 02 Nov 20 nicklas 126         logger.debug(result.toString());
6036 02 Nov 20 nicklas 127       }
6036 02 Nov 20 nicklas 128       
6036 02 Nov 20 nicklas 129     }
6036 02 Nov 20 nicklas 130     catch (InterruptedException ex)
6036 02 Nov 20 nicklas 131     {
6036 02 Nov 20 nicklas 132       throw new SignalException("Aborted by user");
6036 02 Nov 20 nicklas 133     }
6036 02 Nov 20 nicklas 134     catch (Exception ex)
6036 02 Nov 20 nicklas 135     {
6036 02 Nov 20 nicklas 136       result.setExitStatus(1);
6036 02 Nov 20 nicklas 137       result.setException(ex);
6036 02 Nov 20 nicklas 138       logger.error(result.toString(), ex);
6036 02 Nov 20 nicklas 139     }
6036 02 Nov 20 nicklas 140     
6036 02 Nov 20 nicklas 141     return result;
6036 02 Nov 20 nicklas 142   }
6036 02 Nov 20 nicklas 143   
6036 02 Nov 20 nicklas 144
6036 02 Nov 20 nicklas 145 }