blob: 0cfa3dff0d7f8d3771de03402a1a5069baf9601a [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 ZipFileSystem(val zip: ZipFile, val root: String) extends InputStreamFileSystem {
private val directories = mutable.Map.empty[ZipEntry, Array[String]]
def exists(path: String) = entry(path).isDefined
def size(path: String) = entry(path).fold(0L)(_.getSize)
def isDirectory(path: String) = entry(path).exists(_.isDirectory)
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()
}
protected def openInputStream(path: String, handle: Long) = 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
}
}