Fixing ticket 808

This commit is contained in:
Viktor Klang 2011-04-29 17:15:00 +02:00
parent b5873ff2c7
commit c2486cd52c
14 changed files with 95 additions and 79 deletions

View file

@ -16,7 +16,7 @@ import java.net.{InetAddress, UnknownHostException}
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
class AkkaException(message: String = "") extends RuntimeException(message) with Serializable {
class AkkaException(message: String = "", cause: Throwable = null) extends RuntimeException(message, cause) with Serializable {
val uuid = "%s_%s".format(AkkaException.hostname, newUuid)
override lazy val toString = {

View file

@ -67,12 +67,12 @@ case class MaximumNumberOfRestartsWithinTimeRangeReached(
@BeanProperty val lastExceptionCausingRestart: Throwable) extends LifeCycleMessage
// Exceptions for Actors
class ActorStartException private[akka](message: String) extends AkkaException(message)
class IllegalActorStateException private[akka](message: String) extends AkkaException(message)
class ActorKilledException private[akka](message: String) extends AkkaException(message)
class ActorInitializationException private[akka](message: String) extends AkkaException(message)
class ActorTimeoutException private[akka](message: String) extends AkkaException(message)
class InvalidMessageException private[akka](message: String) extends AkkaException(message)
class ActorStartException private[akka](message: String, cause: Throwable = null) extends AkkaException(message, cause)
class IllegalActorStateException private[akka](message: String, cause: Throwable = null) extends AkkaException(message, cause)
class ActorKilledException private[akka](message: String, cause: Throwable = null) extends AkkaException(message, cause)
class ActorInitializationException private[akka](message: String, cause: Throwable = null) extends AkkaException(message, cause)
class ActorTimeoutException private[akka](message: String, cause: Throwable = null) extends AkkaException(message, cause)
class InvalidMessageException private[akka](message: String, cause: Throwable = null) extends AkkaException(message, cause)
/**
* This message is thrown by default when an Actors behavior doesn't match a message
@ -161,12 +161,15 @@ object Actor extends ListenerManagement {
*/
def actorOf(clazz: Class[_ <: Actor]): ActorRef = new LocalActorRef(() => {
import ReflectiveAccess.{ createInstance, noParams, noArgs }
createInstance[Actor](clazz.asInstanceOf[Class[_]], noParams, noArgs).getOrElse(
throw new ActorInitializationException(
createInstance[Actor](clazz.asInstanceOf[Class[_]], noParams, noArgs) match {
case r: Right[Exception, Actor] => r.b
case l: Left[Exception, Actor] => throw new ActorInitializationException(
"Could not instantiate Actor of " + clazz +
"\nMake sure Actor is NOT defined inside a class/trait," +
"\nif so put it outside the class/trait, f.e. in a companion object," +
"\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'."))
"\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'.", l.a)
}
}, None)
/**

View file

@ -13,7 +13,7 @@ import java.util.concurrent.{CopyOnWriteArrayList, ConcurrentHashMap}
import java.net.InetSocketAddress
import akka.config.Supervision._
class SupervisorException private[akka](message: String) extends AkkaException(message)
class SupervisorException private[akka](message: String, cause: Throwable = null) extends AkkaException(message, cause)
/**
* Factory object for creating supervisors declarative. It creates instances of the 'Supervisor' class.

View file

@ -6,8 +6,8 @@ package akka.config
import akka.AkkaException
class ConfigurationException(message: String) extends AkkaException(message)
class ModuleNotAvailableException(message: String) extends AkkaException(message)
class ConfigurationException(message: String, cause: Throwable = null) extends AkkaException(message, cause)
class ModuleNotAvailableException(message: String, cause: Throwable = null) extends AkkaException(message, cause)
/**
* Loads up the configuration (from the akka.conf file).

View file

@ -23,7 +23,7 @@ object DataFlow {
object Start
object Exit
class DataFlowVariableException(msg: String) extends AkkaException(msg)
class DataFlowVariableException(message: String, cause: Throwable = null) extends AkkaException(message, cause)
/**
* Executes the supplied thunk in another thread.

View file

@ -187,14 +187,14 @@ object Dispatchers {
case "GlobalExecutorBasedEventDriven" => GlobalExecutorBasedEventDrivenDispatcherConfigurator
case fqn =>
ReflectiveAccess.getClassFor[MessageDispatcherConfigurator](fqn) match {
case Some(clazz) =>
val instance = ReflectiveAccess.createInstance[MessageDispatcherConfigurator](clazz, Array[Class[_]](), Array[AnyRef]())
if (instance.isEmpty)
throw new IllegalArgumentException("Cannot instantiate MessageDispatcherConfigurator type [%s], make sure it has a default no-args constructor" format fqn)
else
instance.get
case None =>
throw new IllegalArgumentException("Unknown MessageDispatcherConfigurator type [%s]" format fqn)
case r: Right[_, Class[MessageDispatcherConfigurator]] =>
ReflectiveAccess.createInstance[MessageDispatcherConfigurator](r.b, Array[Class[_]](), Array[AnyRef]()) match {
case r: Right[Exception, MessageDispatcherConfigurator] => r.b
case l: Left[Exception, MessageDispatcherConfigurator] =>
throw new IllegalArgumentException("Cannot instantiate MessageDispatcherConfigurator type [%s], make sure it has a default no-args constructor" format fqn, l.a)
}
case l: Left[Exception, _] =>
throw new IllegalArgumentException("Unknown MessageDispatcherConfigurator type [%s]" format fqn, l.a)
}
} map {
_ configure cfg

View file

@ -19,7 +19,7 @@ import java.util.{LinkedList => JLinkedList}
import scala.collection.mutable.Stack
import annotation.tailrec
class FutureTimeoutException(message: String) extends AkkaException(message)
class FutureTimeoutException(message: String, cause: Throwable = null) extends AkkaException(message, cause)
object Futures {

View file

@ -11,7 +11,7 @@ import java.util.{Queue, List, Comparator, PriorityQueue}
import java.util.concurrent._
import akka.util._
class MessageQueueAppendFailedException(message: String) extends AkkaException(message)
class MessageQueueAppendFailedException(message: String, cause: Throwable = null) extends AkkaException(message, cause)
/**
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>

View file

@ -220,14 +220,15 @@ object EventHandler extends ListenerManagement {
}
defaultListeners foreach { listenerName =>
try {
ReflectiveAccess.getClassFor[Actor](listenerName) map { clazz =>
addListener(Actor.actorOf(clazz).start())
ReflectiveAccess.getClassFor[Actor](listenerName) match {
case r: Right[_, Class[Actor]] => addListener(Actor.actorOf(r.b).start())
case l: Left[Exception,_] => throw l.a
}
} catch {
case e: Exception =>
throw new ConfigurationException(
"Event Handler specified in config can't be loaded [" + listenerName +
"] due to [" + e.toString + "]")
"] due to [" + e.toString + "]", e)
}
}
}

View file

@ -116,7 +116,7 @@ case class RemoteServerWriteFailed(
class RemoteClientException private[akka] (
message: String,
@BeanProperty val client: RemoteClientModule,
val remoteAddress: InetSocketAddress) extends AkkaException(message)
val remoteAddress: InetSocketAddress, cause: Throwable = null) extends AkkaException(message, cause)
/**
* Thrown when the remote server actor dispatching fails for some reason.
@ -189,13 +189,14 @@ abstract class RemoteSupport extends ListenerManagement with RemoteServerModule
def actorOf(clazz: Class[_ <: Actor], host: String, port: Int): ActorRef = {
import ReflectiveAccess.{ createInstance, noParams, noArgs }
clientManagedActorOf(() =>
createInstance[Actor](clazz.asInstanceOf[Class[_]], noParams, noArgs).getOrElse(
throw new ActorInitializationException(
"Could not instantiate Actor" +
"\nMake sure Actor is NOT defined inside a class/trait," +
"\nif so put it outside the class/trait, f.e. in a companion object," +
"\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'.")),
host, port)
createInstance[Actor](clazz.asInstanceOf[Class[_]], noParams, noArgs) match {
case r: Right[_, Actor] => r.b
case l: Left[Exception, _] => throw new ActorInitializationException(
"Could not instantiate Actor" +
"\nMake sure Actor is NOT defined inside a class/trait," +
"\nif so put it outside the class/trait, f.e. in a companion object," +
"\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'.", l.a)
}, host, port)
}
/**
@ -217,13 +218,14 @@ abstract class RemoteSupport extends ListenerManagement with RemoteServerModule
def actorOf[T <: Actor : Manifest](host: String, port: Int): ActorRef = {
import ReflectiveAccess.{ createInstance, noParams, noArgs }
clientManagedActorOf(() =>
createInstance[Actor](manifest[T].erasure.asInstanceOf[Class[_]], noParams, noArgs).getOrElse(
throw new ActorInitializationException(
"Could not instantiate Actor" +
"\nMake sure Actor is NOT defined inside a class/trait," +
"\nif so put it outside the class/trait, f.e. in a companion object," +
"\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'.")),
host, port)
createInstance[Actor](manifest[T].erasure.asInstanceOf[Class[_]], noParams, noArgs) match {
case r: Right[_, Actor] => r.b
case l: Left[Exception, _] => throw new ActorInitializationException(
"Could not instantiate Actor" +
"\nMake sure Actor is NOT defined inside a class/trait," +
"\nif so put it outside the class/trait, f.e. in a companion object," +
"\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'.", l.a)
}, host, port)
}
protected override def manageLifeCycleOfListeners = false

View file

@ -42,12 +42,16 @@ object ReflectiveAccess {
lazy val isEnabled = remoteSupportClass.isDefined
def ensureEnabled = if (!isEnabled) {
val e = new ModuleNotAvailableException(
"Can't load the remoting module, make sure that akka-remote.jar is on the classpath")
val e = new ModuleNotAvailableException("Can't load the remoting module, make sure that akka-remote.jar is on the classpath")
EventHandler.debug(this, e.toString)
throw e
}
val remoteSupportClass: Option[Class[_ <: RemoteSupport]] = getClassFor(TRANSPORT)
val remoteSupportClass = getClassFor[RemoteSupport](TRANSPORT) match {
case r: Right[_, Class[RemoteSupport]] => Some(r.b)
case l: Left[Exception,_] =>
EventHandler.debug(this, l.a)
None
}
protected[akka] val defaultRemoteSupport: Option[() => RemoteSupport] =
remoteSupportClass map { remoteClass =>
@ -55,9 +59,11 @@ object ReflectiveAccess {
remoteClass,
Array[Class[_]](),
Array[AnyRef]()
) getOrElse {
) match {
case r: Right[Exception, RemoteSupport] => r.b
case l: Left[Exception, RemoteSupport] =>
val e = new ModuleNotAvailableException(
"Can't instantiate [%s] - make sure that akka-remote.jar is on the classpath".format(remoteClass.getName))
"Can't instantiate [%s] - make sure that akka-remote.jar is on the classpath".format(remoteClass.getName), l.a)
EventHandler.debug(this, e.toString)
throw e
}
@ -114,7 +120,12 @@ object ReflectiveAccess {
getObjectFor("akka.cloud.cluster.Cluster$")
val serializerClass: Option[Class[_]] =
getClassFor("akka.serialization.Serializer")
getClassFor("akka.serialization.Serializer") match {
case r: Right[_, Class[_]] => Some(r.b)
case l: Left[Exception,_] =>
EventHandler.debug(this, l.toString)
None
}
def ensureEnabled = if (!isEnabled) throw new ModuleNotAvailableException(
"Feature is only available in Akka Cloud")
@ -125,17 +136,15 @@ object ReflectiveAccess {
def createInstance[T](clazz: Class[_],
params: Array[Class[_]],
args: Array[AnyRef]): Option[T] = try {
args: Array[AnyRef]): Either[Exception,T] = try {
assert(clazz ne null)
assert(params ne null)
assert(args ne null)
val ctor = clazz.getDeclaredConstructor(params: _*)
ctor.setAccessible(true)
Some(ctor.newInstance(args: _*).asInstanceOf[T])
Right(ctor.newInstance(args: _*).asInstanceOf[T])
} catch {
case e: Exception =>
EventHandler.debug(this, e.toString)
None
case e: Exception => Left(e)
}
def createInstance[T](fqn: String,
@ -145,11 +154,11 @@ object ReflectiveAccess {
assert(params ne null)
assert(args ne null)
getClassFor(fqn) match {
case Some(clazz) =>
val ctor = clazz.getDeclaredConstructor(params: _*)
case r: Right[Exception, Class[T]] =>
val ctor = r.b.getDeclaredConstructor(params: _*)
ctor.setAccessible(true)
Some(ctor.newInstance(args: _*).asInstanceOf[T])
case None => None
case _ => None
}
} catch {
case e: Exception =>
@ -159,11 +168,11 @@ object ReflectiveAccess {
def getObjectFor[T](fqn: String, classloader: ClassLoader = loader): Option[T] = try {//Obtains a reference to $MODULE$
getClassFor(fqn) match {
case Some(clazz) =>
val instance = clazz.getDeclaredField("MODULE$")
case r: Right[Exception, Class[T]] =>
val instance = r.b.getDeclaredField("MODULE$")
instance.setAccessible(true)
Option(instance.get(null).asInstanceOf[T])
case None => None
case _ => None
}
} catch {
case e: ExceptionInInitializerError =>
@ -171,45 +180,44 @@ object ReflectiveAccess {
throw e
}
def getClassFor[T](fqn: String, classloader: ClassLoader = loader): Option[Class[T]] = {
def getClassFor[T](fqn: String, classloader: ClassLoader = loader): Either[Exception,Class[T]] = try {
assert(fqn ne null)
// First, use the specified CL
val first = try {
Option(classloader.loadClass(fqn).asInstanceOf[Class[T]])
Right(classloader.loadClass(fqn).asInstanceOf[Class[T]])
} catch {
case c: ClassNotFoundException => None
case c: ClassNotFoundException => Left(c)
}
if (first.isDefined) first
if (first.isRight) first
else {
// Second option is to use the ContextClassLoader
val second = try {
Option(Thread.currentThread.getContextClassLoader.loadClass(fqn).asInstanceOf[Class[T]])
Right(Thread.currentThread.getContextClassLoader.loadClass(fqn).asInstanceOf[Class[T]])
} catch {
case c: ClassNotFoundException => None
case c: ClassNotFoundException => Left(c)
}
if (second.isDefined) second
if (second.isRight) second
else {
val third = try {
// Don't try to use "loader" if we got the default "classloader" parameter
if (classloader ne loader) Option(loader.loadClass(fqn).asInstanceOf[Class[T]])
else None
if (classloader ne loader) Right(loader.loadClass(fqn).asInstanceOf[Class[T]]) else Left(null) //Horrid
} catch {
case c: ClassNotFoundException => None
case c: ClassNotFoundException => Left(c)
}
if (third.isDefined) third
if (third.isRight) third
else {
// Last option is Class.forName
try {
Option(Class.forName(fqn).asInstanceOf[Class[T]])
Right(Class.forName(fqn).asInstanceOf[Class[T]]) // Last option is Class.forName
} catch {
case c: ClassNotFoundException => None
case c: ClassNotFoundException => Left(c)
}
}
}
}
} catch {
case e: Exception => Left(e)
}
}

View file

@ -41,7 +41,7 @@ import java.util.concurrent.atomic.{AtomicReference, AtomicBoolean}
import java.util.concurrent._
import akka.AkkaException
class RemoteClientMessageBufferException(message: String) extends AkkaException(message)
class RemoteClientMessageBufferException(message: String, cause: Throwable = null) extends AkkaException(message, cause)
object RemoteEncoder {
def encode(rmp: RemoteMessageProtocol): AkkaRemoteProtocol = {

View file

@ -72,12 +72,14 @@ object TestActorRef {
def apply[T <: Actor : Manifest] : TestActorRef[T] = new TestActorRef[T] ({ () =>
import ReflectiveAccess.{ createInstance, noParams, noArgs }
createInstance[T](manifest[T].erasure, noParams, noArgs).getOrElse(
throw new ActorInitializationException(
createInstance[T](manifest[T].erasure, noParams, noArgs) match {
case r: Right[_, T] => r.b
case l: Left[Exception, _] => throw new ActorInitializationException(
"Could not instantiate Actor" +
"\nMake sure Actor is NOT defined inside a class/trait," +
"\nif so put it outside the class/trait, f.e. in a companion object," +
"\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'."))
"\nOR try to change: 'actorOf[MyActor]' to 'actorOf(new MyActor)'.", l.a)
}
})
}

View file

@ -9,7 +9,7 @@ import akka.stm.Atomic
import scala.util.DynamicVariable
class CoordinateException private[akka](message: String) extends AkkaException(message)
class CoordinateException private[akka](message: String, cause: Throwable = null) extends AkkaException(message, cause)
/**
* Coordinating transactions between typed actors.