src/Pure/System/standard_system.scala
author wenzelm
Sun, 25 Nov 2012 20:17:04 +0100
changeset 51218 00d8ad713e32
parent 49426 5b3440850d36
child 51314 f70b3712040f
permissions -rw-r--r--
explicit module UTF8;
     1 /*  Title:      Pure/System/standard_system.scala
     2     Module:     PIDE
     3     Author:     Makarius
     4 
     5 Standard system operations, with basic Cygwin/Posix compatibility.
     6 */
     7 
     8 package isabelle
     9 
    10 import java.lang.System
    11 import java.util.regex.Pattern
    12 import java.util.Locale
    13 import java.net.URL
    14 import java.io.{File => JFile}
    15 
    16 import scala.util.matching.Regex
    17 
    18 
    19 object Standard_System
    20 {
    21   /* shell processes */
    22 
    23   def raw_execute(cwd: JFile, env: Map[String, String], redirect: Boolean, args: String*): Process =
    24   {
    25     val cmdline = new java.util.LinkedList[String]
    26     for (s <- args) cmdline.add(s)
    27 
    28     val proc = new ProcessBuilder(cmdline)
    29     if (cwd != null) proc.directory(cwd)
    30     if (env != null) {
    31       proc.environment.clear
    32       for ((x, y) <- env) proc.environment.put(x, y)
    33     }
    34     proc.redirectErrorStream(redirect)
    35     proc.start
    36   }
    37 
    38   def process_output(proc: Process): (String, Int) =
    39   {
    40     proc.getOutputStream.close
    41     val output = File.read(proc.getInputStream)
    42     val rc =
    43       try { proc.waitFor }
    44       finally {
    45         proc.getInputStream.close
    46         proc.getErrorStream.close
    47         proc.destroy
    48         Thread.interrupted
    49       }
    50     (output, rc)
    51   }
    52 
    53   def raw_exec(cwd: JFile, env: Map[String, String], redirect: Boolean, args: String*)
    54     : (String, Int) = process_output(raw_execute(cwd, env, redirect, args: _*))
    55 
    56 
    57   /* cygwin_root */
    58 
    59   def cygwin_root(): String =
    60   {
    61     val cygwin_root1 = System.getenv("CYGWIN_ROOT")
    62     val cygwin_root2 = System.getProperty("cygwin.root")
    63     val root =
    64       if (cygwin_root1 != null && cygwin_root1 != "") cygwin_root1
    65       else if (cygwin_root2 != null && cygwin_root2 != "") cygwin_root2
    66       else error("Bad Cygwin installation: unknown root")
    67 
    68     val root_file = new JFile(root)
    69     if (!new JFile(root_file, "bin\\bash.exe").isFile ||
    70         !new JFile(root_file, "bin\\env.exe").isFile ||
    71         !new JFile(root_file, "bin\\tar.exe").isFile)
    72       error("Bad Cygwin installation: " + quote(root))
    73 
    74     root
    75   }
    76 }
    77 
    78 
    79 class Standard_System
    80 {
    81   /* platform_root */
    82 
    83   val platform_root = if (Platform.is_windows) Standard_System.cygwin_root() else "/"
    84 
    85 
    86   /* jvm_path */
    87 
    88   private val Cygdrive = new Regex("/cygdrive/([a-zA-Z])($|/.*)")
    89   private val Named_Root = new Regex("//+([^/]*)(.*)")
    90 
    91   def jvm_path(posix_path: String): String =
    92     if (Platform.is_windows) {
    93       val result_path = new StringBuilder
    94       val rest =
    95         posix_path match {
    96           case Cygdrive(drive, rest) =>
    97             result_path ++= (drive.toUpperCase(Locale.ENGLISH) + ":" + JFile.separator)
    98             rest
    99           case Named_Root(root, rest) =>
   100             result_path ++= JFile.separator
   101             result_path ++= JFile.separator
   102             result_path ++= root
   103             rest
   104           case path if path.startsWith("/") =>
   105             result_path ++= platform_root
   106             path
   107           case path => path
   108         }
   109       for (p <- space_explode('/', rest) if p != "") {
   110         val len = result_path.length
   111         if (len > 0 && result_path(len - 1) != JFile.separatorChar)
   112           result_path += JFile.separatorChar
   113         result_path ++= p
   114       }
   115       result_path.toString
   116     }
   117     else posix_path
   118 
   119 
   120   /* posix_path */
   121 
   122   private val Platform_Root = new Regex("(?i)" +
   123     Pattern.quote(platform_root) + """(?:\\+|\z)(.*)""")
   124 
   125   private val Drive = new Regex("""([a-zA-Z]):\\*(.*)""")
   126 
   127   def posix_path(jvm_path: String): String =
   128     if (Platform.is_windows) {
   129       jvm_path.replace('/', '\\') match {
   130         case Platform_Root(rest) => "/" + rest.replace('\\', '/')
   131         case Drive(letter, rest) =>
   132           "/cygdrive/" + letter.toLowerCase(Locale.ENGLISH) +
   133             (if (rest == "") "" else "/" + rest.replace('\\', '/'))
   134         case path => path.replace('\\', '/')
   135       }
   136     }
   137     else jvm_path
   138 
   139 
   140   /* JDK home of running JVM */
   141 
   142   def this_jdk_home(): String =
   143   {
   144     val java_home = System.getProperty("java.home")
   145     val home = new JFile(java_home)
   146     val parent = home.getParent
   147     val jdk_home =
   148       if (home.getName == "jre" && parent != null &&
   149           (new JFile(new JFile(parent, "bin"), "javac")).exists) parent
   150       else java_home
   151     posix_path(jdk_home)
   152   }
   153 }