class loader extension to handle native libraries loaded in multiple class loaders

This commit is contained in:
Mark Harrah 2011-08-05 21:56:32 -04:00
parent f065037572
commit 7ea35daec2
2 changed files with 41 additions and 1 deletions

View File

@ -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
}
}

View File

@ -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))