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

coursier.cli.Launch.scala Maven / Gradle / Ivy

The newest version!
package coursier
package cli

import java.io.File
import java.net.{ URL, URLClassLoader }

import caseapp._

object Launch {

  def run(
    loader: ClassLoader,
    mainClass: String,
    args: Seq[String],
    verbosity: Int,
    beforeMain: => Unit = ()
  ): Unit = {

    val cls =
      try loader.loadClass(mainClass)
      catch { case e: ClassNotFoundException =>
        Helper.errPrintln(s"Error: class $mainClass not found")
        sys.exit(255)
      }
    val method =
      try cls.getMethod("main", classOf[Array[String]])
      catch { case e: NoSuchMethodException =>
        Helper.errPrintln(s"Error: method main not found in $mainClass")
        sys.exit(255)
      }
    method.setAccessible(true)

    if (verbosity >= 2)
      Helper.errPrintln(s"Launching $mainClass ${args.mkString(" ")}")
    else if (verbosity == 1)
      Helper.errPrintln(s"Launching")

    beforeMain

    Thread.currentThread().setContextClassLoader(loader)
    try method.invoke(null, args.toArray)
    catch {
      case e: java.lang.reflect.InvocationTargetException =>
        throw Option(e.getCause).getOrElse(e)
    }
  }

}

class IsolatedClassLoader(
  urls: Array[URL],
  parent: ClassLoader,
  isolationTargets: Array[String]
) extends URLClassLoader(urls, parent) {

  /**
    * Applications wanting to access an isolated `ClassLoader` should inspect the hierarchy of
    * loaders, and look into each of them for this method, by reflection. Then they should
    * call it (still by reflection), and look for an agreed in advance target in it. If it is found,
    * then the corresponding `ClassLoader` is the one with isolated dependencies.
    */
  def getIsolationTargets: Array[String] = isolationTargets

}

// should be in case-app somehow
trait ExtraArgsApp extends caseapp.core.DefaultArgsApp {
  private var remainingArgs1 = Seq.empty[String]
  private var extraArgs1 = Seq.empty[String]

  override def setRemainingArgs(remainingArgs: Seq[String], extraArgs: Seq[String]): Unit = {
    remainingArgs1 = remainingArgs
    extraArgs1 = extraArgs
  }

  override def remainingArgs: Seq[String] =
    remainingArgs1
  def extraArgs: Seq[String] =
    extraArgs1
}

final case class Launch(
  @Recurse
    options: LaunchOptions
) extends App with ExtraArgsApp {

  val userArgs = extraArgs

  val helper = new Helper(
    options.common,
    remainingArgs ++ options.isolated.rawIsolated.map { case (_, dep) => dep },
    extraJars = options.extraJars.map(new File(_)),
    isolated = options.isolated
  )

  val mainClass =
    if (options.mainClass.isEmpty)
      helper.retainedMainClass
    else
      options.mainClass

  Launch.run(
    helper.loader,
    mainClass,
    userArgs,
    options.common.verbosityLevel
  )
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy