From 7ea35daec2cd427f1873376389e00047204ec0db Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Fri, 5 Aug 2011 21:56:32 -0400 Subject: [PATCH] class loader extension to handle native libraries loaded in multiple class loaders --- util/classpath/ClassLoaders.scala | 31 +++++++++++++++++++++++++ util/classpath/ClasspathUtilities.scala | 11 ++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/util/classpath/ClassLoaders.scala b/util/classpath/ClassLoaders.scala index d12283c05..e67764178 100644 --- a/util/classpath/ClassLoaders.scala +++ b/util/classpath/ClassLoaders.scala @@ -128,4 +128,35 @@ private object Loaders def isNestedOrSelf(className: String, checkAgainst: String) = className == checkAgainst || className.startsWith(checkAgainst + "$") def isSbtClass(className: String) = className.startsWith(Loaders.SbtPackage) +} + +final class NativeCopyConfig(val tempDirectory: File, val explicitLibraries: Seq[File], val searchPaths: Seq[File]) +trait NativeCopyLoader extends ClassLoader +{ + protected val config: NativeCopyConfig + import config._ + + private[this] val mapped = new collection.mutable.HashMap[String, String] + + override protected def findLibrary(name: String): String = + synchronized { mapped.getOrElseUpdate(name, findLibrary0(name)) } + + private[this] def findLibrary0(name: String): String = + { + val mappedName = System.mapLibraryName(name) + val explicit = explicitLibraries.filter(_.getName == mappedName).toStream + val search = searchPaths.toStream flatMap relativeLibrary(mappedName) + (explicit ++ search).headOption.map(copy).orNull + } + private[this] def relativeLibrary(mappedName: String)(base: File): Seq[File] = + { + val f = new File(base, mappedName) + if(f.isFile) f :: Nil else Nil + } + private[this] def copy(f: File): String = + { + val target = new File(tempDirectory, f.getName) + IO.copyFile(f, target) + target.getAbsolutePath + } } \ No newline at end of file diff --git a/util/classpath/ClasspathUtilities.scala b/util/classpath/ClasspathUtilities.scala index d94fb19e0..570f1329f 100644 --- a/util/classpath/ClasspathUtilities.scala +++ b/util/classpath/ClasspathUtilities.scala @@ -22,7 +22,13 @@ object ClasspathUtilities def toLoader(paths: Seq[File], parent: ClassLoader, resourceMap: Map[String,String]): ClassLoader = new URLClassLoader(Path.toURLs(paths), parent) with RawResources { override def resources = resourceMap } - + + def toLoader(paths: Seq[File], parent: ClassLoader, resourceMap: Map[String,String], nativeTemp: File): ClassLoader = + new URLClassLoader(Path.toURLs(paths), parent) with RawResources with NativeCopyLoader { + override def resources = resourceMap + override val config = new NativeCopyConfig(nativeTemp, paths, Nil) + } + lazy val rootLoader = { def parent(loader: ClassLoader): ClassLoader = @@ -50,6 +56,9 @@ object ClasspathUtilities def makeLoader[T](classpath: Seq[File], parent: ClassLoader, instance: ScalaInstance): ClassLoader = toLoader(classpath, parent, createClasspathResources(classpath, instance)) + + def makeLoader[T](classpath: Seq[File], parent: ClassLoader, instance: ScalaInstance, nativeTemp: File): ClassLoader = + toLoader(classpath, parent, createClasspathResources(classpath, instance), nativeTemp) private[sbt] def printSource(c: Class[_]) = println(c.getName + " loader=" +c.getClassLoader + " location=" + IO.classLocationFile(c))