diff --git a/RCaller/src/main/java/com/github/rcaller/TempFileService.java b/RCaller/src/main/java/com/github/rcaller/TempFileService.java index 41e7293..eace76f 100644 --- a/RCaller/src/main/java/com/github/rcaller/TempFileService.java +++ b/RCaller/src/main/java/com/github/rcaller/TempFileService.java @@ -7,24 +7,30 @@ import java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; +import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; - public class TempFileService { private static final Logger logger = Logger.getLogger(TempFileService.class.getName()); - private final ArrayList> tempFiles; - - public TempFileService(){ - tempFiles = new ArrayList<>(); + private final ArrayList> tempFiles = new ArrayList<>(); + private final Path tempDir; + + public TempFileService() { + this.tempDir = null; + } + + public TempFileService(final Path tempDir) { + this.tempDir = tempDir; } - - public File createTempFile(String prefix, String suffix) throws IOException { - File f = File.createTempFile(prefix, suffix); + + public File createTempFile(final String prefix, + final String suffix) throws IOException { + File f = File.createTempFile(prefix, suffix, toFileOrNull(tempDir)); FileChannel fileChannel = FileChannel.open( f.toPath(), StandardOpenOption.READ, @@ -32,10 +38,10 @@ public File createTempFile(String prefix, String suffix) throws IOException { StandardOpenOption.CREATE ); tempFiles.add(new ImmutablePair<>(f, fileChannel)); - return(f); + return f; } - - public void deleteRCallerTempFiles(){ + + public void deleteRCallerTempFiles() { for (Pair tempFileAndChannel : tempFiles) { var fileChannel = tempFileAndChannel.getRight(); var tempFile = tempFileAndChannel.getLeft(); @@ -66,4 +72,8 @@ public File createControlFile() { throw new ExecutionException("Can not create a temporary file for storing the R results: " + e.getMessage()); } } -} + + private File toFileOrNull(final Path tempDir) { + return tempDir == null ? null : tempDir.toFile(); + } +} \ No newline at end of file diff --git a/RCaller/src/main/java/com/github/rcaller/rstuff/RCaller.java b/RCaller/src/main/java/com/github/rcaller/rstuff/RCaller.java index 9f40850..e8f0b7f 100644 --- a/RCaller/src/main/java/com/github/rcaller/rstuff/RCaller.java +++ b/RCaller/src/main/java/com/github/rcaller/rstuff/RCaller.java @@ -18,7 +18,6 @@ import static java.lang.String.join; import static java.lang.System.currentTimeMillis; - public class RCaller { private static final Logger logger = Logger.getLogger(RCaller.class.getName()); @@ -40,14 +39,13 @@ protected RCaller(RCode rCode, RStreamHandler rOutput, RStreamHandler rError, MessageSaver messageSaver, - TempFileService tempFileService, RCallerOptions rCallerOptions) { this.rCode = rCode; this.parser = parser; this.rOutput = rOutput; this.rError = rError; this.errorMessageSaver = messageSaver; - this.tempFileService = tempFileService; + this.tempFileService = rCode.getTempFileService(); this.rCallerOptions = rCallerOptions; this.rError.addEventHandler(errorMessageSaver); @@ -60,7 +58,12 @@ protected RCaller(RCode rCode, */ public static RCaller create() { RCallerOptions rCallerOptions = RCallerOptions.create(); - return new RCaller(RCode.create(), ROutputParser.create(rCallerOptions), new RStreamHandler(null, "Output"), new RStreamHandler(null, "Error"), new MessageSaver(), new TempFileService(), rCallerOptions); + return new RCaller(RCode.create(), + ROutputParser.create(rCallerOptions), + new RStreamHandler(null, "Output"), + new RStreamHandler(null, "Error"), + new MessageSaver(), + rCallerOptions); } /*** @@ -69,8 +72,13 @@ public static RCaller create() { * @param rCallerOptions given startup options * @return RCaller object */ - public static RCaller create(RCallerOptions rCallerOptions) { - return new RCaller(RCode.create(rCallerOptions), ROutputParser.create(rCallerOptions), new RStreamHandler(null, "Output"), new RStreamHandler(null, "Error"), new MessageSaver(), new TempFileService(), rCallerOptions); + public static RCaller create(final RCallerOptions rCallerOptions) { + return new RCaller(RCode.create(rCallerOptions), + ROutputParser.create(rCallerOptions), + new RStreamHandler(null, "Output"), + new RStreamHandler(null, "Error"), + new MessageSaver(), + rCallerOptions); } /** @@ -80,11 +88,16 @@ public static RCaller create(RCallerOptions rCallerOptions) { * @param rCallerOptions given startup object * @return RCaller object */ - public static RCaller create(RCode rcode, RCallerOptions rCallerOptions) { - return new RCaller(rcode, ROutputParser.create(rCallerOptions), new RStreamHandler(null, "Output"), new RStreamHandler(null, "Error"), new MessageSaver(), new TempFileService(), rCallerOptions); + public static RCaller create(final RCode rcode, + final RCallerOptions rCallerOptions) { + return new RCaller(rcode, + ROutputParser.create(rCallerOptions), + new RStreamHandler(null, "Output"), + new RStreamHandler(null, "Error"), + new MessageSaver(), + rCallerOptions); } - /** * Stops the threads that are emptying the output and error streams of the * live but idle R process. If R is still working, this may cause it to diff --git a/RCaller/src/main/java/com/github/rcaller/rstuff/RCode.java b/RCaller/src/main/java/com/github/rcaller/rstuff/RCode.java index 4c027cb..4a3532e 100644 --- a/RCaller/src/main/java/com/github/rcaller/rstuff/RCode.java +++ b/RCaller/src/main/java/com/github/rcaller/rstuff/RCode.java @@ -10,48 +10,140 @@ import javax.swing.*; import java.io.*; +import java.nio.file.Path; public class RCode { - private StringBuilder code; - private TempFileService tempFileService = null; + private StringBuilder code = new StringBuilder(); + private final TempFileService tempFileService; private final RCallerOptions rCallerOptions; - private RCode() { - this.code = new StringBuilder(); - rCallerOptions = RCallerOptions.create(); + this.rCallerOptions = RCallerOptions.create(); + this.tempFileService = new TempFileService(); + } + + private RCode(Path tempDir) { + this.rCallerOptions = RCallerOptions.create(); + this.tempFileService = new TempFileService(tempDir); } private RCode(RCallerOptions rCallerOptions) { - this.code = new StringBuilder(); this.rCallerOptions = rCallerOptions; + this.tempFileService = new TempFileService(); } + private RCode(Path tempDir, + RCallerOptions rCallerOptions) { + this.rCallerOptions = rCallerOptions; + this.tempFileService = new TempFileService(tempDir); + } + + /** + * Static factory creator for the default object + * + * @return default RCode object + */ public static RCode create() { RCode rCode = new RCode(); rCode.clear(); return rCode; } + /** + * Static factory creator with given temporary file directory + * + * @param tempDir the directory to use to store temporary files + * @return RCode object + */ + public static RCode create(Path tempDir) { + RCode rCode = new RCode(tempDir); + rCode.clear(); + return rCode; + } + + /** + * Static factory creator with given string buffer + * + * @param stringBuffer the string buffer used for holding R code + * @return RCode object + */ public static RCode create(StringBuffer stringBuffer) { RCode rCode = RCode.create(); rCode.getCode().append(stringBuffer.toString()); return rCode; } + /** + * Static factory creator with given temporary file directory and string buffer + * + * @param tempDir the directory to use to store temporary files + * @param stringBuffer the string buffer used for holding R code + * @return RCode object + */ + public static RCode create(Path tempDir, + StringBuffer stringBuffer) { + RCode rCode = RCode.create(tempDir); + rCode.getCode().append(stringBuffer.toString()); + return rCode; + } + + /** + * Static factory creator with given startup options + * + * @param rCallerOptions given startup object + * @return RCode object + */ public static RCode create(RCallerOptions rCallerOptions) { RCode rCode = new RCode(rCallerOptions); rCode.clear(); return rCode; } - public static RCode create(StringBuffer stringBuffer, RCallerOptions rCallerOptions) { + /** + * Static factory creator with given temporary file directory and startup options + * + * @param tempDir the directory to use to store temporary files + * @param rCallerOptions given startup object + * @return RCode object + */ + public static RCode create(Path tempDir, + RCallerOptions rCallerOptions) { + RCode rCode = new RCode(tempDir, rCallerOptions); + rCode.clear(); + return rCode; + } + + /** + * Static factory creator with given string buffer and startup options + * + * @param stringBuffer the string buffer used for holding R code + * @param rCallerOptions given startup object + * @return RCode object + */ + public static RCode create(StringBuffer stringBuffer, + RCallerOptions rCallerOptions) { RCode rCode = RCode.create(rCallerOptions); rCode.getCode().append(stringBuffer.toString()); return rCode; } + /** + * Static factory creator with given temporary file directory and string buffer and startup options + * + * @param tempDir the directory to use to store temporary files + * @param stringBuffer the string buffer used for holding R code + * @param rCallerOptions given startup object + * @return RCode object + */ + public static RCode create(Path tempDir, + StringBuffer stringBuffer, + RCallerOptions rCallerOptions) { + RCode rCode = RCode.create(tempDir, rCallerOptions); + rCode.getCode().append(stringBuffer.toString()); + return rCode; + } + public void setCode(StringBuffer sb) { this.code = new StringBuilder(); clear(); @@ -68,6 +160,10 @@ public StringBuilder getCode() { return (this.code); } + public TempFileService getTempFileService() { + return tempFileService; + } + public final void clear() { this.code.setLength(0); addRCode(RCodeIO.getInterprocessDependencies(rCallerOptions)); @@ -171,7 +267,7 @@ public void addString(String name, String value){ } public void addDataFrame(String name, DataFrame dataFrame) { - RCodeUtils.addDataFrame(code, name, dataFrame); + RCodeUtils.addDataFrame(code, name, dataFrame, tempFileService); } public File startPlot() throws IOException { @@ -179,9 +275,6 @@ public File startPlot() throws IOException { } public File startPlot(GraphicsType type) throws IOException { - if(tempFileService == null){ - tempFileService = new TempFileService(); - } //File f = File.createTempFile("RPlot", "." + type.name()); File f = tempFileService.createTempFile("RPlot", "." + type.name()); switch (type) { @@ -227,9 +320,7 @@ public void R_source(String sourceFile) { } public void deleteTempFiles(){ - if (tempFileService != null){ - tempFileService.deleteRCallerTempFiles(); - } + tempFileService.deleteRCallerTempFiles(); } @Override diff --git a/RCaller/src/main/java/com/github/rcaller/util/RCodeUtils.java b/RCaller/src/main/java/com/github/rcaller/util/RCodeUtils.java index 52707e5..361b2d8 100644 --- a/RCaller/src/main/java/com/github/rcaller/util/RCodeUtils.java +++ b/RCaller/src/main/java/com/github/rcaller/util/RCodeUtils.java @@ -1,6 +1,7 @@ package com.github.rcaller.util; import com.github.rcaller.JavaObject; +import com.github.rcaller.TempFileService; import com.github.rcaller.datatypes.DataFrame; import com.github.rcaller.exception.ExecutionException; import com.github.rcaller.io.CSVFileWriter; @@ -201,21 +202,25 @@ public static void addRespectToType(StringBuilder rCode, String name, Object o, throw new ExecutionException("Cannot convert Java object " + o.toString() + " in type of " + o.getClass().getCanonicalName() + " to R code due to " + iae.toString()); } } - } public static void addDataFrame(StringBuilder rCode, String name, DataFrame dataFrame) { + addDataFrame(rCode, name, dataFrame, null); + } + + public static void addDataFrame(StringBuilder rCode, String name, DataFrame dataFrame, TempFileService tempFileService) { + if (tempFileService == null) { + tempFileService = new TempFileService(); + } try { - File file = File.createTempFile("dataFrame", ".csv"); + File file = tempFileService.createTempFile("dataFrame", ".csv"); try (CSVFileWriter csvFileWriter = CSVFileWriter.create(file)) { csvFileWriter.writeDataFrameToFile(dataFrame); } rCode.append(name).append(" <- read.csv(\"").append(Globals.getSystemSpecificRPathParameter(file)).append("\")\n"); - } catch (IOException e) { Logger.getLogger(RCodeUtils.class.getName()).log(Level.WARNING, "Couldn't export data frame to csv-file!", e.getStackTrace()); } - } public static void addResourceScript(StringBuilder rCode, String name) {