blob: dfe40cdf6e93eac12daab07c87795615ae20ee57 [file] [log] [blame] [raw]
package li.cil.oc.server.fs
import java.util.zip.{ZipEntry, ZipFile}
import scala.collection.mutable
// TODO we may want to read in the complete zip file (and keep a cache in the
// factory) to avoid a ton of open real file handles.
class ZipFileInputStreamFileSystem(val zip: ZipFile, val root: String) extends InputStreamFileSystem {
private val directories = mutable.Map.empty[ZipEntry, Array[String]]
// ----------------------------------------------------------------------- //
def spaceTotal = spaceUsed
def spaceUsed = spaceUsed_
private lazy val spaceUsed_ = {
var size = 0L
val enum = zip.entries()
while (enum.hasMoreElements) size += enum.nextElement.getSize
size
}
// ----------------------------------------------------------------------- //
override def exists(path: String) = entry(path).isDefined
override def size(path: String) = entry(path) match {
case Some(file) if !file.isDirectory => file.getSize
case _ => 0L
}
override def isDirectory(path: String) = entry(path).exists(_.isDirectory)
def lastModified(path: String) = entry(path) match {
case Some(file) => file.getTime
case _ => 0L
}
override def list(path: String) = entry(path) match {
case Some(entry) if entry.isDirectory => entries(entry)
case _ => null
}
override def close() {
super.close()
zip.close()
directories.clear()
}
// ----------------------------------------------------------------------- //
override protected def openInputStream(path: String) = entry(path).map(entry => zip.getInputStream(entry))
// ----------------------------------------------------------------------- //
private def entry(path: String) = Option(zip.getEntry((root + path.replace("\\", "/")).replace("//", "/")))
private def entries(path: ZipEntry) = directories.get(path).getOrElse {
val pathName = root + path.getName
val list = mutable.ArrayBuffer.empty[String]
val iterator = zip.entries
while (iterator.hasMoreElements) {
val child = iterator.nextElement
if (child.getName.startsWith(pathName)) {
list += child.getName.substring(pathName.length)
}
}
val children = list.toArray
directories += path -> children
children
}
}