blob: 8ec204fafeab20ef82e1ee8acdb802543a0d4338 [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]]
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)
override def list(path: String) = entry(path) match {
case Some(entry) if entry.isDirectory => Some(entries(entry))
case _ => None
}
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
}
}