1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
package scala.scalajs.sbtplugin.env.phantomjs
import scala.scalajs.tools.io.IO
/** A special [[ClassLoader]] to load the Jetty 8 dependency of [[PhantomJSEnv]]
* in a private space.
*
* It loads everything that belongs to [[JettyWebsocketManager]] itself (while
* retrieving the requested class file from its parent.
* For all other classes, it first tries to load them from [[jettyLoader]],
* which should only contain the Jetty 8 classpath.
* If this fails, it delegates to its parent.
*
* The rationale is, that [[JettyWebsocketManager]] and its dependees can use
* the classes on the Jetty 8 classpath, while they remain hidden from the rest
* of the Java world. This allows to load another version of Jetty in the same
* JVM for the rest of the project.
*/
private[sbtplugin] class PhantomJettyClassLoader(jettyLoader: ClassLoader,
parent: ClassLoader) extends ClassLoader(parent) {
def this(loader: ClassLoader) =
this(loader, ClassLoader.getSystemClassLoader())
/** Classes needed to bridge private jetty classpath and public PhantomJS
* Basically everything defined in JettyWebsocketManager.
*/
private val bridgeClasses = Set(
"scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager",
"scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager$WSLogger",
"scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager$ComWebSocketListener",
"scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager$$anon$1",
"scala.scalajs.sbtplugin.env.phantomjs.JettyWebsocketManager$$anon$2"
)
override protected def loadClass(name: String, resolve: Boolean): Class[_] = {
if (bridgeClasses.contains(name)) {
// Load bridgeClasses manually since they must be associated to this
// class loader, rather than the parent class loader in order to find the
// jetty classes
// First check if we have loaded it already
Option(findLoadedClass(name)) getOrElse {
val wsManager =
parent.getResourceAsStream(name.replace('.', '/') + ".class")
if (wsManager == null) {
throw new ClassNotFoundException(name)
} else {
val buf = IO.readInputStreamToByteArray(wsManager)
defineClass(name, buf, 0, buf.length)
}
}
} else {
try {
jettyLoader.loadClass(name)
} catch {
case _: ClassNotFoundException =>
super.loadClass(name, resolve)
}
}
}
}
|