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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
/* NSC -- new Scala compiler
* Copyright 2005-2009 LAMP/EPFL
* @author Paul Phillips
*/
package scala.util
import java.lang.{ ClassLoader => JavaClassLoader }
import java.lang.reflect.{ Constructor, Modifier, Method }
import java.net.URL
import ScalaClassLoader._
import scala.util.control.Exception.{ catching }
trait ScalaClassLoader extends JavaClassLoader
{
/** Executing an action with this classloader as context classloader */
def asContext[T](action: => T): T = {
val oldLoader = getContextLoader
try {
setContextLoader(this)
action
}
finally setContextLoader(oldLoader)
}
def setAsContext() { setContextLoader(this) }
/** Load and link a class with this classloader */
def tryToLoadClass[T <: AnyRef](path: String): Option[Class[T]] = tryClass(path, false)
/** Load, link and initialize a class with this classloader */
def tryToInitializeClass[T <: AnyRef](path: String): Option[Class[T]] = tryClass(path, true)
private def tryClass[T <: AnyRef](path: String, initialize: Boolean): Option[Class[T]] =
catching(classOf[ClassNotFoundException], classOf[SecurityException]) opt
Class.forName(path, initialize, this).asInstanceOf[Class[T]]
/** Create an instance of a class with this classloader */
def create(path: String): AnyRef = {
tryToInitializeClass(path) match {
case Some(clazz) => clazz.newInstance()
case None => null
}
}
/** Run the main method of a class to be loaded by this classloader */
def run(objectName: String, arguments: Seq[String]) {
val clsToRun = tryToInitializeClass(objectName) getOrElse (
throw new ClassNotFoundException(objectName)
)
val method = clsToRun.getMethod("main", classOf[Array[String]])
if (!Modifier.isStatic(method.getModifiers))
throw new NoSuchMethodException(objectName + ".main is not static")
asContext(method.invoke(null, Array(arguments.toArray): _*))
}
}
class URLClassLoader(urls: Seq[URL], parent: JavaClassLoader)
extends java.net.URLClassLoader(urls.toArray, parent)
with ScalaClassLoader
{
/** Override to widen to public */
override def addURL(url: URL) = super.addURL(url)
}
object ScalaClassLoader {
def setContextLoader(cl: JavaClassLoader) = Thread.currentThread.setContextClassLoader(cl)
def getContextLoader() = Thread.currentThread.getContextClassLoader()
def getSystemLoader() = JavaClassLoader.getSystemClassLoader()
def defaultParentClassLoader() = findExtClassLoader()
def fromURLs(urls: Seq[URL]): URLClassLoader =
new URLClassLoader(urls.toList, defaultParentClassLoader())
/** True if supplied class exists in supplied path */
def classExists(urls: Seq[URL], name: String): Boolean =
(fromURLs(urls) tryToLoadClass name).isDefined
// we cannot use the app classloader here or we get what looks to
// be classloader deadlock, but if we pass null we bypass the extension
// classloader and our extensions, so we search the hierarchy to find
// the classloader whose parent is null. Resolves bug #857.
def findExtClassLoader(): JavaClassLoader = {
def search(cl: JavaClassLoader): JavaClassLoader = {
if (cl == null) null
else if (cl.getParent == null) cl
else search(cl.getParent)
}
search(getContextLoader())
}
}
|