Merge pull request #5540 from bjaglin/service-loader

enable ServiceLoader discovery across classloader layers
This commit is contained in:
eugene yokota 2020-05-12 22:05:53 -04:00 committed by GitHub
commit ea608ccd77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 72 additions and 0 deletions

View File

@ -8,7 +8,9 @@
package sbt.internal;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import sbt.util.Logger;
@ -64,6 +66,31 @@ final class ReverseLookupClassLoader extends ManagedClassLoader {
return url != null ? url : directDescendant.get().findResource(name);
}
@Override
public Enumeration<URL> findResources(String name) throws IOException {
final Enumeration<URL> parentResources = super.findResources(name);
if (directDescendant.get() == null) {
return parentResources;
}
final Enumeration<URL> directDescendantResources = directDescendant.get().findResources(name);
return new Enumeration<URL>() {
@Override
public boolean hasMoreElements() {
return parentResources.hasMoreElements() || directDescendantResources.hasMoreElements();
}
@Override
public URL nextElement() {
if (parentResources.hasMoreElements()) {
return parentResources.nextElement();
}
return directDescendantResources.nextElement();
}
};
}
void setup(final File tmpDir) {
setTempDir(tmpDir);
}

View File

@ -0,0 +1,4 @@
val dependency = project.settings(exportJars := true)
val descendant = project.dependsOn(dependency).settings(
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test"
)

View File

@ -0,0 +1,6 @@
package dependency;
public class Runnable implements java.lang.Runnable {
public void run() {}
}

View File

@ -0,0 +1,6 @@
package descendant
class Runnable extends java.lang.Runnable {
override def run(): Unit = ()
}

View File

@ -0,0 +1,20 @@
package test
import collection.JavaConverters._
import org.scalatest._
class ServiceLoaderTest extends FlatSpec {
val expected = Set(classOf[dependency.Runnable], classOf[descendant.Runnable])
val descendantClassLoader = classOf[descendant.Runnable].getClassLoader
val descendantRunnableLoader = java.util.ServiceLoader.load(classOf[java.lang.Runnable], descendantClassLoader)
val descendantLoadedClasses = descendantRunnableLoader.iterator().asScala.map(_.getClass).toSet
assert(descendantLoadedClasses == expected)
// this was the actual problem, when classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.AllLibraryJars
val dependencyClassLoader = classOf[dependency.Runnable].getClassLoader
val dependencyRunnableLoader = java.util.ServiceLoader.load(classOf[java.lang.Runnable], dependencyClassLoader)
val dependencyLoadedClasses = dependencyRunnableLoader.iterator().asScala.map(_.getClass).toSet
assert(dependencyLoadedClasses == expected)
}

View File

@ -0,0 +1,7 @@
> set descendant / Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.AllLibraryJars
> test
> set descendant / Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.ScalaLibrary
> test