From 6ab828bc7fc51f4d9cd50ab9e0332ae0023a9a17 Mon Sep 17 00:00:00 2001 From: Dan Hopkins Date: Mon, 3 Feb 2014 09:37:43 -0700 Subject: [PATCH] Add a serialization format to actor selections. Fixes #3748 --- .../scala/akka/actor/ActorSelectionSpec.scala | 8 +++++++ .../scala/akka/actor/ActorSelection.scala | 21 +++++++++++++++++++ .../test/scala/akka/remote/RemotingSpec.scala | 4 ++++ 3 files changed, 33 insertions(+) diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorSelectionSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorSelectionSpec.scala index aee06caf70..5d74b8e443 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorSelectionSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorSelectionSpec.scala @@ -332,6 +332,14 @@ class ActorSelectionSpec extends AkkaSpec("akka.loglevel=DEBUG") with DefaultTim s"ActorSelection[Anchor(akka://ActorSelectionSpec/user/c2/c21#${c21.path.uid}), Path(/../*/hello)]") } + "have a stringly serializable path" in { + system.actorSelection(system / "c2").toSerializationFormat should be("akka://ActorSelectionSpec/user/c2") + system.actorSelection(system / "c2" / "c21").toSerializationFormat should be("akka://ActorSelectionSpec/user/c2/c21") + ActorSelection(c2, "/").toSerializationFormat should be("akka://ActorSelectionSpec/user/c2") + ActorSelection(c2, "../*/hello").toSerializationFormat should be("akka://ActorSelectionSpec/user/c2/../*/hello") + ActorSelection(c2, "/../*/hello").toSerializationFormat should be("akka://ActorSelectionSpec/user/c2/../*/hello") + } + "send ActorSelection targeted to missing actor to deadLetters" in { val p = TestProbe() system.eventStream.subscribe(p.ref, classOf[DeadLetter]) diff --git a/akka-actor/src/main/scala/akka/actor/ActorSelection.scala b/akka-actor/src/main/scala/akka/actor/ActorSelection.scala index 5441997e5c..9e9a1ed513 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorSelection.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorSelection.scala @@ -99,6 +99,27 @@ abstract class ActorSelection extends Serializable { */ def pathString: String = path.mkString("/", "/", "") + /** + * String representation of the actor selection suitable for storage and recreation. + * The output is similar to the URI fragment returned by [[akka.actor.ActorPath.toSerializationFormat]]. + * @return URI fragment + */ + def toSerializationFormat: String = { + val anchorPath = anchor match { + case a: ActorRefWithCell ⇒ anchor.path.toStringWithAddress(a.provider.getDefaultAddress) + case _ ⇒ anchor.path.toString + } + + val builder = new java.lang.StringBuilder() + builder.append(anchorPath) + val lastChar = builder.charAt(builder.length - 1) + if (path.nonEmpty && lastChar != '/') + builder.append(path.mkString("/", "/", "")) + else if (path.nonEmpty) + builder.append(path.mkString("/")) + builder.toString + } + override def equals(obj: Any): Boolean = obj match { case s: ActorSelection ⇒ this.anchor == s.anchor && this.path == s.path case _ ⇒ false diff --git a/akka-remote/src/test/scala/akka/remote/RemotingSpec.scala b/akka-remote/src/test/scala/akka/remote/RemotingSpec.scala index f9b485b69b..c766d281c8 100644 --- a/akka-remote/src/test/scala/akka/remote/RemotingSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/RemotingSpec.scala @@ -416,6 +416,10 @@ class RemotingSpec extends AkkaSpec(RemotingSpec.cfg) with ImplicitSender with D system.actorSelection(child.path / "*" / "grandgrandchild") ! Identify("idReq13") expectMsg(ActorIdentity("idReq13", Some(grandgrandchild))) + val sel1 = system.actorSelection("/user/looker2/child/grandchild/grandgrandchild") + system.actorSelection(sel1.toSerializationFormat) ! Identify("idReq18") + expectMsg(ActorIdentity("idReq18", Some(grandgrandchild))) + child ! Identify("idReq14") expectMsg(ActorIdentity("idReq14", Some(child))) watch(child)