summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/io/File.scala
diff options
context:
space:
mode:
authorJosh Suereth <joshua.suereth@gmail.com>2012-09-18 10:35:26 -0400
committerJosh Suereth <joshua.suereth@gmail.com>2012-09-18 15:36:13 -0400
commitc6dde6a1e884b71ae8bf8e0136287e434594e92b (patch)
tree261fb3b1693806bbcb334e500767304ef67382fc /src/reflect/scala/reflect/io/File.scala
parenta9f95dc29f366d935604f15a4a99cbfd1a1bd275 (diff)
downloadscala-c6dde6a1e884b71ae8bf8e0136287e434594e92b.tar.gz
scala-c6dde6a1e884b71ae8bf8e0136287e434594e92b.tar.bz2
scala-c6dde6a1e884b71ae8bf8e0136287e434594e92b.zip
Fixes SI-6305 scala.tools.nsc.io split between jars.
* migrates scala.tools.nsc.io portions into scala.reflect.io * marks all classes in scala.reflect.io experimental/internal * rewires src/reflect to use new io locations * creates forwarders in scala.tools.nsci.io package object.
Diffstat (limited to 'src/reflect/scala/reflect/io/File.scala')
-rw-r--r--src/reflect/scala/reflect/io/File.scala197
1 files changed, 197 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/io/File.scala b/src/reflect/scala/reflect/io/File.scala
new file mode 100644
index 0000000000..9e306371f7
--- /dev/null
+++ b/src/reflect/scala/reflect/io/File.scala
@@ -0,0 +1,197 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+
+package scala.reflect
+package io
+
+import java.io.{
+ FileInputStream, FileOutputStream, BufferedReader, BufferedWriter, InputStreamReader, OutputStreamWriter,
+ BufferedInputStream, BufferedOutputStream, IOException, PrintStream, PrintWriter, Closeable => JCloseable }
+import java.io.{ File => JFile }
+import java.nio.channels.{ Channel, FileChannel }
+import scala.io.Codec
+import scala.language.{reflectiveCalls, implicitConversions}
+/**
+ * ''Note: This library is considered experimental and should not be used unless you know what you are doing.''
+ */
+object File {
+ def pathSeparator = java.io.File.pathSeparator
+ def separator = java.io.File.separator
+
+ def apply(path: Path)(implicit codec: Codec) = new File(path.jfile)(codec)
+
+ // Create a temporary file, which will be deleted upon jvm exit.
+ def makeTemp(prefix: String = Path.randomPrefix, suffix: String = null, dir: JFile = null) = {
+ val jfile = java.io.File.createTempFile(prefix, suffix, dir)
+ jfile.deleteOnExit()
+ apply(jfile)
+ }
+
+ 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 => }
+ }
+
+ // this is a workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6503430
+ // we are using a static initializer to statically initialize a java class so we don't
+ // trigger java.lang.InternalErrors later when using it concurrently. We ignore all
+ // the exceptions so as not to cause spurious failures when no write access is available,
+ // e.g. google app engine.
+ //
+ // XXX need to put this behind a setting.
+ //
+ // try {
+ // import Streamable.closing
+ // val tmp = java.io.File.createTempFile("bug6503430", null, null)
+ // 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 => ()
+ // }
+}
+import File._
+import Path._
+
+/** An abstraction for files. For character data, a Codec
+ * can be supplied at either creation time or when a method
+ * involving character data is called (with the latter taking
+ * precedence if supplied.) If neither is available, the value
+ * of scala.io.Codec.default is used.
+ *
+ * @author Paul Phillips
+ * @since 2.8
+ *
+ * ''Note: This is library is considered experimental and should not be used unless you know what you are doing.''
+ */
+class File(jfile: JFile)(implicit constructorCodec: Codec) extends Path(jfile) with Streamable.Chars {
+ override val creationCodec = constructorCodec
+ def withCodec(codec: Codec): File = new File(jfile)(codec)
+
+ override def addExtension(ext: String): File = super.addExtension(ext).toFile
+ override def toAbsolute: File = if (isAbsolute) this else super.toAbsolute.toFile
+ override def toDirectory: Directory = new Directory(jfile)
+ override def toFile: File = this
+ override def normalize: File = super.normalize.toFile
+ override def isValid = jfile.isFile() || !jfile.exists()
+ override def length = super[Path].length
+ override def walkFilter(cond: Path => Boolean): Iterator[Path] =
+ if (cond(this)) Iterator.single(this) else Iterator.empty
+
+ /** Obtains an InputStream. */
+ def inputStream() = new FileInputStream(jfile)
+
+ /** Obtains a OutputStream. */
+ def outputStream(append: Boolean = false) = new FileOutputStream(jfile, append)
+ def bufferedOutput(append: Boolean = false) = new BufferedOutputStream(outputStream(append))
+ def printStream(append: Boolean = false) = new PrintStream(outputStream(append), true)
+
+ /** Obtains an OutputStreamWriter wrapped around a FileOutputStream.
+ * This should behave like a less broken version of java.io.FileWriter,
+ * in that unlike the java version you can specify the encoding.
+ */
+ def writer(): OutputStreamWriter = writer(false)
+ def writer(append: Boolean): OutputStreamWriter = writer(append, creationCodec)
+ def writer(append: Boolean, codec: Codec): OutputStreamWriter =
+ new OutputStreamWriter(outputStream(append), codec.charSet)
+
+ /** Wraps a BufferedWriter around the result of writer().
+ */
+ def bufferedWriter(): BufferedWriter = bufferedWriter(false)
+ def bufferedWriter(append: Boolean): BufferedWriter = bufferedWriter(append, creationCodec)
+ def bufferedWriter(append: Boolean, codec: Codec): BufferedWriter =
+ new BufferedWriter(writer(append, codec))
+
+ def printWriter(): PrintWriter = new PrintWriter(bufferedWriter(), true)
+ def printWriter(append: Boolean): PrintWriter = new PrintWriter(bufferedWriter(append), true)
+
+ /** Creates a new file and writes all the Strings to it. */
+ def writeAll(strings: String*): Unit = {
+ val out = bufferedWriter()
+ try strings foreach (out write _)
+ finally out.close()
+ }
+
+ def writeBytes(bytes: Array[Byte]): Unit = {
+ val out = bufferedOutput()
+ try out write bytes
+ finally out.close()
+ }
+
+ def appendAll(strings: String*): Unit = {
+ val out = bufferedWriter(append = true)
+ try strings foreach (out write _)
+ finally out.close()
+ }
+
+ /** Calls println on each string (so it adds a newline in the PrintWriter fashion.) */
+ def printlnAll(strings: String*): Unit = {
+ val out = printWriter()
+ try strings foreach (out println _)
+ finally out.close()
+ }
+
+ def safeSlurp(): Option[String] =
+ try Some(slurp())
+ catch { case _: IOException => None }
+
+ def copyTo(destPath: Path, preserveFileDate: Boolean = false): Boolean = {
+ val CHUNK = 1024 * 1024 * 16 // 16 MB
+ val dest = destPath.toFile
+ if (!isValid) fail("Source %s is not a valid file." format name)
+ if (this.normalize == dest.normalize) fail("Source and destination are the same.")
+ if (!dest.parent.exists) fail("Destination cannot be created.")
+ if (dest.exists && !dest.canWrite) fail("Destination exists but is not writable.")
+ if (dest.isDirectory) fail("Destination exists but is a directory.")
+
+ lazy val in_s = inputStream()
+ lazy val out_s = dest.outputStream()
+ lazy val in = in_s.getChannel()
+ lazy val out = out_s.getChannel()
+
+ try {
+ val size = in.size()
+ var pos, count = 0L
+ while (pos < size) {
+ count = (size - pos) min CHUNK
+ pos += out.transferFrom(in, pos, count)
+ }
+ }
+ 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))
+
+ if (preserveFileDate)
+ dest.lastModified = this.lastModified
+
+ true
+ }
+
+ /** Reflection since we're into the java 6+ API.
+ */
+ def setExecutable(executable: Boolean, ownerOnly: Boolean = true): Boolean = {
+ type JBoolean = java.lang.Boolean
+ val method =
+ try classOf[JFile].getMethod("setExecutable", classOf[Boolean], classOf[Boolean])
+ catch { case _: NoSuchMethodException => return false }
+
+ try method.invoke(jfile, executable: JBoolean, ownerOnly: JBoolean).asInstanceOf[JBoolean].booleanValue
+ catch { case _: Exception => false }
+ }
+}