diff options
author | Raphael Jolly <rjolly@users.sourceforge.net> | 2013-03-09 21:54:22 +0100 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-03-11 22:35:54 -0700 |
commit | 3e8f8ddb2ac057ad82e1a7e37f59baff1c0e15ac (patch) | |
tree | 5b510ff5f73e1c645da400ca759bc9d1a0f34fd8 /src/reflect/scala/reflect/io/ZipArchive.scala | |
parent | 9eb21e54bdb1ea23b4215c641c98bd90a8b859cf (diff) | |
download | scala-3e8f8ddb2ac057ad82e1a7e37f59baff1c0e15ac.tar.gz scala-3e8f8ddb2ac057ad82e1a7e37f59baff1c0e15ac.tar.bz2 scala-3e8f8ddb2ac057ad82e1a7e37f59baff1c0e15ac.zip |
SI-874 reflect.io improvements
Diffstat (limited to 'src/reflect/scala/reflect/io/ZipArchive.scala')
-rw-r--r-- | src/reflect/scala/reflect/io/ZipArchive.scala | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/src/reflect/scala/reflect/io/ZipArchive.scala b/src/reflect/scala/reflect/io/ZipArchive.scala index 5414441e00..1342fde3c5 100644 --- a/src/reflect/scala/reflect/io/ZipArchive.scala +++ b/src/reflect/scala/reflect/io/ZipArchive.scala @@ -7,10 +7,12 @@ package scala.reflect package io import java.net.URL -import java.io.{ IOException, InputStream, ByteArrayInputStream } +import java.io.{ IOException, InputStream, ByteArrayInputStream, FilterInputStream } import java.io.{ File => JFile } import java.util.zip.{ ZipEntry, ZipFile, ZipInputStream } +import java.util.jar.Manifest import scala.collection.{ immutable, mutable } +import scala.collection.convert.WrapAsScala.asScalaIterator import scala.annotation.tailrec /** An abstraction for zip files and streams. Everything is written the way @@ -39,6 +41,8 @@ object ZipArchive { */ def fromURL(url: URL): URLZipArchive = new URLZipArchive(url) + def fromManifestURL(url: URL): AbstractFile = new ManifestResources(url) + private def dirName(path: String) = splitPath(path, front = true) private def baseName(path: String) = splitPath(path, front = false) private def splitPath(path0: String, front: Boolean): String = { @@ -227,3 +231,59 @@ final class URLZipArchive(val url: URL) extends ZipArchive(null) { case _ => false } } + +final class ManifestResources(val url: URL) extends ZipArchive(null) { + def iterator = { + val root = new DirEntry("/") + val dirs = mutable.HashMap[String, DirEntry]("/" -> root) + val manifest = new Manifest(input) + val iter = manifest.getEntries().keySet().iterator().filter(_.endsWith(".class")).map(new ZipEntry(_)) + + while (iter.hasNext) { + val zipEntry = iter.next() + val dir = getDir(dirs, zipEntry) + if (zipEntry.isDirectory) dir + else { + class FileEntry() extends Entry(zipEntry.getName) { + override def lastModified = zipEntry.getTime() + override def input = resourceInputStream(path) + override def sizeOption = None + } + val f = new FileEntry() + dir.entries(f.name) = f + } + } + + try root.iterator + finally dirs.clear() + } + + def name = path + def path: String = url.getPath() match { case s => s.substring(0, s.lastIndexOf('!')) } + def input = url.openStream() + def lastModified = + try url.openConnection().getLastModified() + catch { case _: IOException => 0 } + + override def canEqual(other: Any) = other.isInstanceOf[ManifestResources] + override def hashCode() = url.hashCode + override def equals(that: Any) = that match { + case x: ManifestResources => url == x.url + case _ => false + } + + private def resourceInputStream(path: String): InputStream = { + new FilterInputStream(null) { + override def read(): Int = { + if(in == null) in = Thread.currentThread().getContextClassLoader().getResourceAsStream(path); + if(in == null) throw new RuntimeException(path + " not found") + super.read(); + } + + override def close(): Unit = { + super.close(); + in = null; + } + } + } +} |