@@ -14,14 +14,16 @@ package scala.tools.nsc.classpath
1414
1515import java .io .{Closeable ,File }
1616import java .net .{URI ,URL }
17+ import java .nio .file ._
1718
18- import scala .reflect .io .{AbstractFile ,PlainFile ,PlainNioFile }
19- import scala .tools .nsc .util .{ClassPath ,ClassRepresentation ,EfficientClassPath }
20- import FileUtils ._
2119import scala .jdk .CollectionConverters ._
2220import scala .reflect .internal .JDK9Reflectors
21+ import scala .reflect .io .{AbstractFile ,PlainFile ,PlainNioFile }
2322import scala .tools .nsc .CloseableRegistry
2423import scala .tools .nsc .classpath .PackageNameUtils .{packageContains ,separatePkgAndClassNames }
24+ import scala .tools .nsc .util .{ClassPath ,ClassRepresentation ,EfficientClassPath }
25+ import scala .util .Properties .{isJavaAtLeast ,javaHome }
26+ import FileUtils ._
2527
2628/**
2729 * A trait allowing to look for classpath entries in directories. It provides common logic for
@@ -129,12 +131,10 @@ trait JFileDirectoryLookup[FileEntryType <: ClassRepresentation] extends Directo
129131}
130132
131133object JrtClassPath {
132- import java .nio .file ._ ,java .net .URI
133134private val jrtClassPathCache = new FileBasedCache [Unit ,JrtClassPath ]()
134135private val ctSymClassPathCache = new FileBasedCache [String ,CtSymClassPath ]()
135- def apply (release :Option [String ],closeableRegistry :CloseableRegistry ): Option [ClassPath ]= {
136- import scala .util .Properties ._
137- if (! isJavaAtLeast(" 9" ))None
136+ def apply (release :Option [String ],unsafe :Option [List [String ]],closeableRegistry :CloseableRegistry ): List [ClassPath ]=
137+ if (! isJavaAtLeast(" 9" ))Nil
138138else {
139139// TODO escalate errors once we're sure they are fatal
140140// I'm hesitant to do this immediately, because -release will still work for multi-release JARs
@@ -145,28 +145,52 @@ object JrtClassPath {
145145
146146val currentMajorVersion : Int = JDK9Reflectors .runtimeVersionMajor(JDK9Reflectors .runtimeVersion()).intValue()
147147 releasematch {
148- case Some (v)if v.toInt< currentMajorVersion=>
149- try {
150- val ctSym = Paths .get(javaHome).resolve(" lib" ).resolve(" ct.sym" )
151- if (Files .notExists(ctSym))None
152- else {
153- val classPath = ctSymClassPathCache.getOrCreate(v, ctSym:: Nil , ()=> new CtSymClassPath (ctSym, v.toInt), closeableRegistry,true )
154- Some (classPath)
155- }
156- }catch {
157- case _ :Throwable => None
148+ case Some (version)if version.toInt< currentMajorVersion=>
149+ val ct = createCt(version, closeableRegistry)
150+ unsafematch {
151+ case Some (pkgs)=>
152+ val open = if (pkgs.isEmpty)List (" sun.misc" )else pkgs
153+ val jrts = createJrt(closeableRegistry)
154+ if (jrts.isEmpty) ct
155+ else ct.appended(new FilteringJrtClassPath (jrts.head,open :_* ))
156+ case _=> ct
158157 }
159158case _=>
160- try {
161- val fs = FileSystems .getFileSystem(URI .create(" jrt:/" ))
162- val classPath = jrtClassPathCache.getOrCreate((),Nil , ()=> new JrtClassPath (fs), closeableRegistry,false )
163- Some (classPath)
164- }catch {
165- case _ :ProviderNotFoundException | _ :FileSystemNotFoundException => None
166- }
159+ createJrt(closeableRegistry)
167160 }
168161 }
169- }
162+ private def createCt (v :String ,closeableRegistry :CloseableRegistry ): List [ClassPath ]=
163+ try {
164+ val ctSym = Paths .get(javaHome).resolve(" lib" ).resolve(" ct.sym" )
165+ if (Files .notExists(ctSym))Nil
166+ else {
167+ val classPath = ctSymClassPathCache.getOrCreate(v, ctSym:: Nil , ()=> new CtSymClassPath (ctSym, v.toInt), closeableRegistry, checkStamps= true )
168+ List (classPath)
169+ }
170+ }catch {
171+ case _ :Throwable => Nil
172+ }
173+ private def createJrt (closeableRegistry :CloseableRegistry ): List [JrtClassPath ]=
174+ try {
175+ val fs = FileSystems .getFileSystem(URI .create(" jrt:/" ))
176+ val classPath = jrtClassPathCache.getOrCreate((),Nil , ()=> new JrtClassPath (fs), closeableRegistry, checkStamps= false )
177+ List (classPath)
178+ }catch {
179+ case _ :ProviderNotFoundException | _ :FileSystemNotFoundException => Nil
180+ }
181+ }
182+
183+ final class FilteringJrtClassPath (delegate :JrtClassPath ,allowed :String * )extends ClassPath with NoSourcePaths {
184+ private val allowedPackages = allowed
185+ private def packagePrefix (p :String ,q :String )= p.startsWith(q)&& (p.length== q.length|| p.charAt(q.length)== '.' )
186+ private def ok (pkg :PackageName )= pkg.dottedString.isEmpty|| allowedPackages.exists(packagePrefix(_, pkg.dottedString))
187+ def asClassPathStrings : Seq [String ]= delegate.asClassPathStrings
188+ def asURLs : Seq [java.net.URL ]= delegate.asURLs
189+ private [nsc]def classes (inPackage :PackageName )= if (ok(inPackage)) delegate.classes(inPackage)else Nil
190+ def findClassFile (className :String )= if (ok(PackageName (separatePkgAndClassNames(className)._1))) delegate.findClassFile(className)else None
191+ private [nsc]def hasPackage (pkg :PackageName )= ok(pkg)&& delegate.hasPackage(pkg)
192+ private [nsc]def list (inPackage :PackageName )= if (ok(inPackage)) delegate.list(inPackage)else ClassPathEntries (Nil ,Nil )
193+ private [nsc]def packages (inPackage :PackageName )= if (ok(inPackage)) delegate.packages(inPackage)else Nil
170194}
171195
172196/**
@@ -177,8 +201,7 @@ object JrtClassPath {
177201 *
178202 * The implementation assumes that no classes exist in the empty package.
179203*/
180- final class JrtClassPath (fs : java.nio.file.FileSystem )extends ClassPath with NoSourcePaths {
181- import java .nio .file .Path ,java .nio .file ._
204+ final class JrtClassPath (fs :FileSystem )extends ClassPath with NoSourcePaths {
182205type F = Path
183206private val dir : Path = fs.getPath(" /packages" )
184207
@@ -246,7 +269,7 @@ final class CtSymClassPath(ctSym: java.nio.file.Path, release: Int) extends Clas
246269// e.g. "java.lang" -> Seq(/876/java/lang, /87/java/lang, /8/java/lang))
247270private val packageIndex : scala.collection.Map [String , scala.collection.Seq [Path ]]= {
248271val index = collection.mutable.AnyRefMap [String , collection.mutable.ListBuffer [Path ]]()
249- val isJava12OrHigher = scala.util. Properties . isJavaAtLeast(" 12" )
272+ val isJava12OrHigher = isJavaAtLeast(" 12" )
250273 rootsForRelease.foreach(root=> Files .walk(root).iterator().asScala.filter(Files .isDirectory(_)).foreach { p=>
251274val moduleNamePathElementCount = if (isJava12OrHigher)1 else 0
252275if (p.getNameCount> root.getNameCount+ moduleNamePathElementCount) {