src/Pure/System/classpath.scala
author wenzelm
Fri, 12 Aug 2022 16:08:12 +0200
changeset 75825 ad00fbf64bff
parent 75704 1fac896c2b69
child 75906 2167b9e3157a
permissions -rw-r--r--
clarified signature --- simplified types;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
75702
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/System/classpath.scala
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
     3
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
     4
Java classpath and Scala services.
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
     5
*/
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
     6
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
     7
package isabelle
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
     8
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
     9
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    10
import java.io.{File => JFile}
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    11
import java.nio.file.Files
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    12
import java.net.URLClassLoader
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    13
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    14
import scala.jdk.CollectionConverters._
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    15
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    16
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    17
object Classpath {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    18
  abstract class Service
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    19
  type Service_Class = Class[Service]
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    20
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    21
  def apply(
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    22
    jar_files: List[JFile] = Nil,
75825
ad00fbf64bff clarified signature --- simplified types;
wenzelm
parents: 75704
diff changeset
    23
    jar_contents: List[File.Content] = Nil): Classpath =
75702
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    24
  {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    25
    val jar_files0 =
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    26
      for {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    27
        s <- space_explode(JFile.pathSeparatorChar, System.getProperty("java.class.path", ""))
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    28
        if s.nonEmpty
75703
8faeea36eb99 mor robust;
wenzelm
parents: 75702
diff changeset
    29
      } yield File.absolute(new JFile(s))
75702
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    30
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    31
    val jar_files1 =
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    32
      jar_files.flatMap(start => File.find_files(start, _.getName.endsWith(".jar")))
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    33
        .map(File.absolute)
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    34
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    35
    val tmp_jars =
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    36
      for (jar <- jar_contents) yield {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    37
        val tmp_jar = Files.createTempFile("jar", "jar").toFile
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    38
        tmp_jar.deleteOnExit()
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    39
        Bytes.write(tmp_jar, jar.content)
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    40
        tmp_jar
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    41
      }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    42
    new Classpath(jar_files0 ::: jar_files1, tmp_jars)
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    43
  }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    44
}
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    45
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    46
class Classpath private(static_jars: List[JFile], dynamic_jars: List[JFile]) {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    47
  def jars: List[JFile] = static_jars ::: dynamic_jars
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    48
  override def toString: String = jars.mkString("Classpath(", ", ", ")")
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    49
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    50
  def platform_path: String = jars.map(_.getPath).mkString(JFile.pathSeparator)
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    51
75704
wenzelm
parents: 75703
diff changeset
    52
  val class_loader: ClassLoader =
75702
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    53
  {
75704
wenzelm
parents: 75703
diff changeset
    54
    val this_class_loader = this.getClass.getClassLoader
wenzelm
parents: 75703
diff changeset
    55
    if (dynamic_jars.isEmpty) this_class_loader
75702
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    56
    else {
75704
wenzelm
parents: 75703
diff changeset
    57
      new URLClassLoader(dynamic_jars.map(File.url).toArray, this_class_loader) {
75702
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    58
        override def finalize(): Unit = {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    59
          for (jar <- dynamic_jars) {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    60
            try { jar.delete() }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    61
            catch { case _: Throwable => }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    62
          }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    63
        }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    64
      }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    65
    }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    66
  }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    67
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    68
  private def init_services(where: String, names: List[String]): List[Classpath.Service_Class] = {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    69
    for (name <- names) yield {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    70
      def err(msg: String): Nothing =
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    71
        error("Bad Isabelle/Scala service " + quote(name) + " in " + where + "\n" + msg)
75704
wenzelm
parents: 75703
diff changeset
    72
      try { Class.forName(name, true, class_loader).asInstanceOf[Classpath.Service_Class] }
75702
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    73
      catch {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    74
        case _: ClassNotFoundException => err("Class not found")
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    75
        case exn: Throwable => err(Exn.message(exn))
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    76
      }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    77
    }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    78
  }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    79
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    80
  val services: List[Classpath.Service_Class] =
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    81
  {
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    82
    val variable = "ISABELLE_SCALA_SERVICES"
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    83
    val services_env =
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    84
      init_services(quote(variable), space_explode(':', Isabelle_System.getenv_strict(variable)))
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    85
    val services_jars =
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    86
      jars.flatMap(jar =>
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    87
        init_services(File.standard_path(jar),
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    88
          isabelle.setup.Build.get_services(jar.toPath).asScala.toList))
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    89
    services_env ::: services_jars
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    90
  }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    91
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    92
  def make_services[C](c: Class[C]): List[C] =
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    93
    for { c1 <- services if Library.is_subclass(c1, c) }
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    94
      yield c1.getDeclaredConstructor().newInstance().asInstanceOf[C]
97e8f4c938bf clarified modules;
wenzelm
parents:
diff changeset
    95
}