2010-08-14 15:55:49 +02:00
|
|
|
/* sbt -- Simple Build Tool
|
|
|
|
|
* Copyright 2010 Mark Harrah
|
|
|
|
|
*/
|
|
|
|
|
package sbt
|
|
|
|
|
package std
|
|
|
|
|
|
2010-09-08 20:30:27 +02:00
|
|
|
import java.io.{InputStream, IOException, OutputStream, Reader, Writer}
|
2010-08-14 15:55:49 +02:00
|
|
|
import java.io.{BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter, PrintWriter}
|
|
|
|
|
import java.io.{Closeable, File, FileInputStream, FileOutputStream, InputStreamReader, OutputStreamWriter}
|
|
|
|
|
|
|
|
|
|
import Path._
|
|
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
// no longer specific to Tasks, so 'TaskStreams' should be renamed
|
|
|
|
|
sealed trait TaskStreams[Key]
|
2010-08-14 15:55:49 +02:00
|
|
|
{
|
|
|
|
|
def default = outID
|
|
|
|
|
def outID = "out"
|
|
|
|
|
def errorID = "err"
|
|
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
def readText(key: Key, sid: String = default): BufferedReader
|
|
|
|
|
def readBinary(a: Key, sid: String = default): BufferedInputStream
|
2010-08-14 15:55:49 +02:00
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
final def readText(a: Key, sid: Option[String]): BufferedReader = readText(a, getID(sid))
|
|
|
|
|
final def readBinary(a: Key, sid: Option[String]): BufferedInputStream = readBinary(a, getID(sid))
|
2010-08-14 15:55:49 +02:00
|
|
|
|
|
|
|
|
def text(sid: String = default): PrintWriter
|
|
|
|
|
def binary(sid: String = default): BufferedOutputStream
|
|
|
|
|
|
|
|
|
|
// default logger
|
2010-09-04 14:45:34 +02:00
|
|
|
final lazy val log: Logger = log(default)
|
|
|
|
|
def log(sid: String): Logger
|
2010-08-14 15:55:49 +02:00
|
|
|
|
|
|
|
|
private[this] def getID(s: Option[String]) = s getOrElse default
|
|
|
|
|
}
|
2011-05-12 15:26:15 +02:00
|
|
|
sealed trait ManagedStreams[Key] extends TaskStreams[Key]
|
2010-08-14 15:55:49 +02:00
|
|
|
{
|
|
|
|
|
def open()
|
|
|
|
|
def close()
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-06 03:39:34 +01:00
|
|
|
trait Streams[Key]
|
2010-08-14 15:55:49 +02:00
|
|
|
{
|
2011-02-06 03:39:34 +01:00
|
|
|
def apply(a: Key): ManagedStreams[Key]
|
2011-01-21 23:22:18 +01:00
|
|
|
def use[T](key: Key)(f: TaskStreams[Key] => T): T =
|
|
|
|
|
{
|
|
|
|
|
val s = apply(key)
|
|
|
|
|
s.open()
|
|
|
|
|
try { f(s) } finally { s.close() }
|
|
|
|
|
}
|
2010-08-14 15:55:49 +02:00
|
|
|
}
|
2011-02-06 03:39:34 +01:00
|
|
|
trait CloseableStreams[Key] extends Streams[Key] with java.io.Closeable
|
2010-08-14 15:55:49 +02:00
|
|
|
object Streams
|
|
|
|
|
{
|
2010-09-08 20:30:27 +02:00
|
|
|
private[this] val closeQuietly = (c: Closeable) => try { c.close() } catch { case _: IOException => () }
|
2011-02-06 03:39:34 +01:00
|
|
|
|
|
|
|
|
def closeable[Key](delegate: Streams[Key]): CloseableStreams[Key] = new CloseableStreams[Key] {
|
|
|
|
|
private[this] val streams = new collection.mutable.HashMap[Key,ManagedStreams[Key]]
|
|
|
|
|
|
|
|
|
|
def apply(key: Key): ManagedStreams[Key] =
|
|
|
|
|
synchronized { streams.getOrElseUpdate(key, delegate(key)) }
|
|
|
|
|
|
|
|
|
|
def close(): Unit =
|
|
|
|
|
synchronized { streams.values.foreach(_.close() ); streams.clear() }
|
|
|
|
|
}
|
2010-08-14 15:55:49 +02:00
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
def apply[Key](taskDirectory: Key => File, name: Key => String, mkLogger: (Key, PrintWriter) => Logger): Streams[Key] = new Streams[Key] {
|
2010-08-14 15:55:49 +02:00
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
def apply(a: Key): ManagedStreams[Key] = new ManagedStreams[Key] {
|
2010-08-14 15:55:49 +02:00
|
|
|
private[this] var opened: List[Closeable] = Nil
|
|
|
|
|
private[this] var closed = false
|
|
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
def readText(a: Key, sid: String = default): BufferedReader =
|
|
|
|
|
make(a, sid)(f => new BufferedReader(new InputStreamReader(new FileInputStream(f), IO.defaultCharset)) )
|
2010-08-14 15:55:49 +02:00
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
def readBinary(a: Key, sid: String = default): BufferedInputStream =
|
|
|
|
|
make(a, sid)(f => new BufferedInputStream(new FileInputStream(f)))
|
2010-08-14 15:55:49 +02:00
|
|
|
|
|
|
|
|
def text(sid: String = default): PrintWriter =
|
|
|
|
|
make(a, sid)(f => new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), IO.defaultCharset))) )
|
|
|
|
|
|
|
|
|
|
def binary(sid: String = default): BufferedOutputStream =
|
|
|
|
|
make(a, sid)(f => new BufferedOutputStream(new FileOutputStream(f)))
|
|
|
|
|
|
2010-09-04 14:45:34 +02:00
|
|
|
def log(sid: String): Logger = mkLogger(a, text(sid))
|
|
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
def make[T <: Closeable](a: Key, sid: String)(f: File => T): T = synchronized {
|
2010-08-14 15:55:49 +02:00
|
|
|
checkOpen()
|
|
|
|
|
val file = taskDirectory(a) / sid
|
2011-05-18 13:56:58 +02:00
|
|
|
IO.touch(file, false)
|
2010-08-14 15:55:49 +02:00
|
|
|
val t = f( file )
|
|
|
|
|
opened ::= t
|
|
|
|
|
t
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def open() {}
|
|
|
|
|
|
|
|
|
|
def close(): Unit = synchronized {
|
|
|
|
|
if(!closed)
|
|
|
|
|
{
|
|
|
|
|
closed = true
|
|
|
|
|
opened foreach closeQuietly
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
def checkOpen(): Unit = synchronized {
|
|
|
|
|
if(closed) error("Streams for '" + name(a) + "' have been closed.")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|