diff options
Diffstat (limited to 'test/disabled/presentation/akka/src/akka/util/ReflectiveAccess.scala')
-rw-r--r-- | test/disabled/presentation/akka/src/akka/util/ReflectiveAccess.scala | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/test/disabled/presentation/akka/src/akka/util/ReflectiveAccess.scala b/test/disabled/presentation/akka/src/akka/util/ReflectiveAccess.scala new file mode 100644 index 0000000000..f38d1f9b98 --- /dev/null +++ b/test/disabled/presentation/akka/src/akka/util/ReflectiveAccess.scala @@ -0,0 +1,232 @@ +/** + * Copyright (C) 2009-2011 Scalable Solutions AB <http://scalablesolutions.se> + */ + +package akka.util + +import akka.dispatch.{ Future, CompletableFuture, MessageInvocation } +import akka.config.{ Config, ModuleNotAvailableException } + +import java.net.InetSocketAddress +import akka.remoteinterface.RemoteSupport +import akka.actor._ +import akka.event.EventHandler + +/** + * Helper class for reflective access to different modules in order to allow optional loading of modules. + * + * @author <a href="http://jonasboner.com">Jonas Bonér</a> + */ +object ReflectiveAccess { + + val loader = getClass.getClassLoader + + def isRemotingEnabled = Remote.isEnabled + lazy val isTypedActorEnabled = TypedActorModule.isEnabled + + def ensureRemotingEnabled = Remote.ensureEnabled + def ensureTypedActorEnabled = TypedActorModule.ensureEnabled + + /** + * Reflective access to the RemoteClient module. + * + * @author <a href="http://jonasboner.com">Jonas Bonér</a> + */ + object Remote { + val TRANSPORT = Config.config.getString("akka.remote.layer", "akka.remote.netty.NettyRemoteSupport") + + private[akka] val configDefaultAddress = + new InetSocketAddress(Config.config.getString("akka.remote.server.hostname", "localhost"), + Config.config.getInt("akka.remote.server.port", 2552)) + + 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") + EventHandler.debug(this, e.toString) + throw e + } + val remoteSupportClass = getClassFor[RemoteSupport](TRANSPORT) match { + case Right(value) => Some(value) + case Left(exception) => + EventHandler.debug(this, exception.toString) + None + } + + protected[akka] val defaultRemoteSupport: Option[() => RemoteSupport] = + remoteSupportClass map { remoteClass => + () => createInstance[RemoteSupport]( + remoteClass, + Array[Class[_]](), + Array[AnyRef]()) match { + case Right(value) => value + case Left(exception) => + val e = new ModuleNotAvailableException( + "Can't instantiate [%s] - make sure that akka-remote.jar is on the classpath".format(remoteClass.getName), exception) + EventHandler.debug(this, e.toString) + throw e + } + } + } + + /** + * Reflective access to the TypedActors module. + * + * @author <a href="http://jonasboner.com">Jonas Bonér</a> + */ + object TypedActorModule { + + type TypedActorObject = { + def isJoinPoint(message: Any): Boolean + def isJoinPointAndOneWay(message: Any): Boolean + def actorFor(proxy: AnyRef): Option[ActorRef] + def proxyFor(actorRef: ActorRef): Option[AnyRef] + def stop(anyRef: AnyRef): Unit + } + + lazy val isEnabled = typedActorObjectInstance.isDefined + + def ensureEnabled = if (!isTypedActorEnabled) throw new ModuleNotAvailableException( + "Can't load the typed actor module, make sure that akka-typed-actor.jar is on the classpath") + + val typedActorObjectInstance: Option[TypedActorObject] = + getObjectFor[TypedActorObject]("akka.actor.TypedActor$") match { + case Right(value) => Some(value) + case Left(exception) => + EventHandler.debug(this, exception.toString) + None + } + + def resolveFutureIfMessageIsJoinPoint(message: Any, future: Future[_]): Boolean = { + ensureEnabled + if (typedActorObjectInstance.get.isJoinPointAndOneWay(message)) { + future.asInstanceOf[CompletableFuture[Option[_]]].completeWithResult(None) + } + typedActorObjectInstance.get.isJoinPoint(message) + } + } + + object AkkaCloudModule { + + type Mailbox = { + def enqueue(message: MessageInvocation) + def dequeue: MessageInvocation + } + + type Serializer = { + def toBinary(obj: AnyRef): Array[Byte] + def fromBinary(bytes: Array[Byte], clazz: Option[Class[_]]): AnyRef + } + + lazy val isEnabled = clusterObjectInstance.isDefined + + val clusterObjectInstance: Option[AnyRef] = + getObjectFor[AnyRef]("akka.cloud.cluster.Cluster$") match { + case Right(value) => Some(value) + case Left(exception) => + EventHandler.debug(this, exception.toString) + None + } + + val serializerClass: Option[Class[_]] = + getClassFor("akka.serialization.Serializer") match { + case Right(value) => Some(value) + case Left(exception) => + EventHandler.debug(this, exception.toString) + None + } + + def ensureEnabled = if (!isEnabled) throw new ModuleNotAvailableException( + "Feature is only available in Akka Cloud") + } + + val noParams = Array[Class[_]]() + val noArgs = Array[AnyRef]() + + def createInstance[T](clazz: Class[_], + params: Array[Class[_]], + 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) + Right(ctor.newInstance(args: _*).asInstanceOf[T]) + } catch { + case e: Exception => Left(e) + } + + def createInstance[T](fqn: String, + params: Array[Class[_]], + args: Array[AnyRef], + classloader: ClassLoader = loader): Either[Exception, T] = try { + assert(params ne null) + assert(args ne null) + getClassFor(fqn) match { + case Right(value) => + val ctor = value.getDeclaredConstructor(params: _*) + ctor.setAccessible(true) + Right(ctor.newInstance(args: _*).asInstanceOf[T]) + case Left(exception) => Left(exception) //We could just cast this to Either[Exception, T] but it's ugly + } + } catch { + case e: Exception => + Left(e) + } + + //Obtains a reference to fqn.MODULE$ + def getObjectFor[T](fqn: String, classloader: ClassLoader = loader): Either[Exception, T] = try { + getClassFor(fqn) match { + case Right(value) => + val instance = value.getDeclaredField("MODULE$") + instance.setAccessible(true) + val obj = instance.get(null) + if (obj eq null) Left(new NullPointerException) else Right(obj.asInstanceOf[T]) + case Left(exception) => Left(exception) //We could just cast this to Either[Exception, T] but it's ugly + } + } catch { + case e: Exception => + Left(e) + } + + 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 { + Right(classloader.loadClass(fqn).asInstanceOf[Class[T]]) + } catch { + case c: ClassNotFoundException => Left(c) + } + + if (first.isRight) first + else { + // Second option is to use the ContextClassLoader + val second = try { + Right(Thread.currentThread.getContextClassLoader.loadClass(fqn).asInstanceOf[Class[T]]) + } catch { + case c: ClassNotFoundException => Left(c) + } + + if (second.isRight) second + else { + val third = try { + if (classloader ne loader) Right(loader.loadClass(fqn).asInstanceOf[Class[T]]) else Left(null) //Horrid + } catch { + case c: ClassNotFoundException => Left(c) + } + + if (third.isRight) third + else { + try { + Right(Class.forName(fqn).asInstanceOf[Class[T]]) // Last option is Class.forName + } catch { + case c: ClassNotFoundException => Left(c) + } + } + } + } + } catch { + case e: Exception => Left(e) + } +} |