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 | |
parent | 9eb21e54bdb1ea23b4215c641c98bd90a8b859cf (diff) | |
download | scala-3e8f8ddb2ac057ad82e1a7e37f59baff1c0e15ac.tar.gz scala-3e8f8ddb2ac057ad82e1a7e37f59baff1c0e15ac.tar.bz2 scala-3e8f8ddb2ac057ad82e1a7e37f59baff1c0e15ac.zip |
SI-874 reflect.io improvements
-rw-r--r-- | src/reflect/scala/reflect/io/AbstractFile.scala | 34 | ||||
-rw-r--r-- | src/reflect/scala/reflect/io/Path.scala | 9 | ||||
-rw-r--r-- | src/reflect/scala/reflect/io/ZipArchive.scala | 62 |
3 files changed, 90 insertions, 15 deletions
diff --git a/src/reflect/scala/reflect/io/AbstractFile.scala b/src/reflect/scala/reflect/io/AbstractFile.scala index 4d6f14c71d..8b69efc749 100644 --- a/src/reflect/scala/reflect/io/AbstractFile.scala +++ b/src/reflect/scala/reflect/io/AbstractFile.scala @@ -7,7 +7,7 @@ package scala.reflect package io -import java.io.{ FileOutputStream, IOException, InputStream, OutputStream, BufferedOutputStream } +import java.io.{ FileOutputStream, IOException, InputStream, OutputStream, BufferedOutputStream, ByteArrayOutputStream } import java.io.{ File => JFile } import java.net.URL import scala.collection.mutable.ArrayBuffer @@ -54,6 +54,8 @@ object AbstractFile { if (url == null || !Path.isExtensionJarOrZip(url.getPath)) null else ZipArchive fromURL url } + + def getResources(url: URL): AbstractFile = ZipArchive fromManifestURL url } /** @@ -156,16 +158,28 @@ abstract class AbstractFile extends Iterable[AbstractFile] { @throws(classOf[IOException]) def toByteArray: Array[Byte] = { val in = input - var rest = sizeOption.getOrElse(0) - val arr = new Array[Byte](rest) - while (rest > 0) { - val res = in.read(arr, arr.length - rest, rest) - if (res == -1) - throw new IOException("read error") - rest -= res + sizeOption match { + case Some(size) => + var rest = size + val arr = new Array[Byte](rest) + while (rest > 0) { + val res = in.read(arr, arr.length - rest, rest) + if (res == -1) + throw new IOException("read error") + rest -= res + } + in.close() + arr + case None => + val out = new ByteArrayOutputStream() + var c = in.read() + while(c != -1) { + out.write(c) + c = in.read() + } + in.close() + out.toByteArray() } - in.close() - arr } /** Returns all abstract subfiles of this abstract directory. */ diff --git a/src/reflect/scala/reflect/io/Path.scala b/src/reflect/scala/reflect/io/Path.scala index 3b5d3079cd..44fb41a1cd 100644 --- a/src/reflect/scala/reflect/io/Path.scala +++ b/src/reflect/scala/reflect/io/Path.scala @@ -56,10 +56,11 @@ object Path { def roots: List[Path] = java.io.File.listRoots().toList map Path.apply def apply(path: String): Path = apply(new JFile(path)) - def apply(jfile: JFile): Path = + def apply(jfile: JFile): Path = try { if (jfile.isFile) new File(jfile) else if (jfile.isDirectory) new Directory(jfile) else new Path(jfile) + } catch { case ex: SecurityException => new Path(jfile) } /** Avoiding any shell/path issues by only using alphanumerics. */ private[io] def randomPrefix = alphanumeric take 6 mkString "" @@ -186,10 +187,10 @@ class Path private[io] (val jfile: JFile) { // Boolean tests def canRead = jfile.canRead() def canWrite = jfile.canWrite() - def exists = jfile.exists() + def exists = try jfile.exists() catch { case ex: SecurityException => false } - def isFile = jfile.isFile() - def isDirectory = jfile.isDirectory() + def isFile = try jfile.isFile() catch { case ex: SecurityException => false } + def isDirectory = try jfile.isDirectory() catch { case ex: SecurityException => false } def isAbsolute = jfile.isAbsolute() def isEmpty = path.length == 0 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; + } + } + } +} |