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

fr.iscpif.gridscale.ssh.SSHStorage.scala Maven / Gradle / Ivy

There is a newer version: 1.100
Show newest version
/*
 * Copyright (C) 2012 Romain Reuillon
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */

package fr.iscpif.gridscale.ssh

import java.io.InputStream
import java.util.logging.{ Level, Logger }

import fr.iscpif.gridscale.storage._

import scala.collection.JavaConversions._
import scala.concurrent.duration._

object SSHStorage {

  def apply(host: String, port: Int = 22, timeout: Duration = 1 minute)(implicit credential: SSHAuthentication) = {
    val (_port, _host, _credential, _timeout) = (port, host, credential, timeout)

    new SSHStorage {
      override def credential: SSHAuthentication = _credential
      override def host: String = _host
      override def timeout: Duration = _timeout
      override def port: Int = _port
    }
  }

}

trait SSHStorage extends Storage with SSHHost { storage ⇒

  object FilePermission {

    sealed abstract class FilePermission

    case object USR_RWX extends FilePermission

    case object GRP_RWX extends FilePermission

    case object OTH_RWX extends FilePermission
    def toMask(fps: Set[FilePermission]): Int = {

      import net.schmizz.sshj.xfer.{ FilePermission ⇒ SSHJFilePermission }

      SSHJFilePermission.toMask(
        fps map {
          case USR_RWX ⇒ SSHJFilePermission.USR_RWX
          case GRP_RWX ⇒ SSHJFilePermission.GRP_RWX
          case OTH_RWX ⇒ SSHJFilePermission.OTH_RWX
        })
    }
  }

  def home = withSftpClient {
    _.canonicalize(".")
  }

  override def exists(path: String): Boolean = withSftpClient { c ⇒
    c.exists(path)
  }

  override def errorWrapping(operation: String, t: Throwable) =
    t match {
      case e: net.schmizz.sshj.sftp.SFTPException if e.getMessage == "No such file" ⇒
        new SSHException.NoSuchFileException(s"$operation: " + e.getMessage)
      case t: Throwable ⇒ super.errorWrapping(operation, t)
    }

  def chmod(path: String, perms: FilePermission.FilePermission*) = withSftpClient {
    _.chmod(path, FilePermission.toMask(perms.toSet[FilePermission.FilePermission]))
  }

  def _list(path: String) = withSftpClient {
    _.ls(path)(e ⇒ e == "." || e == "..")
  }

  def _makeDir(path: String) = withSftpClient {
    _.mkdir(path)
  }

  def _rmDir(path: String) = withSftpClient {
    rmDirWithClient(path)(_)
  }

  private def rmDirWithClient(path: String)(c: SFTPClient): Unit = wrapException(s"rm dir $path") {
    c.ls(path)(_ ⇒ true).foreach {
      entry ⇒
        val child = path + "/" + entry.name
        entry.`type` match {
          case FileType      ⇒ rmFileWithClient(child)(c)
          case LinkType      ⇒ rmFileWithClient(child)(c)
          case DirectoryType ⇒ rmDirWithClient(child)(c)
          case UnknownType   ⇒ rmFileWithClient(child)(c)
        }
    }
    c.rmdir(path)
  }

  def _rmFile(path: String) = withSftpClient {
    rmFileWithClient(path)(_)
  }

  def _mv(from: String, to: String) = withSftpClient {
    _.rename(from, to)
  }

  protected def rmFileWithClient(path: String)(implicit c: SFTPClient) = wrapException(s"rm $path") {
    c.rm(path)
  }


  // FIXME resource not released in normal case!
  def withNotClosedResource[R <: { def release(connection: SSHClient)}, T](f: SFTPClient => T): T = withConnection { connection =>
    val sftpClient =
      try connection.newSFTPClient
      catch {
        case e: Throwable ⇒
          release(connection)
          throw e
      }

      f(sftpClient)
  }

  override def _read(path: String): InputStream = withNotClosedResource(_.readAheadFileInputStream(path))

  // FIXME signature incoherent with read
  override def _write(is: InputStream, path: String): Unit = withSftpClient(_.fileOutputStream(is, path))
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy