All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalax.file.ramfs.tree.scala Maven / Gradle / Ivy

/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2009-2010, Jesse Eichar          **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

package scalax.file
package ramfs

import scala.collection.mutable.ArrayBuffer
import java.io.{
  OutputStream, InputStream, ByteArrayOutputStream, ByteArrayInputStream, IOException
}
import scalax.io._
import scalax.io.managed._
import StandardOpenOption._

private[ramfs] trait NodeFac {
  def create(name:String):Node
  def accepts(node:Node):Boolean
}

private[ramfs] object FileNode extends NodeFac {
  def create(name:String) = new FileNode(name)
  def accepts(node:Node) = node.isInstanceOf[FileNode]
}


private[ramfs] object DirNode extends NodeFac {
  def create(name:String) = new DirNode(name)
  def accepts(node:Node) = node.isInstanceOf[DirNode]
}

private[ramfs] trait Node {
  var name:String
  var lastModified:Long
  var (canRead, canWrite, canExecute) = initAccess;
  protected def initAccess = (true, true, false)
  override def toString = getClass.getSimpleName+": "+name
}

private[ramfs] class FileNode(var name:String) extends Node {
    var data = ArrayBuffer[Byte]()
    var lastModified = System.currentTimeMillis
    def inputStream : InputStream = new ByteArrayInputStream(data.toArray)

    def outputResource(owner:RamPath, openOptions: OpenOption*) : OutputStream = {
      require (owner.node exists {_ == this})
      if (!canWrite) {
        throw new IOException("Not permitted to write to this file")
      }

      def newResource = {
        val out = new ByteArrayOutputStream(){
          override def close() {
            super.close()
            if(openOptions contains DeleteOnClose) {
              owner.delete(force=true);
            } else {
              data = ArrayBuffer(this.toByteArray:_*)
            }
          }
        }

        if(openOptions contains Append) out.write(data.toArray,0,data.size);

        out
      }

      if(openOptions contains Truncate) data.clear()

      newResource
    }

    def channel(owner:RamPath, openOptions: OpenOption*) = {
      def newchannel = new ArrayBufferSeekableChannel(this.data,openOptions:_*)(_ => owner.delete(force=true), _ => ())
      newchannel
    }
  }

private[ramfs] class DirNode(var name:String) extends Node {
  override protected def initAccess = (true, true, true)

  val children = ArrayBuffer[Node]()
  var lastModified = System.currentTimeMillis
  val self = this;

  def lookup(path:Seq[String]) : Option[Node]= {
//    println("lookup",name,children,path)
    path match {
      case Seq(s) if s == name =>
        Some(self)
      case Seq(s) =>
        children.find {_.name == s}
      case Seq(s, rest @ _*) if s == name =>
        self.lookup(rest)
      case Seq(s, rest @ _*) =>
        children.find {_.name == s} match {
          case Some(x:DirNode) => x.lookup(rest)
          case _ => None
        }
      }
  }

  def create(path:Seq[String], fac:NodeFac) : Node = path match {
    case Seq(s) if s == name =>
      // TODO Consider a specific type of exception
      if(fac accepts self) throw new IOException(name+" is a DirNode not a file")
      self
    case Seq(s) =>
      children.find {_.name == path.head} match {
        case Some(x) if fac accepts x =>
          // good
          self
        case Some(x) =>
          // TODO specific exception type ??
          throw new IOException(x+" is not a "+fac)
        case None if !canWrite =>
          throw new IOException("Permission denied to create file in "+name)
        case None =>
          val newNode = fac create s
          children += newNode
          newNode
      }
    case Seq(s, rest @ _*) =>
      children.find {_.name == path.head} match {
        case Some(f:FileNode) =>
           throw new NotDirectoryException(f.name)
        case Some(d) if !d.canWrite =>
          throw new IOException("Permission denied to create file in "+name)
        case Some (d:DirNode) =>
          d.create(rest, fac)
        case None if !canWrite =>
          throw new IOException("Permission denied to create file in "+name)
        case None =>
          val newNode = new DirNode(s)
          children += newNode
          newNode.create(rest,fac)
      }
    case _ =>
      throw new Error("uh oh what's going on?")
  }

  def mkString() : String = {
    name + children.map{
      case f:FileNode => name
      case d:DirNode => d.mkString()
    }.mkString("{",",","}")
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy