From b8b6426cf914ea7125995f72ca47a21ed4ae8412 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Thu, 26 Sep 2013 09:42:30 -0400 Subject: [PATCH] Allow main class to be non-public. Fixes #883. --- compile/api/src/main/scala/xsbt/api/Discovery.scala | 9 ++++++++- run/src/main/scala/sbt/Run.scala | 3 +++ sbt/src/sbt-test/java/varargs-main/A.java | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/compile/api/src/main/scala/xsbt/api/Discovery.scala b/compile/api/src/main/scala/xsbt/api/Discovery.scala index a137cbfe7..fffeea31c 100644 --- a/compile/api/src/main/scala/xsbt/api/Discovery.scala +++ b/compile/api/src/main/scala/xsbt/api/Discovery.scala @@ -14,7 +14,13 @@ class Discovery(baseClasses: Set[String], annotations: Set[String]) def apply(d: Definition): Discovered = d match { - case c: ClassLike if isPublic(c) && isConcrete(c.modifiers) => discover(c) + case c: ClassLike if isConcrete(c.modifiers) => + if(isPublic(c)) + discover(c) + else if(isModule(c) && hasMainMethod(c)) // jvm does not require a main class to be public + new Discovered(Set.empty, Set.empty, true, true) + else + Discovered.empty case _ => Discovered.empty } def discover(c: ClassLike): Discovered = @@ -24,6 +30,7 @@ class Discovery(baseClasses: Set[String], annotations: Set[String]) val module = isModule(c) new Discovered( bases(c.name, c.structure.parents), onClass ++ onDefs, module && hasMainMethod(c), module ) } + def bases(own: String, c: Seq[Type]): Set[String] = (own +: c.flatMap(simpleName)).filter(baseClasses).toSet diff --git a/run/src/main/scala/sbt/Run.scala b/run/src/main/scala/sbt/Run.scala index 1166c3239..e493d3934 100644 --- a/run/src/main/scala/sbt/Run.scala +++ b/run/src/main/scala/sbt/Run.scala @@ -76,6 +76,9 @@ class Run(instance: ScalaInstance, trapExit: Boolean, nativeTmp: File) extends S { val mainClass = Class.forName(mainClassName, true, loader) val method = mainClass.getMethod("main", classOf[Array[String]]) + // jvm allows the actual main class to be non-public and to run a method in the non-public class, + // we need to make it accessible + method.setAccessible(true) val modifiers = method.getModifiers if(!isPublic(modifiers)) throw new NoSuchMethodException(mainClassName + ".main is not public") if(!isStatic(modifiers)) throw new NoSuchMethodException(mainClassName + ".main is not static") diff --git a/sbt/src/sbt-test/java/varargs-main/A.java b/sbt/src/sbt-test/java/varargs-main/A.java index 3b417329f..56dac6178 100644 --- a/sbt/src/sbt-test/java/varargs-main/A.java +++ b/sbt/src/sbt-test/java/varargs-main/A.java @@ -1,4 +1,5 @@ -public class A{ +// Java allows the main class to have default access, test that here +class A{ public static void main(String... args){ }