@@ -12,6 +12,8 @@ package inc
12
12
import java .io .File
13
13
import xsbti .ArtifactInfo .ScalaOrganization
14
14
import sbt .io .IO
15
+ import scala .language .reflectiveCalls
16
+ import sbt .internal .inc .classpath .ClasspathUtilities
15
17
16
18
/**
17
19
* A Scala instance encapsulates all the information that is bound to a concrete
@@ -35,12 +37,33 @@ import sbt.io.IO
35
37
final class ScalaInstance (
36
38
val version : String ,
37
39
val loader : ClassLoader ,
40
+ val loaderLibraryOnly : ClassLoader ,
38
41
val libraryJar : File ,
39
42
val compilerJar : File ,
40
43
val allJars : Array [File ],
41
44
val explicitActual : Option [String ]
42
45
) extends xsbti.compile.ScalaInstance {
43
46
47
+ @ deprecated(" Use constructor with loaderLibraryOnly" , " 1.1.2" )
48
+ def this (
49
+ version : String ,
50
+ loader : ClassLoader ,
51
+ libraryJar : File ,
52
+ compilerJar : File ,
53
+ allJars : Array [File ],
54
+ explicitActual : Option [String ]
55
+ ) {
56
+ this (
57
+ version,
58
+ loader,
59
+ ClasspathUtilities .rootLoader,
60
+ libraryJar,
61
+ compilerJar,
62
+ allJars,
63
+ explicitActual
64
+ )
65
+ }
66
+
44
67
/**
45
68
* Check whether `scalaInstance` comes from a managed (i.e. ivy-resolved)
46
69
* scala **or** if it's a free-floating `ScalaInstance`, in which case we
@@ -75,7 +98,13 @@ final class ScalaInstance(
75
98
override def toString : String =
76
99
s " Scala instance { version label $version, actual version $actualVersion, $jarStrings } "
77
100
}
101
+
78
102
object ScalaInstance {
103
+ /*
104
+ * Structural extention for the ScalaProvider post 1.0.3 launcher.
105
+ * See https://github.com/sbt/zinc/pull/505.
106
+ */
107
+ private type ScalaProvider2 = { def loaderLibraryOnly : ClassLoader }
79
108
80
109
/** Name of scala organisation to be used for artifact resolution. */
81
110
val ScalaOrg = ScalaOrganization
@@ -123,30 +152,47 @@ object ScalaInstance {
123
152
}
124
153
}
125
154
val jars = provider.jars
126
- val loader = provider.loader
127
155
val libraryJar = findOrCrash(jars, " scala-library.jar" )
128
156
val compilerJar = findOrCrash(jars, " scala-compiler.jar" )
129
- new ScalaInstance (version, loader, libraryJar, compilerJar, jars, None )
157
+ def fallbackClassLoaders = {
158
+ val l = ClasspathUtilities .toLoader(Vector (libraryJar))
159
+ val c = scalaLoader(l)(jars.toVector filterNot { _ == libraryJar })
160
+ (c, l)
161
+ }
162
+ // sbt launcher 1.0.3 will construct layered classloader. Use them if we find them.
163
+ // otherwise, construct layered loaders manually.
164
+ val (loader, loaderLibraryOnly) = {
165
+ (try {
166
+ provider match {
167
+ case p : ScalaProvider2 @ unchecked => Option ((provider.loader, p.loaderLibraryOnly))
168
+ }
169
+ } catch {
170
+ case _ : NoSuchMethodError => None
171
+ }) getOrElse fallbackClassLoaders
172
+ }
173
+ new ScalaInstance (version, loader, loaderLibraryOnly, libraryJar, compilerJar, jars, None )
130
174
}
131
175
132
176
def apply (scalaHome : File , launcher : xsbti.Launcher ): ScalaInstance =
133
- apply(scalaHome)(scalaLoader (launcher))
177
+ apply(scalaHome)(scalaLibraryLoader (launcher))
134
178
135
179
def apply (scalaHome : File )(classLoader : List [File ] => ClassLoader ): ScalaInstance = {
136
180
val all = allJars(scalaHome)
137
- val loader = classLoader(all.toList)
138
181
val library = libraryJar(scalaHome)
182
+ val loaderLibraryOnly = classLoader(List (library))
183
+ val loader = scalaLoader(loaderLibraryOnly)(all.toVector filterNot { _ == library })
139
184
val version = actualVersion(loader)(" (library jar " + library.getAbsolutePath + " )" )
140
185
val compiler = compilerJar(scalaHome)
141
- new ScalaInstance (version, loader, library, compiler, all.toArray, None )
186
+ new ScalaInstance (version, loader, loaderLibraryOnly, library, compiler, all.toArray, None )
142
187
}
143
188
144
189
def apply (version : String , scalaHome : File , launcher : xsbti.Launcher ): ScalaInstance = {
145
190
val all = allJars(scalaHome)
146
- val loader = scalaLoader(launcher)(all.toList)
147
191
val library = libraryJar(scalaHome)
192
+ val loaderLibraryOnly = scalaLibraryLoader(launcher)(List (library))
193
+ val loader = scalaLoader(loaderLibraryOnly)(all.toVector)
148
194
val compiler = compilerJar(scalaHome)
149
- new ScalaInstance (version, loader, library, compiler, all.toArray, None )
195
+ new ScalaInstance (version, loader, loaderLibraryOnly, library, compiler, all.toArray, None )
150
196
}
151
197
152
198
/** Return all the required Scala jars from a path `scalaHome`. */
@@ -209,12 +255,12 @@ object ScalaInstance {
209
255
} finally stream.close()
210
256
}
211
257
212
- private def scalaLoader (launcher : xsbti.Launcher ): Seq [File ] => ClassLoader = { jars =>
213
- import java . net .{ URL , URLClassLoader }
214
- new URLClassLoader (
215
- jars.map(_.toURI.toURL).toArray[ URL ],
216
- launcher.topLoader
217
- )
258
+ private def scalaLibraryLoader (launcher : xsbti.Launcher ): Seq [File ] => ClassLoader = { jars =>
259
+ ClasspathUtilities .toLoader(jars, launcher.topLoader)
260
+ }
261
+
262
+ private def scalaLoader ( parent : ClassLoader ) : Seq [ File ] => ClassLoader = { jars =>
263
+ ClasspathUtilities .toLoader(jars, parent )
218
264
}
219
265
}
220
266
0 commit comments