diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java index 48f915a75aa80d1c987ff58395aa36534cbf8a6f..2674108cd8dd0968352be48814417cbc7057bcde 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime; +import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -32,9 +33,10 @@ import java.util.zip.GZIPInputStream; import com.oracle.truffle.r.runtime.conn.GZIPConnections.GZIPRConnection; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import org.tukaani.xz.LZMA2InputStream; + /** - * Abstracts the implementation of the various forms of compression used in R. Since the C API for - * LZMA is very complex (as used by GnuR), we use an 'xz' subprocess to do the work. + * Abstracts the implementation of the various forms of compression used in R. */ public class RCompression { public enum Type { @@ -98,7 +100,7 @@ public class RCompression { case BZIP2: throw RInternalError.unimplemented("BZIP2 compression"); case LZMA: - return lzmaUncompress(udata, cdata); + return lzmaUncompressInternal(udata, cdata); default: assert false; return false; @@ -160,29 +162,18 @@ public class RCompression { } - private static boolean lzmaUncompress(byte[] udata, byte[] data) { - int rc; - ProcessBuilder pb = new ProcessBuilder("xz", "--decompress", "--format=raw", "--lzma2", "--stdout"); - pb.redirectError(Redirect.INHERIT); - try { - Process p = pb.start(); - OutputStream os = p.getOutputStream(); - InputStream is = p.getInputStream(); - ProcessOutputManager.OutputThread readThread = new ProcessOutputManager.OutputThreadFixed("xz", is, udata); - readThread.start(); - os.write(data); - os.close(); - rc = p.waitFor(); - if (rc == 0) { - readThread.join(); - if (readThread.totalRead != udata.length) { - return false; - } + private static boolean lzmaUncompressInternal(byte[] udata, byte[] data) { + int dictSize = udata.length < LZMA2InputStream.DICT_SIZE_MIN ? LZMA2InputStream.DICT_SIZE_MIN : udata.length; + try (LZMA2InputStream lzmaStream = new LZMA2InputStream(new ByteArrayInputStream(data), dictSize)) { + int totalRead = 0; + int n; + while ((n = lzmaStream.read(udata, totalRead, udata.length - totalRead)) > 0) { + totalRead += n; } - } catch (InterruptedException | IOException ex) { + return totalRead == udata.length; + } catch (IOException ex) { return false; } - return rc == 0; } /** diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index ce81b0b2cf17024c81bac57e7754702a520a4153..7d7a63cc62dd0c4019cb88f278468654749b55a8 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -73,6 +73,16 @@ suite = { "resource" : "true" }, + "APACHE_COMMONS_COMPRESS" : { + "urls" : ["http://central.maven.org/maven2/org/apache/commons/commons-compress/1.12/commons-compress-1.12.jar"], + "sha1" : "84caa68576e345eb5e7ae61a0e5a9229eb100d7b" + }, + + "TUKAANI_XZ" : { + "urls" : ["http://central.maven.org/maven2/org/tukaani/xz/1.5/xz-1.5.jar"], + "sha1" : "9c64274b7dbb65288237216e3fae7877fd3f2bee", + }, + "ANTLR-3.5" : { "path" : "libdownloads/antlr-runtime-3.5.jar", "urls" : ["http://central.maven.org/maven2/org/antlr/antlr-runtime/3.5/antlr-runtime-3.5.jar"], @@ -315,6 +325,8 @@ suite = { "dependencies" : [ "truffle:TRUFFLE_API", "truffle:TRUFFLE_DEBUG", + "APACHE_COMMONS_COMPRESS", + "TUKAANI_XZ", ], "checkstyle" : "com.oracle.truffle.r.runtime", "javaCompliance" : "1.8", @@ -427,6 +439,8 @@ suite = { "ANTLR-3.5", "GNUR", "GNU_ICONV", + "APACHE_COMMONS_COMPRESS", + "TUKAANI_XZ", ], "distDependencies" : [ "truffle:TRUFFLE_API",