From f82a8ce0585353e94fe8317272714f9892440f04 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 31 Dec 2010 00:08:55 +0000 Subject: Poking around at and hardening anything which m... Poking around at and hardening anything which may conceivably interact with ZipFile.getNextEntry. No review. --- src/compiler/scala/tools/nsc/io/File.scala | 24 ++++++++++++++++-------- src/compiler/scala/tools/nsc/io/Streamable.scala | 7 ++++++- 2 files changed, 22 insertions(+), 9 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/io/File.scala b/src/compiler/scala/tools/nsc/io/File.scala index e9741ed5cb..7bf04cbe5c 100644 --- a/src/compiler/scala/tools/nsc/io/File.scala +++ b/src/compiler/scala/tools/nsc/io/File.scala @@ -12,7 +12,7 @@ package io import java.io.{ FileInputStream, FileOutputStream, BufferedReader, BufferedWriter, InputStreamReader, OutputStreamWriter, - BufferedInputStream, BufferedOutputStream, IOException, PrintStream, File => JFile } + BufferedInputStream, BufferedOutputStream, IOException, PrintStream, File => JFile, Closeable => JCloseable } import java.nio.channels.{ Channel, FileChannel } import scala.io.Codec @@ -26,8 +26,12 @@ object File { def makeTemp(prefix: String = Path.randomPrefix, suffix: String = null, dir: JFile = null) = apply(JFile.createTempFile(prefix, suffix, dir)) - type Closeable = { def close(): Unit } - def closeQuietly(target: Closeable) { + type HasClose = { def close(): Unit } + + def closeQuietly(target: HasClose) { + try target.close() catch { case e: IOException => } + } + def closeQuietly(target: JCloseable) { try target.close() catch { case e: IOException => } } @@ -37,11 +41,15 @@ object File { // the exceptions so as not to cause spurious failures when no write access is available, // e.g. google app engine. try { + import Streamable.closing val tmp = JFile.createTempFile("bug6503430", null, null) - val in = new FileInputStream(tmp).getChannel() - val out = new FileOutputStream(tmp, true).getChannel() - out.transferFrom(in, 0, 0) - tmp.delete() + try closing(new FileInputStream(tmp)) { in => + val inc = in.getChannel() + closing(new FileOutputStream(tmp, true)) { out => + out.getChannel().transferFrom(inc, 0, 0) + } + } + finally tmp.delete() } catch { case _: IllegalArgumentException | _: IllegalStateException | _: IOException | _: SecurityException => () @@ -132,7 +140,7 @@ class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) w pos += out.transferFrom(in, pos, count) } } - finally List[Closeable](out, out_s, in, in_s) foreach closeQuietly + finally List[HasClose](out, out_s, in, in_s) foreach closeQuietly if (this.length != dest.length) fail("Failed to completely copy %s to %s".format(name, dest.name)) diff --git a/src/compiler/scala/tools/nsc/io/Streamable.scala b/src/compiler/scala/tools/nsc/io/Streamable.scala index 7839de9df1..2297056de0 100644 --- a/src/compiler/scala/tools/nsc/io/Streamable.scala +++ b/src/compiler/scala/tools/nsc/io/Streamable.scala @@ -8,7 +8,7 @@ package io import java.net.{ URI, URL } import java.io.{ BufferedInputStream, InputStream, PrintStream, File => JFile } -import java.io.{ BufferedReader, InputStreamReader } +import java.io.{ BufferedReader, InputStreamReader, Closeable => JCloseable } import scala.io.{ Codec, BufferedSource, Source } import collection.mutable.ArrayBuffer import Path.fail @@ -106,6 +106,11 @@ object Streamable { def slurp(codec: Codec) = chars(codec).mkString } + /** Call a function on something Closeable, finally closing it. */ + def closing[T <: JCloseable, U](stream: T)(f: T => U): U = + try f(stream) + finally stream.close() + def bytes(is: InputStream): Array[Byte] = new Bytes { val inputStream = is } toByteArray -- cgit v1.2.3