Skip to content

Commit 0b526de

Browse files
committed
Fix running JARs from scala script
1 parent 3842ae1 commit 0b526de

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

compiler/src/dotty/tools/MainGenericRunner.scala

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import scala.annotation.internal.sharable
1212
import dotty.tools.dotc.util.ClasspathFromClassloader
1313
import dotty.tools.runner.ObjectRunner
1414
import dotty.tools.dotc.config.Properties.envOrNone
15+
import java.util.jar._
16+
import java.util.jar.Attributes.Name
1517

1618
enum ExecuteMode:
1719
case Guess
@@ -129,7 +131,25 @@ object MainGenericRunner {
129131
case ExecuteMode.Run =>
130132
val scalaClasspath = ClasspathFromClassloader(Thread.currentThread().getContextClassLoader).split(classpathSeparator)
131133
val newClasspath = (settings.classPath ++ scalaClasspath :+ ".").map(File(_).toURI.toURL)
132-
errorFn("", ObjectRunner.runAndCatch(newClasspath, settings.residualArgs.head, settings.residualArgs.drop(1)))
134+
val res = ObjectRunner.runAndCatch(newClasspath, settings.residualArgs.head, settings.residualArgs.drop(1)).flatMap {
135+
case ex: ClassNotFoundException if ex.getMessage == settings.residualArgs.head =>
136+
val file = settings.residualArgs.head
137+
def withJarInput[T](f: JarInputStream => T): T =
138+
val in = new JarInputStream(java.io.FileInputStream(file))
139+
try f(in)
140+
finally in.close()
141+
val manifest = withJarInput(s => Option(s.getManifest))
142+
manifest match
143+
case None => Some(IllegalArgumentException(s"Cannot find manifest in jar: $file"))
144+
case Some(f) =>
145+
f.getMainAttributes.get(Name.MAIN_CLASS) match
146+
case mainClass: String =>
147+
ObjectRunner.runAndCatch(newClasspath :+ File(file).toURI.toURL, mainClass, settings.residualArgs)
148+
case _ =>
149+
Some(IllegalArgumentException(s"No main class defined in manifest in jar: $file"))
150+
case ex => Some(ex)
151+
}
152+
errorFn("", res)
133153
case ExecuteMode.Script =>
134154
val properArgs =
135155
List("-classpath", settings.classPath.mkString(classpathSeparator)).filter(Function.const(settings.classPath.nonEmpty))

compiler/test-coursier/dotty/tools/coursier/CoursierScalaTests.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ class CoursierScalaTests:
9292
assertTrue(source.getParentFile.listFiles.find(_.getName == "myfile.jar").isDefined)
9393
jar()
9494

95+
def runThatJar() =
96+
val source = new File(getClass.getResource("/run/myfile.jar").getPath)
97+
val output = CoursierScalaTests.csCmd(source.absPath)
98+
assertEquals(output.mkString("\n"), "Hello")
99+
runThatJar()
100+
95101
object CoursierScalaTests:
96102

97103
def execCmd(command: String, options: String*): List[String] =

0 commit comments

Comments
 (0)