|
| 1 | +package dotty.tools.dotc.util |
| 2 | + |
| 3 | +import java.net.URLClassLoader |
| 4 | +import java.nio.file.Paths |
| 5 | + |
| 6 | +import dotty.tools.repl.AbstractFileClassLoader |
| 7 | + |
| 8 | +object ClasspathFromClassloader { |
| 9 | + |
| 10 | + /** Attempt to recreate a classpath from a classloader. |
| 11 | + * |
| 12 | + * BEWARE: with exotic enough classloaders, this may not work at all or do |
| 13 | + * the wrong thing. |
| 14 | + */ |
| 15 | + def apply(cl: ClassLoader): String = { |
| 16 | + val classpathBuff = List.newBuilder[String] |
| 17 | + def collectClassLoaderPaths(cl: ClassLoader): Unit = { |
| 18 | + if (cl != null) { |
| 19 | + cl match { |
| 20 | + case cl: URLClassLoader => |
| 21 | + // This is wrong if we're in a subclass of URLClassLoader |
| 22 | + // that filters loading classes from its parent ¯\_(ツ)_/¯ |
| 23 | + collectClassLoaderPaths(cl.getParent) |
| 24 | + // Parent classloaders are searched before their child, so the part of |
| 25 | + // the classpath coming from the child is added at the _end_ of the |
| 26 | + // classpath. |
| 27 | + classpathBuff ++= |
| 28 | + cl.getURLs.iterator.map(url => Paths.get(url.toURI).toAbsolutePath.toString) |
| 29 | + case _ => |
| 30 | + // HACK: We can't just collect the classpath from arbitrary parent |
| 31 | + // classloaders since the current classloader might intentionally |
| 32 | + // filter loading classes from its parent (for example |
| 33 | + // BootFilteredLoader in the sbt launcher does this and we really |
| 34 | + // don't want to include the scala-library that sbt depends on |
| 35 | + // here), but we do need to look at the parent of the REPL |
| 36 | + // classloader, so we special case it. We can't do this using a type |
| 37 | + // test since the REPL classloader class itself is normally loaded |
| 38 | + // with a different classloader. |
| 39 | + if (cl.getClass.getName == classOf[AbstractFileClassLoader].getName) |
| 40 | + collectClassLoaderPaths(cl.getParent) |
| 41 | + } |
| 42 | + } |
| 43 | + } |
| 44 | + collectClassLoaderPaths(cl) |
| 45 | + classpathBuff.result().mkString(java.io.File.pathSeparator) |
| 46 | + } |
| 47 | +} |
0 commit comments