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

com.rojoma.simplearm.v2.ResourceUtil.scala Maven / Gradle / Ivy

The newest version!
package com.rojoma.simplearm.v2

import scala.language.implicitConversions

import java.io.{File, IOException}
import java.nio.file.{Path, Files, SimpleFileVisitor, FileVisitResult}
import java.nio.file.attribute

import com.rojoma.simplearm.v2.{managed => mgd}

object ResourceUtil {
  def withCleanup[T, U](f: => T)(cleanup: T => U): Managed[T] =
    mgd(f)(new Resource[T] { override def close(t: T) = cleanup(t) })

  /** Helpers to create temporary files.
    */
  object Temporary {
    sealed abstract class TempPath
    object TempPath {
      implicit def tempPathOfPath(p: Path): TempPath = PathTempPath(p)
      implicit def tempPathOfFile(f: File): TempPath = PathTempPath(f.toPath)
    }
    case object DefaultTempPath extends TempPath
    case class PathTempPath(path: Path) extends TempPath

    sealed abstract class PathLike[T] {
      private[Temporary] val fileResource: Resource[T]
      private[Temporary] val directoryResource: Resource[T]
    }

    object PathLike {
      implicit case object FilePathLike extends PathLike[File] {
        private[Temporary] val fileResource = new Resource[File] {
          private val ppr = PathPathLike.fileResource
          override def close(dir: File) {
            ppr.close(dir.toPath)
          }
        }
        private[Temporary] val directoryResource = new Resource[File] {
          private val ppr = PathPathLike.directoryResource
          override def close(dir: File) {
            ppr.close(dir.toPath)
          }
        }
      }

      implicit case object PathPathLike extends PathLike[Path] {
        private[Temporary] val fileResource = new Resource[Path] {
          override def close(file: Path) =
            Files.deleteIfExists(file)
        }
        private[Temporary] val directoryResource = new Resource[Path] {
          private val visitor = new SimpleFileVisitor[Path] {
            override def visitFile(file: Path, attrs: attribute.BasicFileAttributes) = {
              Files.deleteIfExists(file)
              FileVisitResult.CONTINUE
            }
            override def postVisitDirectory(dir: Path, e: IOException) = {
              if(e != null) throw e
              Files.deleteIfExists(dir)
              FileVisitResult.CONTINUE
            }
          }

          override def close(dir: Path) {
            Files.walkFileTree(dir, visitor)
          }
        }
      }
    }

    object File {
      private val ppr = PathLike.PathPathLike.fileResource

      private def createTempFile(dir: TempPath, prefix: String, suffix: String): File = {
        val path = createTempPath(dir, prefix, suffix)
        try {
          path.toFile
        } catch {
          case e: Throwable =>
            try {
              ppr.close(path)
            } catch {
              case e2: Throwable =>
                if(e ne e2) e.addSuppressed(e2)
            }
            throw e
        }
      }

      private def createTempPath(dir: TempPath, prefix: String, suffix: String): Path =
        dir match {
          case DefaultTempPath =>
            Files.createTempFile(prefix, suffix)
          case PathTempPath(dir) =>
            Files.createTempFile(dir, prefix, suffix)
        }

      def scoped[T](rs: ResourceScope, dir: TempPath = DefaultTempPath, prefix: String = "tmp", suffix: String = ".tmp")(implicit ev: PathLike[T]): T =
        ev match {
          case PathLike.FilePathLike =>
            rs.open(createTempFile(dir, prefix, suffix))(ev.fileResource)
          case PathLike.PathPathLike =>
            rs.open(createTempPath(dir, prefix, suffix))(ev.fileResource)
        }

      def managed[T](dir: TempPath = DefaultTempPath, prefix: String = "tmp", suffix: String = ".tmp")(implicit ev: PathLike[T]): Managed[T] =
        ev match {
          case PathLike.FilePathLike =>
            mgd(createTempFile(dir, prefix, suffix))(ev.fileResource)
          case PathLike.PathPathLike =>
            mgd(createTempPath(dir, prefix, suffix))(ev.fileResource)
        }
    }

    object Directory {
      private val ppr = PathLike.PathPathLike.directoryResource

      private def createTempDirFile(dir: TempPath, prefix: String): File = {
        val path = createTempDirPath(dir, prefix)
        try {
          path.toFile
        } catch {
          case e: Throwable =>
            try {
              ppr.close(path)
            } catch {
              case e2: Throwable =>
                if(e ne e2) e.addSuppressed(e2)
            }
            throw e
        }
      }

      private def createTempDirPath(dir: TempPath, prefix: String): Path =
        dir match {
          case DefaultTempPath =>
            Files.createTempDirectory(prefix)
          case PathTempPath(dir) =>
            Files.createTempDirectory(dir, prefix)
        }


      def scoped[T](rs: ResourceScope, dir: TempPath = DefaultTempPath, prefix: String = "tmp")(implicit ev: PathLike[T]): T =
        ev match {
          case PathLike.FilePathLike =>
            rs.open(createTempDirFile(dir, prefix))(ev.directoryResource)
          case PathLike.PathPathLike =>
            rs.open(createTempDirPath(dir, prefix))(ev.directoryResource)
        }

      def managed[T](dir: TempPath = DefaultTempPath, prefix: String = "tmp")(implicit ev: PathLike[T]): Managed[T] =
        ev match {
          case PathLike.FilePathLike =>
            mgd(createTempDirFile(dir, prefix))(ev.directoryResource)
          case PathLike.PathPathLike =>
            mgd(createTempDirPath(dir, prefix))(ev.directoryResource)
        }
    }
  }

  @deprecated("use Temporary.File instead", since="2.3.0")
  object TempFile {
    def scoped(dir: Path, rs: ResourceScope): Path =
      Temporary.File.scoped[Path](rs, dir = dir)

    def scoped(rs: ResourceScope): Path =
      Temporary.File.scoped[Path](rs)

    def managed(dir: Path): Managed[Path] =
      Temporary.File.managed[Path](dir = dir)

    def managed(): Managed[Path] =
      Temporary.File.managed[Path]()
  }

  @deprecated("use Temporary.Directory instead", since="2.3.0")
  object TempDir {
    def scoped(dir: Path, rs: ResourceScope): Path =
      Temporary.Directory.scoped[Path](rs, dir = dir)

    def scoped(rs: ResourceScope): Path =
      Temporary.Directory.scoped[Path](rs)

    def managed(dir: Path): Managed[Path] =
      Temporary.Directory.managed[Path](dir = dir)

    def managed(): Managed[Path] =
      Temporary.Directory.managed[Path]()
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy