summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/io/Jar.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-03-16 07:49:16 +0000
committerPaul Phillips <paulp@improving.org>2011-03-16 07:49:16 +0000
commiteb0b73b1160c7e62e2ae0e338a9664b8b53ddbde (patch)
treed1836661a909a33fc805d302183741868582876f /src/compiler/scala/tools/nsc/io/Jar.scala
parentf80801c67545a28f61abd1a36a5ef8b5bc337d87 (diff)
downloadscala-eb0b73b1160c7e62e2ae0e338a9664b8b53ddbde.tar.gz
scala-eb0b73b1160c7e62e2ae0e338a9664b8b53ddbde.tar.bz2
scala-eb0b73b1160c7e62e2ae0e338a9664b8b53ddbde.zip
Undoing some much too hacky code to implement a...
Undoing some much too hacky code to implement a -jar option and then following wherever that led me. Tangible results include: * much beautified scala -help, including documenting some things never before documented in this plane of existence * an improved Jar abstraction * further systemization of system properties In addition, the jars created by -savecompiled are given the right manifest so the jar is runnable. That means you can: scala -savecompiled bippy.scala arg1 arg2 scala -jar bippy.scala.jar arg1 arg2 And both lines should yield the same result. No review.
Diffstat (limited to 'src/compiler/scala/tools/nsc/io/Jar.scala')
-rw-r--r--src/compiler/scala/tools/nsc/io/Jar.scala77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/io/Jar.scala b/src/compiler/scala/tools/nsc/io/Jar.scala
new file mode 100644
index 0000000000..0796742fb6
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/io/Jar.scala
@@ -0,0 +1,77 @@
+package scala.tools.nsc
+package io
+
+import java.io.{ InputStream, OutputStream, IOException, FileNotFoundException, FileInputStream }
+import java.util.jar._
+import collection.JavaConverters._
+import Attributes.Name
+
+class Jar(file: File) extends Iterable[JarEntry] {
+ def this(path: String) = this(File(path))
+ protected def errorFn(msg: String): Unit = Console println msg
+
+ lazy val jarFile = new JarFile(file.jfile)
+ lazy val manifest = withJarInput(s => Option(s.getManifest))
+ def mainClass = manifest map (f => f(Name.MAIN_CLASS))
+
+ def withJarInput[T](f: JarInputStream => T): T = {
+ val in = new JarInputStream(file.inputStream())
+ try f(in)
+ finally in.close()
+ }
+ def jarWriter() = new JarWriter(file)
+
+ override def foreach[U](f: JarEntry => U): Unit = withJarInput { in =>
+ Iterator continually in.getNextJarEntry() takeWhile (_ != null) foreach f
+ }
+ override def iterator: Iterator[JarEntry] = this.toList.iterator
+ def fileishIterator: Iterator[Fileish] = jarFile.entries.asScala map (x => Fileish(x, () => getEntryStream(x)))
+
+ private def getEntryStream(entry: JarEntry) = jarFile getInputStream entry match {
+ case null => errorFn("No such entry: " + entry) ; null
+ case x => x
+ }
+ override def toString = "" + file
+}
+
+class JarWriter(file: File, val manifest: Manifest = new Manifest()) {
+ private lazy val out = new JarOutputStream(file.outputStream(), manifest)
+ def writeAllFrom(dir: Directory) = {
+ try dir.list foreach (x => addEntry(x, ""))
+ finally out.close()
+
+ file
+ }
+ private def addFile(entry: File, prefix: String) {
+ out putNextEntry new JarEntry(prefix + entry.name)
+ try transfer(entry.inputStream(), out)
+ finally out.closeEntry()
+ }
+ private def addEntry(entry: Path, prefix: String) {
+ if (entry.isFile) addFile(entry.toFile, prefix)
+ else addDirectory(entry.toDirectory, prefix + entry.name + "/")
+ }
+ private def addDirectory(entry: Directory, prefix: String) {
+ entry.list foreach (p => addEntry(p, prefix))
+ }
+ private def transfer(in: InputStream, out: OutputStream) = {
+ val buf = new Array[Byte](10240)
+ def loop: Unit = in.read(buf, 0, buf.length) match {
+ case -1 => in.close()
+ case n => out.write(buf, 0, n) ; loop
+ }
+ loop
+ }
+}
+
+object Jar {
+ // CLASS_PATH
+ // CONTENT_TYPE
+
+ def create(file: File, sourceDir: Directory, mainClass: String): File = {
+ val writer = new Jar(file).jarWriter()
+ writer.manifest(Name.MANIFEST_VERSION) = "1.0"
+ writer.manifest(Name.MAIN_CLASS) = mainClass
+ writer writeAllFrom sourceDir
+ }
+}