#1878 - whippin' up some badass ClassLoader magicks
This commit is contained in:
parent
4876eb037f
commit
8b02a20d75
3 changed files with 41 additions and 37 deletions
|
|
@ -11,7 +11,7 @@ import akka.util.Timeout
|
|||
import akka.util.duration._
|
||||
|
||||
@deprecated("use ActorSystem instead", "2.0")
|
||||
object GlobalActorSystem extends ActorSystemImpl("GlobalSystem", OldConfigurationLoader.defaultConfig) {
|
||||
object GlobalActorSystem extends ActorSystemImpl("GlobalSystem", OldConfigurationLoader.defaultConfig, OldConfigurationLoader.oldClassLoader) {
|
||||
start()
|
||||
|
||||
/**
|
||||
|
|
@ -26,11 +26,12 @@ object GlobalActorSystem extends ActorSystemImpl("GlobalSystem", OldConfiguratio
|
|||
*/
|
||||
@deprecated("use default config location or write your own configuration loader", "2.0")
|
||||
object OldConfigurationLoader {
|
||||
val oldClassLoader: ClassLoader = ActorSystem.findClassLoader(1)
|
||||
|
||||
val defaultConfig: Config = {
|
||||
val cfg = fromProperties orElse fromClasspath orElse fromHome getOrElse emptyConfig
|
||||
val config = cfg.withFallback(ConfigFactory.defaultReference)
|
||||
config.checkValid(ConfigFactory.defaultReference, "akka")
|
||||
val config = cfg.withFallback(ConfigFactory.defaultReference(oldClassLoader))
|
||||
config.checkValid(ConfigFactory.defaultReference(oldClassLoader), "akka")
|
||||
config
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import akka.routing._
|
|||
import akka.AkkaException
|
||||
import akka.util.{ Switch, Helpers }
|
||||
import akka.event._
|
||||
import com.typesafe.config.ConfigFactory
|
||||
|
||||
/**
|
||||
* Interface for all ActorRef providers to implement.
|
||||
|
|
|
|||
|
|
@ -37,27 +37,30 @@ object ActorSystem {
|
|||
|
||||
val GlobalHome = SystemHome orElse EnvHome
|
||||
|
||||
def create(name: String, config: Config): ActorSystem = apply(name, config)
|
||||
def apply(name: String, config: Config): ActorSystem = new ActorSystemImpl(name, config).start()
|
||||
|
||||
def create(): ActorSystem = apply()
|
||||
/**
|
||||
* Uses the standard default Config from ConfigFactory.load(), since none is provided.
|
||||
*/
|
||||
def create(name: String): ActorSystem = apply(name)
|
||||
def create(name: String, config: Config): ActorSystem = apply(name, config)
|
||||
def create(name: String, config: Config, classLoader: ClassLoader): ActorSystem = apply(name, config, classLoader)
|
||||
|
||||
/**
|
||||
* Uses the standard default Config from ConfigFactory.load(), since none is provided.
|
||||
*/
|
||||
def apply(name: String): ActorSystem = apply(name, ConfigFactory.load())
|
||||
|
||||
def create(): ActorSystem = apply()
|
||||
def apply(): ActorSystem = apply("default")
|
||||
def apply(name: String): ActorSystem = {
|
||||
val classLoader = findClassLoader(1)
|
||||
apply(name, ConfigFactory.load(classLoader), classLoader)
|
||||
}
|
||||
def apply(name: String, config: Config): ActorSystem = apply(name, config, findClassLoader(1))
|
||||
def apply(name: String, config: Config, classLoader: ClassLoader): ActorSystem = new ActorSystemImpl(name, config, classLoader).start()
|
||||
|
||||
class Settings(cfg: Config, final val name: String) {
|
||||
class Settings(classLoader: ClassLoader, cfg: Config, final val name: String) {
|
||||
|
||||
final val config: Config = {
|
||||
val config = cfg.withFallback(ConfigFactory.defaultReference)
|
||||
config.checkValid(ConfigFactory.defaultReference, "akka")
|
||||
val config = cfg.withFallback(ConfigFactory.defaultReference(classLoader))
|
||||
config.checkValid(ConfigFactory.defaultReference(classLoader), "akka")
|
||||
config
|
||||
}
|
||||
|
||||
|
|
@ -98,6 +101,27 @@ object ActorSystem {
|
|||
|
||||
override def toString: String = config.root.render
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL
|
||||
*/
|
||||
private[akka] def findClassLoader(depth: Int): ClassLoader = {
|
||||
def findCaller(get: Int ⇒ Class[_]): ClassLoader =
|
||||
Iterator.from(depth).map(get) dropWhile { c ⇒
|
||||
c != null &&
|
||||
(c.getName.startsWith("akka.actor.ActorSystem") ||
|
||||
c.getName.startsWith("scala.Option") ||
|
||||
c.getName.startsWith("scala.collection.Iterator") ||
|
||||
c.getName.startsWith("akka.util.Reflect"))
|
||||
} next () match {
|
||||
case null ⇒ getClass.getClassLoader
|
||||
case c ⇒ c.getClassLoader
|
||||
}
|
||||
|
||||
Option(Thread.currentThread.getContextClassLoader) orElse
|
||||
(Reflect.getCallerClass map findCaller) getOrElse
|
||||
getClass.getClassLoader
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -344,14 +368,14 @@ abstract class ExtendedActorSystem extends ActorSystem {
|
|||
def dynamicAccess: DynamicAccess
|
||||
}
|
||||
|
||||
class ActorSystemImpl protected[akka] (val name: String, applicationConfig: Config) extends ExtendedActorSystem {
|
||||
class ActorSystemImpl protected[akka] (val name: String, applicationConfig: Config, classLoader: ClassLoader) extends ExtendedActorSystem {
|
||||
|
||||
if (!name.matches("""^\w+$"""))
|
||||
throw new IllegalArgumentException("invalid ActorSystem name [" + name + "], must contain only word characters (i.e. [a-zA-Z_0-9])")
|
||||
|
||||
import ActorSystem._
|
||||
|
||||
final val settings: Settings = new Settings(applicationConfig, name)
|
||||
final val settings: Settings = new Settings(classLoader, applicationConfig, name)
|
||||
|
||||
protected def uncaughtExceptionHandler: Thread.UncaughtExceptionHandler =
|
||||
new Thread.UncaughtExceptionHandler() {
|
||||
|
|
@ -366,33 +390,13 @@ class ActorSystemImpl protected[akka] (val name: String, applicationConfig: Conf
|
|||
}
|
||||
|
||||
final val threadFactory: MonitorableThreadFactory =
|
||||
MonitorableThreadFactory(name, settings.Daemonicity, Option(Thread.currentThread.getContextClassLoader), uncaughtExceptionHandler)
|
||||
MonitorableThreadFactory(name, settings.Daemonicity, Option(classLoader), uncaughtExceptionHandler)
|
||||
|
||||
/**
|
||||
* This is an extension point: by overriding this method, subclasses can
|
||||
* control all reflection activities of an actor system.
|
||||
*/
|
||||
protected def createDynamicAccess(): DynamicAccess = new ReflectiveDynamicAccess(findClassLoader)
|
||||
|
||||
protected def findClassLoader: ClassLoader = {
|
||||
def findCaller(get: Int ⇒ Class[_]): ClassLoader = {
|
||||
val frames = Iterator.from(2).map(get)
|
||||
frames dropWhile { c ⇒
|
||||
c != null &&
|
||||
(c.getName.startsWith("akka.actor.ActorSystem") ||
|
||||
c.getName.startsWith("scala.Option") ||
|
||||
c.getName.startsWith("scala.collection.Iterator") ||
|
||||
c.getName.startsWith("akka.util.Reflect"))
|
||||
} next () match {
|
||||
case null ⇒ getClass.getClassLoader
|
||||
case c ⇒ c.getClassLoader
|
||||
}
|
||||
}
|
||||
|
||||
Option(Thread.currentThread.getContextClassLoader) orElse
|
||||
(Reflect.getCallerClass map findCaller) getOrElse
|
||||
getClass.getClassLoader
|
||||
}
|
||||
protected def createDynamicAccess(): DynamicAccess = new ReflectiveDynamicAccess(classLoader)
|
||||
|
||||
private val _pm: DynamicAccess = createDynamicAccess()
|
||||
def dynamicAccess: DynamicAccess = _pm
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue