mirror of https://github.com/sbt/sbt.git
Port XMainConfiguration to Java
The bytecode generated by 2.13 compiler contains scala.runtime.BoxedUnit in the constant pool. To avoid referencing scala-library, port XMainConfiguration to Java.
This commit is contained in:
parent
d687cf11ff
commit
6d2a516df5
|
|
@ -1029,7 +1029,11 @@ lazy val mainProj = (project in file("main"))
|
||||||
// internal logging apis,
|
// internal logging apis,
|
||||||
exclude[IncompatibleSignatureProblem]("sbt.internal.LogManager*"),
|
exclude[IncompatibleSignatureProblem]("sbt.internal.LogManager*"),
|
||||||
exclude[MissingTypesProblem]("sbt.internal.RelayAppender"),
|
exclude[MissingTypesProblem]("sbt.internal.RelayAppender"),
|
||||||
exclude[MissingClassProblem]("sbt.internal.TaskProgress$ProgressThread")
|
exclude[MissingClassProblem]("sbt.internal.TaskProgress$ProgressThread"),
|
||||||
|
// internal implementation
|
||||||
|
exclude[MissingClassProblem](
|
||||||
|
"sbt.internal.XMainConfiguration$ModifiedConfiguration$ModifiedAppProvider$ModifiedScalaProvider$"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.configure(
|
.configure(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,299 @@
|
||||||
|
/*
|
||||||
|
* sbt
|
||||||
|
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||||
|
* Copyright 2008 - 2010, Mark Harrah
|
||||||
|
* Licensed under Apache License 2.0 (see LICENSE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sbt.internal;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import xsbti.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a new app configuration and invokes xMainImpl.run. For AppConfigurations generated by
|
||||||
|
* recent launchers, it is unnecessary to modify the original configuration, but configurations
|
||||||
|
* generated by older launchers need to be modified to place the test interface jar higher in the
|
||||||
|
* class hierarchy. The methods this object are implemented without using the scala library so that
|
||||||
|
* we can avoid loading any classes from the old scala provider.
|
||||||
|
*/
|
||||||
|
public class XMainConfiguration {
|
||||||
|
public xsbti.MainResult run(String moduleName, xsbti.AppConfiguration configuration) {
|
||||||
|
try {
|
||||||
|
ClassLoader topLoader = configuration.provider().scalaProvider().launcher().topLoader();
|
||||||
|
xsbti.AppConfiguration updatedConfiguration = null;
|
||||||
|
try {
|
||||||
|
Method method = topLoader.getClass().getMethod("getJLineJars");
|
||||||
|
URL[] jars = (URL[]) method.invoke(topLoader);
|
||||||
|
boolean canReuseConfiguration = jars.length == 3;
|
||||||
|
int j = 0;
|
||||||
|
while (j < jars.length && canReuseConfiguration) {
|
||||||
|
String s = jars[j].toString();
|
||||||
|
canReuseConfiguration = s.contains("jline") || s.contains("jansi");
|
||||||
|
j += 1;
|
||||||
|
}
|
||||||
|
if (canReuseConfiguration && j == 3) {
|
||||||
|
updatedConfiguration = configuration;
|
||||||
|
} else {
|
||||||
|
updatedConfiguration = makeConfiguration(configuration);
|
||||||
|
}
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
updatedConfiguration = makeConfiguration(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassLoader loader = updatedConfiguration.provider().loader();
|
||||||
|
Thread.currentThread().setContextClassLoader(loader);
|
||||||
|
Class<?> clazz = loader.loadClass("sbt." + moduleName + "$");
|
||||||
|
Object instance = clazz.getField("MODULE$").get(null);
|
||||||
|
Method runMethod = clazz.getMethod("run", xsbti.AppConfiguration.class);
|
||||||
|
try {
|
||||||
|
Class<?> clw = loader.loadClass("sbt.internal.ClassLoaderWarmup$");
|
||||||
|
clw.getMethod("warmup").invoke(clw.getField("MODULE$").get(null));
|
||||||
|
return (xsbti.MainResult) runMethod.invoke(instance, updatedConfiguration);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
// This propogates xsbti.FullReload to the launcher
|
||||||
|
throw (xsbti.FullReload) e.getCause();
|
||||||
|
}
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private xsbti.AppConfiguration makeConfiguration(xsbti.AppConfiguration configuration) {
|
||||||
|
try {
|
||||||
|
ClassLoader baseLoader = XMainConfiguration.class.getClassLoader();
|
||||||
|
String className = "sbt/internal/XMainConfiguration.class";
|
||||||
|
URL url = baseLoader.getResource(className);
|
||||||
|
String path = url.toString().replaceAll(className.concat("$"), "");
|
||||||
|
URL[] urlArray = new URL[1];
|
||||||
|
urlArray[0] = new URL(path);
|
||||||
|
ClassLoader topLoader = configuration.provider().scalaProvider().launcher().topLoader();
|
||||||
|
// This loader doesn't have the scala library in it so it's critical that none of the code
|
||||||
|
// in this file use the scala library.
|
||||||
|
ClassLoader modifiedLoader = new XMainClassLoader(urlArray, topLoader);
|
||||||
|
Class<?> xMainConfigurationClass =
|
||||||
|
modifiedLoader.loadClass("sbt.internal.XMainConfiguration");
|
||||||
|
Object instance = (Object) xMainConfigurationClass.getConstructor().newInstance();
|
||||||
|
Class<?> metaBuildLoaderClass = modifiedLoader.loadClass("sbt.internal.MetaBuildLoader");
|
||||||
|
Method method = metaBuildLoaderClass.getMethod("makeLoader", AppProvider.class);
|
||||||
|
|
||||||
|
ClassLoader loader = (ClassLoader) method.invoke(null, configuration.provider());
|
||||||
|
|
||||||
|
Thread.currentThread().setContextClassLoader(loader);
|
||||||
|
Class<?> modifiedConfigurationClass =
|
||||||
|
modifiedLoader.loadClass("sbt.internal.XMainConfiguration$ModifiedConfiguration");
|
||||||
|
Constructor<?> cons = modifiedConfigurationClass.getConstructors()[0];
|
||||||
|
ClassLoaderClose.close(configuration.provider().loader());
|
||||||
|
ScalaProvider scalaProvider = configuration.provider().scalaProvider();
|
||||||
|
Class<? extends ScalaProvider> providerClass = scalaProvider.getClass();
|
||||||
|
try {
|
||||||
|
Method method2 = providerClass.getMethod("loaderLibraryOnly");
|
||||||
|
ClassLoaderClose.close((ClassLoader) method2.invoke(scalaProvider));
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
}
|
||||||
|
ClassLoaderClose.close(scalaProvider.loader());
|
||||||
|
ClassLoaderClose.close(configuration.provider().loader());
|
||||||
|
return (xsbti.AppConfiguration) cons.newInstance(instance, configuration, loader);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replaces the AppProvider.loader method with a new loader that puts the sbt test interface
|
||||||
|
* jar ahead of the rest of the sbt classpath in the classloading hierarchy.
|
||||||
|
*/
|
||||||
|
public class ModifiedConfiguration implements xsbti.AppConfiguration {
|
||||||
|
private xsbti.AppConfiguration configuration;
|
||||||
|
private ClassLoader metaLoader;
|
||||||
|
|
||||||
|
public ModifiedConfiguration(xsbti.AppConfiguration configuration, ClassLoader metaLoader) {
|
||||||
|
this.configuration = configuration;
|
||||||
|
this.metaLoader = metaLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ModifiedAppProvider implements AppProvider {
|
||||||
|
private AppProvider appProvider;
|
||||||
|
private ScalaProvider instance;
|
||||||
|
|
||||||
|
public ModifiedAppProvider(AppProvider appProvider) throws ClassNotFoundException {
|
||||||
|
this.appProvider = appProvider;
|
||||||
|
ScalaProvider delegate = configuration.provider().scalaProvider();
|
||||||
|
this.instance =
|
||||||
|
new ScalaProvider() {
|
||||||
|
public Launcher _launcher =
|
||||||
|
new Launcher() {
|
||||||
|
private Launcher delegateLauncher = delegate.launcher();
|
||||||
|
private ClassLoader interfaceLoader =
|
||||||
|
metaLoader.loadClass("sbt.testing.Framework").getClassLoader();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScalaProvider getScala(String version) {
|
||||||
|
return getScala(version, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScalaProvider getScala(String version, String reason) {
|
||||||
|
return getScala(version, reason, "org.scala-lang");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScalaProvider getScala(String version, String reason, String scalaOrg) {
|
||||||
|
return delegateLauncher.getScala(version, reason, scalaOrg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppProvider app(xsbti.ApplicationID id, String version) {
|
||||||
|
return delegateLauncher.app(id, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassLoader topLoader() {
|
||||||
|
return interfaceLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GlobalLock globalLock() {
|
||||||
|
return delegateLauncher.globalLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File bootDirectory() {
|
||||||
|
return delegateLauncher.bootDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public xsbti.Repository[] ivyRepositories() {
|
||||||
|
return delegateLauncher.ivyRepositories();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public xsbti.Repository[] appRepositories() {
|
||||||
|
return delegateLauncher.appRepositories();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOverrideRepositories() {
|
||||||
|
return delegateLauncher.isOverrideRepositories();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File ivyHome() {
|
||||||
|
return delegateLauncher.ivyHome();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] checksums() {
|
||||||
|
return delegateLauncher.checksums();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Launcher launcher() {
|
||||||
|
return this._launcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String version() {
|
||||||
|
return delegate.version();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassLoader loader() {
|
||||||
|
return metaLoader.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File[] jars() {
|
||||||
|
return delegate.jars();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Deprecated()
|
||||||
|
public File libraryJar() {
|
||||||
|
return delegate.libraryJar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Deprecated()
|
||||||
|
public File compilerJar() {
|
||||||
|
return delegate.compilerJar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppProvider app(xsbti.ApplicationID id) {
|
||||||
|
return delegate.app(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClassLoader loaderLibraryOnly() {
|
||||||
|
return metaLoader.getParent().getParent();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScalaProvider scalaProvider() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public xsbti.ApplicationID id() {
|
||||||
|
return appProvider.id();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassLoader loader() {
|
||||||
|
return metaLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Deprecated()
|
||||||
|
public Class<? extends AppMain> mainClass() {
|
||||||
|
return appProvider.mainClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> entryPoint() {
|
||||||
|
return appProvider.entryPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppMain newMain() {
|
||||||
|
return appProvider.newMain();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File[] mainClasspath() {
|
||||||
|
return appProvider.mainClasspath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ComponentProvider components() {
|
||||||
|
return appProvider.components();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] arguments() {
|
||||||
|
return configuration.arguments();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File baseDirectory() {
|
||||||
|
return configuration.baseDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppProvider provider() {
|
||||||
|
try {
|
||||||
|
return new ModifiedAppProvider(configuration.provider());
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* sbt
|
||||||
|
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||||
|
* Copyright 2008 - 2010, Mark Harrah
|
||||||
|
* Licensed under Apache License 2.0 (see LICENSE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sbt.internal
|
||||||
|
|
||||||
|
import java.util.concurrent.{ ExecutorService, Executors }
|
||||||
|
import sbt.plugins.{ CorePlugin, IvyPlugin, JvmPlugin }
|
||||||
|
|
||||||
|
private[internal] object ClassLoaderWarmup {
|
||||||
|
def warmup(): Unit = {
|
||||||
|
if (Runtime.getRuntime.availableProcessors > 1) {
|
||||||
|
val executorService: ExecutorService =
|
||||||
|
Executors.newFixedThreadPool(Runtime.getRuntime.availableProcessors - 1)
|
||||||
|
def submit[R](f: => R): Unit = {
|
||||||
|
executorService.submit(new Runnable {
|
||||||
|
override def run(): Unit = { f; () }
|
||||||
|
})
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
|
submit(Class.forName("sbt.internal.parser.SbtParserInit").getConstructor().newInstance())
|
||||||
|
submit(CorePlugin.projectSettings)
|
||||||
|
submit(IvyPlugin.projectSettings)
|
||||||
|
submit(JvmPlugin.projectSettings)
|
||||||
|
submit(() => {
|
||||||
|
try {
|
||||||
|
val clazz = Class.forName("scala.reflect.runtime.package$")
|
||||||
|
clazz.getMethod("universe").invoke(clazz.getField("MODULE$").get(null))
|
||||||
|
} catch {
|
||||||
|
case _: Exception =>
|
||||||
|
}
|
||||||
|
executorService.shutdown()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
/*
|
|
||||||
* sbt
|
|
||||||
* Copyright 2011 - 2018, Lightbend, Inc.
|
|
||||||
* Copyright 2008 - 2010, Mark Harrah
|
|
||||||
* Licensed under Apache License 2.0 (see LICENSE)
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sbt.internal
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
import java.lang.reflect.InvocationTargetException
|
|
||||||
import java.net.URL
|
|
||||||
import java.util.concurrent.{ ExecutorService, Executors }
|
|
||||||
import ClassLoaderClose.close
|
|
||||||
|
|
||||||
import sbt.plugins.{ CorePlugin, IvyPlugin, JvmPlugin }
|
|
||||||
import xsbti._
|
|
||||||
|
|
||||||
private[internal] object ClassLoaderWarmup {
|
|
||||||
def warmup(): Unit = {
|
|
||||||
if (Runtime.getRuntime.availableProcessors > 1) {
|
|
||||||
val executorService: ExecutorService =
|
|
||||||
Executors.newFixedThreadPool(Runtime.getRuntime.availableProcessors - 1)
|
|
||||||
def submit[R](f: => R): Unit = {
|
|
||||||
executorService.submit(new Runnable {
|
|
||||||
override def run(): Unit = { f; () }
|
|
||||||
})
|
|
||||||
()
|
|
||||||
}
|
|
||||||
|
|
||||||
submit(Class.forName("sbt.internal.parser.SbtParserInit").getConstructor().newInstance())
|
|
||||||
submit(CorePlugin.projectSettings)
|
|
||||||
submit(IvyPlugin.projectSettings)
|
|
||||||
submit(JvmPlugin.projectSettings)
|
|
||||||
submit(() => {
|
|
||||||
try {
|
|
||||||
val clazz = Class.forName("scala.reflect.runtime.package$")
|
|
||||||
clazz.getMethod("universe").invoke(clazz.getField("MODULE$").get(null))
|
|
||||||
} catch {
|
|
||||||
case _: Exception =>
|
|
||||||
}
|
|
||||||
executorService.shutdown()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a new app configuration and invokes xMainImpl.run. For AppConfigurations generated
|
|
||||||
* by recent launchers, it is unnecessary to modify the original configuration, but configurations
|
|
||||||
* generated by older launchers need to be modified to place the test interface jar higher in
|
|
||||||
* the class hierarchy. The methods this object are implemented without using the scala library
|
|
||||||
* so that we can avoid loading any classes from the old scala provider. Verified as of
|
|
||||||
* sbt 1.3.0 that there are no references to the scala standard library in any of the methods
|
|
||||||
* in this file.
|
|
||||||
*/
|
|
||||||
private[sbt] class XMainConfiguration {
|
|
||||||
def run(moduleName: String, configuration: xsbti.AppConfiguration): xsbti.MainResult = {
|
|
||||||
val topLoader = configuration.provider.scalaProvider.launcher.topLoader
|
|
||||||
val updatedConfiguration =
|
|
||||||
try {
|
|
||||||
val method = topLoader.getClass.getMethod("getJLineJars")
|
|
||||||
val jars = method.invoke(topLoader).asInstanceOf[Array[URL]]
|
|
||||||
var canReuseConfiguration = jars.length == 3
|
|
||||||
var j = 0
|
|
||||||
while (j < jars.length && canReuseConfiguration) {
|
|
||||||
val s = jars(j).toString
|
|
||||||
canReuseConfiguration = s.contains("jline") || s.contains("jansi")
|
|
||||||
j += 1
|
|
||||||
}
|
|
||||||
if (canReuseConfiguration && j == 3) configuration else makeConfiguration(configuration)
|
|
||||||
} catch {
|
|
||||||
case _: NoSuchMethodException => makeConfiguration(configuration)
|
|
||||||
}
|
|
||||||
val loader = updatedConfiguration.provider.loader
|
|
||||||
Thread.currentThread.setContextClassLoader(loader)
|
|
||||||
val clazz = loader.loadClass(s"sbt.$moduleName$$")
|
|
||||||
val instance = clazz.getField("MODULE$").get(null)
|
|
||||||
val runMethod = clazz.getMethod("run", classOf[xsbti.AppConfiguration])
|
|
||||||
try {
|
|
||||||
val clw = loader.loadClass("sbt.internal.ClassLoaderWarmup$")
|
|
||||||
clw.getMethod("warmup").invoke(clw.getField("MODULE$").get(null))
|
|
||||||
runMethod.invoke(instance, updatedConfiguration).asInstanceOf[xsbti.MainResult]
|
|
||||||
} catch {
|
|
||||||
case e: InvocationTargetException =>
|
|
||||||
// This propogates xsbti.FullReload to the launcher
|
|
||||||
throw e.getCause
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def makeConfiguration(configuration: xsbti.AppConfiguration): xsbti.AppConfiguration = {
|
|
||||||
val baseLoader = classOf[XMainConfiguration].getClassLoader
|
|
||||||
val className = "sbt/internal/XMainConfiguration.class"
|
|
||||||
val url = baseLoader.getResource(className)
|
|
||||||
val path = url.toString.replaceAll(s"$className$$", "")
|
|
||||||
val urlArray = new Array[URL](1)
|
|
||||||
urlArray(0) = new URL(path)
|
|
||||||
val topLoader = configuration.provider.scalaProvider.launcher.topLoader
|
|
||||||
// This loader doesn't have the scala library in it so it's critical that none of the code
|
|
||||||
// in this file use the scala library.
|
|
||||||
val modifiedLoader = new XMainClassLoader(urlArray, topLoader)
|
|
||||||
val xMainConfigurationClass = modifiedLoader.loadClass("sbt.internal.XMainConfiguration")
|
|
||||||
val instance: AnyRef =
|
|
||||||
xMainConfigurationClass.getConstructor().newInstance().asInstanceOf[AnyRef]
|
|
||||||
|
|
||||||
val metaBuildLoaderClass = modifiedLoader.loadClass("sbt.internal.MetaBuildLoader")
|
|
||||||
val method = metaBuildLoaderClass.getMethod("makeLoader", classOf[AppProvider])
|
|
||||||
|
|
||||||
val loader = method.invoke(null, configuration.provider).asInstanceOf[ClassLoader]
|
|
||||||
|
|
||||||
Thread.currentThread.setContextClassLoader(loader)
|
|
||||||
val modifiedConfigurationClass =
|
|
||||||
modifiedLoader.loadClass("sbt.internal.XMainConfiguration$ModifiedConfiguration")
|
|
||||||
val cons = modifiedConfigurationClass.getConstructors()(0)
|
|
||||||
close(configuration.provider.loader)
|
|
||||||
val scalaProvider = configuration.provider.scalaProvider
|
|
||||||
val providerClass = scalaProvider.getClass
|
|
||||||
val _ = try {
|
|
||||||
val method = providerClass.getMethod("loaderLibraryOnly")
|
|
||||||
close(method.invoke(scalaProvider).asInstanceOf[ClassLoader])
|
|
||||||
1
|
|
||||||
} catch { case _: NoSuchMethodException => 1 }
|
|
||||||
close(scalaProvider.loader)
|
|
||||||
close(configuration.provider.loader)
|
|
||||||
cons.newInstance(instance, configuration, loader).asInstanceOf[xsbti.AppConfiguration]
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Replaces the AppProvider.loader method with a new loader that puts the sbt test interface
|
|
||||||
* jar ahead of the rest of the sbt classpath in the classloading hierarchy.
|
|
||||||
*/
|
|
||||||
private[sbt] class ModifiedConfiguration(
|
|
||||||
val configuration: xsbti.AppConfiguration,
|
|
||||||
val metaLoader: ClassLoader
|
|
||||||
) extends xsbti.AppConfiguration {
|
|
||||||
|
|
||||||
private class ModifiedAppProvider(val appProvider: AppProvider) extends AppProvider {
|
|
||||||
private val delegate = configuration.provider.scalaProvider
|
|
||||||
object ModifiedScalaProvider extends ScalaProvider {
|
|
||||||
override def launcher(): Launcher = new Launcher {
|
|
||||||
private val delegateLauncher = delegate.launcher
|
|
||||||
private val interfaceLoader = metaLoader.loadClass("sbt.testing.Framework").getClassLoader
|
|
||||||
override def getScala(version: String): ScalaProvider = getScala(version, "")
|
|
||||||
override def getScala(version: String, reason: String): ScalaProvider =
|
|
||||||
getScala(version, reason, "org.scala-lang")
|
|
||||||
override def getScala(version: String, reason: String, scalaOrg: String): ScalaProvider =
|
|
||||||
delegateLauncher.getScala(version, reason, scalaOrg)
|
|
||||||
override def app(id: xsbti.ApplicationID, version: String): AppProvider =
|
|
||||||
delegateLauncher.app(id, version)
|
|
||||||
override def topLoader(): ClassLoader = interfaceLoader
|
|
||||||
override def globalLock(): GlobalLock = delegateLauncher.globalLock()
|
|
||||||
override def bootDirectory(): File = delegateLauncher.bootDirectory()
|
|
||||||
override def ivyRepositories(): Array[xsbti.Repository] =
|
|
||||||
delegateLauncher.ivyRepositories()
|
|
||||||
override def appRepositories(): Array[xsbti.Repository] =
|
|
||||||
delegateLauncher.appRepositories()
|
|
||||||
override def isOverrideRepositories: Boolean = delegateLauncher.isOverrideRepositories
|
|
||||||
override def ivyHome(): File = delegateLauncher.ivyHome()
|
|
||||||
override def checksums(): Array[String] = delegateLauncher.checksums()
|
|
||||||
}
|
|
||||||
override def version(): String = delegate.version
|
|
||||||
override def loader(): ClassLoader = metaLoader.getParent
|
|
||||||
override def jars(): Array[File] = delegate.jars
|
|
||||||
@deprecated("Implements deprecated api", "1.3.0")
|
|
||||||
override def libraryJar(): File = delegate.libraryJar
|
|
||||||
@deprecated("Implements deprecated api", "1.3.0")
|
|
||||||
override def compilerJar(): File = delegate.compilerJar
|
|
||||||
override def app(id: xsbti.ApplicationID): AppProvider = delegate.app(id)
|
|
||||||
def loaderLibraryOnly(): ClassLoader = metaLoader.getParent.getParent
|
|
||||||
}
|
|
||||||
override def scalaProvider(): ModifiedScalaProvider.type = ModifiedScalaProvider
|
|
||||||
override def id(): xsbti.ApplicationID = appProvider.id()
|
|
||||||
override def loader(): ClassLoader = metaLoader
|
|
||||||
@deprecated("Implements deprecated api", "1.3.0")
|
|
||||||
override def mainClass(): Class[_ <: AppMain] = appProvider.mainClass()
|
|
||||||
override def entryPoint(): Class[_] = appProvider.entryPoint()
|
|
||||||
override def newMain(): AppMain = appProvider.newMain()
|
|
||||||
override def mainClasspath(): Array[File] = appProvider.mainClasspath()
|
|
||||||
override def components(): ComponentProvider = appProvider.components()
|
|
||||||
}
|
|
||||||
override def arguments(): Array[String] = configuration.arguments
|
|
||||||
override def baseDirectory(): File = configuration.baseDirectory
|
|
||||||
override def provider(): AppProvider = new ModifiedAppProvider(configuration.provider)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue