diff --git a/akka-actor-tests/src/test/java/akka/actor/JavaExtension.java b/akka-actor-tests/src/test/java/akka/actor/JavaExtension.java index fefec7640a..43aade632e 100644 --- a/akka-actor-tests/src/test/java/akka/actor/JavaExtension.java +++ b/akka-actor-tests/src/test/java/akka/actor/JavaExtension.java @@ -31,6 +31,15 @@ public class JavaExtension { system = i; } } + + static class OtherExtension implements Extension { + static final ExtensionKey key = new ExtensionKey(OtherExtension.class) {}; + + public final ActorSystemImpl system; + public OtherExtension(ActorSystemImpl i) { + system = i; + } + } private Config c = ConfigFactory.parseString("akka.extensions = [ \"akka.actor.JavaExtension$Provider\" ]", ConfigParseOptions.defaults()); @@ -42,5 +51,10 @@ public class JavaExtension { assertSame(system.extension(defaultInstance).system, system); assertSame(defaultInstance.apply(system).system, system); } + + @Test + public void mustBeAdHoc() { + assertSame(OtherExtension.key.apply(system).system, system); + } } diff --git a/akka-actor/src/main/scala/akka/actor/Extension.scala b/akka-actor/src/main/scala/akka/actor/Extension.scala index bfd4ab6a52..966795ff93 100644 --- a/akka-actor/src/main/scala/akka/actor/Extension.scala +++ b/akka-actor/src/main/scala/akka/actor/Extension.scala @@ -3,6 +3,8 @@ */ package akka.actor +import akka.util.ReflectiveAccess + /** * The basic ActorSystem covers all that is needed for locally running actors, * using futures and so on. In addition, more features can hook into it and @@ -64,3 +66,37 @@ trait ExtensionIdProvider { */ def lookup(): ExtensionId[_ <: Extension] } + +/** + * This is a one-stop-shop if all you want is an extension which is + * constructed with the ActorSystemImpl as its only constructor argument: + * + * {{{ + * object MyExt extends ExtensionKey[Ext] + * + * class Ext(system: ActorSystemImpl) extends MyExt { + * ... + * } + * }}} + * + * Java API: + * + * {{{ + * public class MyExt extends Extension { + * static final ExtensionKey key = new ExtensionKey(MyExt.class); + * + * public MyExt(ActorSystemImpl system) { + * ... + * } + * }}} + */ +abstract class ExtensionKey[T <: Extension](implicit m: ClassManifest[T]) extends ExtensionId[T] with ExtensionIdProvider { + def this(clazz: Class[T]) = this()(ClassManifest.fromClass(clazz)) + + override def lookup() = this + def createExtension(system: ActorSystemImpl): T = + ReflectiveAccess.createInstance[T](m.erasure, Array[Class[_]](classOf[ActorSystemImpl]), Array[AnyRef](system)) match { + case Left(ex) ⇒ throw ex + case Right(r) ⇒ r + } +} diff --git a/akka-actor/src/main/scala/akka/event/Logging.scala b/akka-actor/src/main/scala/akka/event/Logging.scala index bae930cb17..ad99dd5af2 100644 --- a/akka-actor/src/main/scala/akka/event/Logging.scala +++ b/akka-actor/src/main/scala/akka/event/Logging.scala @@ -3,7 +3,7 @@ */ package akka.event -import akka.actor.{ Actor, ActorPath, ActorRef, MinimalActorRef, LocalActorRef, Props, ActorSystem, ActorSystemImpl, simpleName } +import akka.actor._ import akka.AkkaException import akka.actor.ActorSystem.Settings import akka.util.ReflectiveAccess @@ -38,7 +38,6 @@ trait LoggingBus extends ActorEventBus { private val guard = new ReentrantGuard private var loggers = Seq.empty[ActorRef] private var _logLevel: LogLevel = _ - private val loggerId = new AtomicInteger /** * Query currently set log level. See object Logging for more information. @@ -144,7 +143,7 @@ trait LoggingBus extends ActorEventBus { } private def addLogger(system: ActorSystemImpl, clazz: Class[_ <: Actor], level: LogLevel): ActorRef = { - val name = "log" + loggerId.incrementAndGet + "-" + simpleName(clazz) + val name = "log" + Extension(system).id() + "-" + simpleName(clazz) val actor = system.systemActorOf(Props(clazz), name) implicit val timeout = Timeout(3 seconds) val response = try actor ? InitializeLogger(this) get catch { @@ -225,6 +224,13 @@ object LogSource { */ object Logging { + object Extension extends ExtensionKey[Ext] + + class Ext(system: ActorSystemImpl) extends Extension { + private val loggerId = new AtomicInteger + def id() = loggerId.incrementAndGet() + } + /** * Marker trait for annotating LogLevel, which must be Int after erasure. */