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

org.backuity.puppet.Shell.scala Maven / Gradle / Ivy

package org.backuity.puppet

import java.io.File
import java.nio.file.Path

import org.apache.commons.io.IOUtils

trait Shell {
  /** @throws CommandException if the command failed */
  def exec(cmd: String, path: Path) : String = {
    exec(cmd, path.toFile)
  }

  /** @throws CommandException if the command failed */
  def exec(cmd: String, dir: File) : String
}

case class CommandException(cmd: String, dir: File, returnCode: Int, stderr: String) extends
  RuntimeException(s"Command '$cmd' executed in $dir failed ($returnCode):\n$stderr")

class ShellImpl(implicit log: Logger) extends Shell {
  override def exec(cmd: String, dir: File): String = {
    log.debug(s"$dir $$ $cmd")
    val process = Runtime.getRuntime.exec(ShellImpl.tokenize(cmd), null, dir)
    process.waitFor() match {
      case 0 =>
        val stdout = process.getInputStream
        if( stdout == null ) {
          ""
        } else {
          IOUtils.toString(stdout)
        }

      case errorCode =>
        val stderr = IOUtils.toString(process.getErrorStream)
        throw CommandException(cmd, dir, errorCode, stderr)
    }
  }
}

object ShellImpl {
  def tokenize(cmd: String) : Array[String] = {
    var tokens = List.empty[String]
    var token = ""

    def addToken(): Unit = {
      tokens ::= token
      token = ""
    }

    def addToToken(char: Char): Unit = {
      token += char
    }

    var withinSingleQuote = false
    var withinDoubleQuote = false
    for( i <- 0 until cmd.length) {
      cmd(i) match {
        case '\'' =>
          withinSingleQuote = !withinSingleQuote
          if( withinDoubleQuote ) {
            addToToken('\'')
          }

        case '"' =>
          withinDoubleQuote = !withinDoubleQuote
          if( withinSingleQuote ) {
            addToToken('"')
          }

        case ' ' =>
          if( !withinSingleQuote && !withinDoubleQuote ) {
            addToken()
          } else {
            addToToken(' ')
          }

        case other => addToToken(other)
      }
    }
    if( !token.isEmpty ) addToken()

    tokens.reverse.toArray
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy