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

replpp.shaded.os.ResourcePath.scala Maven / Gradle / Ivy

There is a newer version: 0.1.98
Show newest version
package replpp.shaded
package os

import java.io.InputStream

import scala.language.implicitConversions

object ResourcePath {
  def resource(resRoot: ResourceRoot) = {
    new ResourcePath(resRoot, Array.empty[String])
  }
}

/**
 * Represents path to a resource on the java classpath.
 *
 * Classloaders are tricky: http://stackoverflow.com/questions/12292926
 */
class ResourcePath private[os] (val resRoot: ResourceRoot, segments0: Array[String])
    extends BasePathImpl with ReadablePath with SegmentedPath {
  def getInputStream = resRoot.getResourceAsStream(segments.mkString("/")) match {
    case null => throw ResourceNotFoundException(this)
    case stream => stream
  }
  def toSource = new Source.WritableSource(getInputStream)
  val segments: IndexedSeq[String] = segments0.toIndexedSeq
  type ThisType = ResourcePath
  def lastOpt = segments0.lastOption
  override def toString = resRoot.errorName + "/" + segments0.mkString("/")
  protected[this] def make(p: Seq[String], ups: Int) = {
    if (ups > 0) {
      throw PathError.AbsolutePathOutsideRoot
    }
    new ResourcePath(resRoot, p.toArray[String])
  }

  def relativeTo(base: ResourcePath) = {
    var newUps = 0
    var s2 = base.segments

    while (!segments0.startsWith(s2)) {
      s2 = s2.dropRight(1)
      newUps += 1
    }
    new RelPath(segments0.drop(s2.length), newUps)
  }

  def startsWith(target: ResourcePath) = {
    segments0.startsWith(target.segments)
  }

}

/**
 * Thrown when you try to read from a resource that doesn't exist.
 * @param path
 */
case class ResourceNotFoundException(path: ResourcePath) extends Exception(path.toString)

/**
 * Represents a possible root where classpath resources can be loaded from;
 * either a [[ResourceRoot.ClassLoader]] or a [[ResourceRoot.Class]]. Resources
 * loaded from classloaders are always loaded via their absolute path, while
 * resources loaded via classes are always loaded relatively.
 */
sealed trait ResourceRoot {
  def getResourceAsStream(s: String): InputStream
  def errorName: String
}
object ResourceRoot {
  private[this] def renderClassloader(cl: java.lang.ClassLoader) = {
    cl.getClass.getName + "@" + java.lang.Integer.toHexString(cl.hashCode())
  }
  implicit def classResourceRoot(cls: java.lang.Class[_]): ResourceRoot = Class(cls)
  case class Class(cls: java.lang.Class[_]) extends ResourceRoot {
    def getResourceAsStream(s: String) = cls.getResourceAsStream(s)
    def errorName = renderClassloader(cls.getClassLoader) + ":" + cls.getName
  }
  implicit def classLoaderResourceRoot(cl: java.lang.ClassLoader): ResourceRoot = ClassLoader(cl)
  case class ClassLoader(cl: java.lang.ClassLoader) extends ResourceRoot {
    def getResourceAsStream(s: String) = cl.getResourceAsStream(s)
    def errorName = renderClassloader(cl)
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy