diff options
author | Christopher Vogt <oss.nsp@cvogt.org> | 2016-03-14 23:29:09 -0400 |
---|---|---|
committer | Christopher Vogt <oss.nsp@cvogt.org> | 2016-03-19 21:13:49 -0400 |
commit | a5f4db210aa2878eb8e15a6d9fe5235199d4aee6 (patch) | |
tree | 62ee3ddd75578f340a6c36f99188fae413585b4e /stage1/resolver.scala | |
parent | 35a96fea9336dfcac8aac75824450cbf7dc4ae1a (diff) | |
download | cbt-a5f4db210aa2878eb8e15a6d9fe5235199d4aee6.tar.gz cbt-a5f4db210aa2878eb8e15a6d9fe5235199d4aee6.tar.bz2 cbt-a5f4db210aa2878eb8e15a6d9fe5235199d4aee6.zip |
replace two level classloader with hierarchy
replace two level classloader (one for non-cachable dependencies with a cached parent one for cachable ones) with a hierachy of classloaders corresponding
this should eventually allow re-using CBT's classloader between stage1 and stage2
this change breaks the ScalaTest support for now
Diffstat (limited to 'stage1/resolver.scala')
-rw-r--r-- | stage1/resolver.scala | 105 |
1 files changed, 69 insertions, 36 deletions
diff --git a/stage1/resolver.scala b/stage1/resolver.scala index 87b9a24..87bab66 100644 --- a/stage1/resolver.scala +++ b/stage1/resolver.scala @@ -36,7 +36,6 @@ abstract class Dependency{ def jars: Seq[File] = exportedJars ++ dependencyJars def canBeCached = false - def cacheDependencyClassLoader = true //private type BuildCache = KeyLockedLazyCache[Dependency, Future[ClassPath]] def exportClasspathConcurrently: ClassPath = { @@ -86,43 +85,65 @@ abstract class Dependency{ ) } - private object classLoaderCache extends Cache[URLClassLoader] - def classLoader( classLoaderCache: ClassLoaderCache ): URLClassLoader = { - if( concurrencyEnabled ){ - // trigger concurrent building / downloading dependencies - exportClasspathConcurrently - } - val transitiveClassPath = { - (this +: transitiveDependencies).map{ - case d if d.canBeCached => Left(d) - case d => Right(d) - } - } - val buildClassPath = ClassPath.flatten( - transitiveClassPath.flatMap( - _.right.toOption.map(_.exportedClasspath) - ) - ) - val cachedClassPath = ClassPath.flatten( - transitiveClassPath.flatMap( - _.left.toOption - ).par.map(_.exportedClasspath).seq.sortBy(_.string) - ) - - if(cacheDependencyClassLoader){ - new URLClassLoader( - buildClassPath, - classLoaderCache.persistent.get( - cachedClassPath.string, - cbt.URLClassLoader( cachedClassPath, ClassLoader.getSystemClassLoader ) + def actual(current: Dependency, latest: Map[(String,String),Dependency]) = current match { + case d: ArtifactInfo => latest((d.groupId,d.artifactId)) + case d => d + } + private def dependencyClassLoader( latest: Map[(String,String),Dependency], cache: ClassLoaderCache ): ClassLoader = { + if( dependencies.isEmpty ){ + ClassLoader.getSystemClassLoader + } else if( dependencies.size == 1 ){ + dependencies.head.classLoaderRecursion( latest, cache ) + } else if( dependencies.forall(_.canBeCached) ){ + assert(transitiveDependencies.forall(_.canBeCached)) + cache.persistent.get( + dependencyClasspath.string, + new MultiClassLoader( + dependencies.map( _.classLoaderRecursion(latest, cache) ) ) ) } else { + val (cachable, nonCachable) = dependencies.partition(_.canBeCached) new URLClassLoader( - buildClassPath ++ cachedClassPath, ClassLoader.getSystemClassLoader + ClassPath.flatten( nonCachable.map(actual(_,latest)).map(_.exportedClasspath) ), + cache.persistent.get( + ClassPath.flatten( cachable.map(actual(_,latest)).map(_.exportedClasspath) ).string, + new MultiClassLoader( + cachable.map( _.classLoaderRecursion(latest, cache) ) + ) + ) + ) + new MultiClassLoader( + dependencies.map( _.classLoaderRecursion(latest, cache) ) ) } } + protected def classLoaderRecursion( latest: Map[(String,String),Dependency], cache: ClassLoaderCache ): ClassLoader = { + if( canBeCached ){ + val a = actual( this, latest ) + cache.persistent.get( + a.classpath.string, + cbt.URLClassLoader( a.exportedClasspath, dependencyClassLoader(latest, cache) ) + ) + } else { + cbt.URLClassLoader( exportedClasspath, dependencyClassLoader(latest, cache) ) + } + } + private object classLoaderCache extends Cache[ClassLoader] + def classLoader( cache: ClassLoaderCache ): ClassLoader = classLoaderCache{ + if( concurrencyEnabled ){ + // trigger concurrent building / downloading dependencies + exportClasspathConcurrently + } + classLoaderRecursion( + (this +: transitiveDependencies).collect{ + case d: ArtifactInfo => d + }.groupBy( + d => (d.groupId,d.artifactId) + ).mapValues(_.head), + cache + ) + } def classpath : ClassPath = exportedClasspath ++ dependencyClasspath def dependencyJars : Seq[File] = transitiveDependencies.flatMap(_.jars) def dependencyClasspath : ClassPath = ClassPath.flatten( transitiveDependencies.map(_.exportedClasspath) ) @@ -182,15 +203,27 @@ case class BinaryDependency( path: File, dependencies: Seq[Dependency] )(implici } case class Stage1Dependency()(implicit val logger: Logger) extends Dependency{ - def exportedClasspath = ClassPath( Seq(nailgunTarget, stage1Target) ) - def exportedJars = Seq[File]() - def dependencies = ScalaDependencies(constants.scalaVersion).dependencies def updated = false // FIXME: think this through, might allow simplifications and/or optimizations + override def canBeCached = false + private object classLoaderRecursionCache extends Cache[ClassLoader] + /* + override def classLoaderRecursion(latest: Map[(String,String),Dependency], cache: ClassLoaderCache) = classLoaderRecursionCache{ + println(System.currentTimeMillis) + val cl = getClass.getClassLoader + println(System.currentTimeMillis) + cl + ClassLoader.getSystemClassLoader + } + */ + override def exportedClasspath = ClassPath(Seq(nailgunTarget, stage1Target) ) + override def exportedJars = ???//Seq[File]() + override def dependencies = ScalaDependencies(constants.scalaVersion).dependencies def targetClasspath = exportedClasspath } case class CbtDependency()(implicit val logger: Logger) extends Dependency{ - def exportedClasspath = ClassPath( Seq( stage2Target ) ) - def exportedJars = Seq[File]() + override def canBeCached = false + override def exportedClasspath = ClassPath( Seq( stage2Target ) ) + override def exportedJars = Seq[File]() override def dependencies = Seq( Stage1Dependency(), JavaDependency("net.incongru.watchservice","barbary-watchservice","1.0"), |