2016-04-28 23:33:59 +10:00
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
|
|
|
|
|
*/
|
|
|
|
|
package akka.remote.serialization
|
|
|
|
|
|
|
|
|
|
import akka.actor._
|
|
|
|
|
import akka.protobuf.ByteString
|
|
|
|
|
import akka.remote.ContainerFormats
|
|
|
|
|
import akka.serialization.{ Serialization, BaseSerializer, SerializationExtension, SerializerWithStringManifest }
|
|
|
|
|
|
|
|
|
|
class MiscMessageSerializer(val system: ExtendedActorSystem) extends SerializerWithStringManifest with BaseSerializer {
|
|
|
|
|
|
|
|
|
|
private lazy val serialization = SerializationExtension(system)
|
2016-09-28 11:14:33 +02:00
|
|
|
private val payloadSupport = new WrappedPayloadSupport(system)
|
|
|
|
|
private val throwableSupport = new ThrowableSupport(system)
|
2016-04-28 23:33:59 +10:00
|
|
|
|
2016-09-26 15:04:53 +02:00
|
|
|
private val ParameterlessSerialized = Array.empty[Byte]
|
2016-06-19 17:55:10 +02:00
|
|
|
|
2016-04-28 23:33:59 +10:00
|
|
|
def toBinary(obj: AnyRef): Array[Byte] = obj match {
|
|
|
|
|
case identify: Identify ⇒ serializeIdentify(identify)
|
|
|
|
|
case identity: ActorIdentity ⇒ serializeActorIdentity(identity)
|
2016-06-19 17:55:10 +02:00
|
|
|
case Some(value) ⇒ serializeSome(value)
|
|
|
|
|
case None ⇒ NoneSerialized
|
2016-09-27 15:46:22 +02:00
|
|
|
case r: ActorRef ⇒ serializeActorRef(r)
|
2016-09-28 11:14:33 +02:00
|
|
|
case s: Status.Success ⇒ serializeStatusSuccess(s)
|
|
|
|
|
case f: Status.Failure ⇒ serializeStatusFailure(f)
|
|
|
|
|
case t: Throwable ⇒ throwableSupport.serializeThrowable(t)
|
2016-09-26 15:04:53 +02:00
|
|
|
case None ⇒ ParameterlessSerialized
|
|
|
|
|
case PoisonPill ⇒ ParameterlessSerialized
|
|
|
|
|
case Kill ⇒ ParameterlessSerialized
|
2016-04-28 23:33:59 +10:00
|
|
|
case _ ⇒ throw new IllegalArgumentException(s"Cannot serialize object of type [${obj.getClass.getName}]")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def serializeIdentify(identify: Identify): Array[Byte] =
|
|
|
|
|
ContainerFormats.Identify.newBuilder()
|
2016-09-28 11:14:33 +02:00
|
|
|
.setMessageId(payloadSupport.payloadBuilder(identify.messageId))
|
2016-04-28 23:33:59 +10:00
|
|
|
.build()
|
|
|
|
|
.toByteArray
|
|
|
|
|
|
|
|
|
|
private def serializeActorIdentity(actorIdentity: ActorIdentity): Array[Byte] = {
|
|
|
|
|
val builder =
|
|
|
|
|
ContainerFormats.ActorIdentity.newBuilder()
|
2016-09-28 11:14:33 +02:00
|
|
|
.setCorrelationId(payloadSupport.payloadBuilder(actorIdentity.correlationId))
|
2016-04-28 23:33:59 +10:00
|
|
|
|
|
|
|
|
actorIdentity.ref.foreach { actorRef ⇒
|
|
|
|
|
builder.setRef(actorRefBuilder(actorRef))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
builder
|
|
|
|
|
.build()
|
|
|
|
|
.toByteArray
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-19 17:55:10 +02:00
|
|
|
private def serializeSome(someValue: Any): Array[Byte] =
|
|
|
|
|
ContainerFormats.Option.newBuilder()
|
2016-09-28 11:14:33 +02:00
|
|
|
.setValue(payloadSupport.payloadBuilder(someValue))
|
2016-06-19 17:55:10 +02:00
|
|
|
.build()
|
|
|
|
|
.toByteArray
|
|
|
|
|
|
2016-09-27 15:46:22 +02:00
|
|
|
private def serializeActorRef(ref: ActorRef): Array[Byte] =
|
|
|
|
|
actorRefBuilder(ref).build().toByteArray
|
|
|
|
|
|
2016-04-28 23:33:59 +10:00
|
|
|
private def actorRefBuilder(actorRef: ActorRef): ContainerFormats.ActorRef.Builder =
|
|
|
|
|
ContainerFormats.ActorRef.newBuilder()
|
|
|
|
|
.setPath(Serialization.serializedActorPath(actorRef))
|
|
|
|
|
|
2016-09-28 11:14:33 +02:00
|
|
|
private def serializeStatusSuccess(success: Status.Success): Array[Byte] =
|
|
|
|
|
payloadSupport.payloadBuilder(success.status).build().toByteArray
|
2016-04-28 23:33:59 +10:00
|
|
|
|
2016-09-28 11:14:33 +02:00
|
|
|
private def serializeStatusFailure(failure: Status.Failure): Array[Byte] =
|
|
|
|
|
payloadSupport.payloadBuilder(failure.cause).build().toByteArray
|
2016-04-28 23:33:59 +10:00
|
|
|
|
|
|
|
|
private val IdentifyManifest = "A"
|
2016-09-26 15:04:53 +02:00
|
|
|
private val ActorIdentityManifest = "B"
|
2016-06-19 17:55:10 +02:00
|
|
|
private val OptionManifest = "C"
|
2016-09-28 11:14:33 +02:00
|
|
|
private val StatusSuccessManifest = "D"
|
|
|
|
|
private val StatusFailureManifest = "E"
|
|
|
|
|
private val ThrowableManifest = "F"
|
2016-09-27 15:46:22 +02:00
|
|
|
private val ActorRefManifest = "G"
|
2016-09-26 15:04:53 +02:00
|
|
|
private val PoisonPillManifest = "P"
|
|
|
|
|
private val KillManifest = "K"
|
2016-04-28 23:33:59 +10:00
|
|
|
|
|
|
|
|
private val fromBinaryMap = Map[String, Array[Byte] ⇒ AnyRef](
|
2016-06-02 14:06:57 +02:00
|
|
|
IdentifyManifest → deserializeIdentify,
|
2016-06-19 17:55:10 +02:00
|
|
|
ActorIdentifyManifest → deserializeActorIdentity,
|
2016-09-28 11:14:33 +02:00
|
|
|
OptionManifest → deserializeOption,
|
|
|
|
|
StatusSuccessManifest → deserializeStatusSuccess,
|
|
|
|
|
StatusFailureManifest → deserializeStatusFailure,
|
2016-09-27 15:46:22 +02:00
|
|
|
ThrowableManifest → throwableSupport.deserializeThrowable,
|
|
|
|
|
ActorRefManifest → deserializeActorRefBytes)
|
2016-09-26 15:04:53 +02:00
|
|
|
OptionManifest → deserializeOption,
|
|
|
|
|
PoisonPillManifest → ((_) ⇒ PoisonPill),
|
|
|
|
|
KillManifest → ((_) ⇒ Kill)
|
|
|
|
|
)
|
2016-04-28 23:33:59 +10:00
|
|
|
|
|
|
|
|
override def manifest(o: AnyRef): String =
|
|
|
|
|
o match {
|
2016-09-28 11:14:33 +02:00
|
|
|
case _: Identify ⇒ IdentifyManifest
|
|
|
|
|
case _: ActorIdentity ⇒ ActorIdentifyManifest
|
|
|
|
|
case _: Option[Any] ⇒ OptionManifest
|
2016-09-27 15:46:22 +02:00
|
|
|
case _: ActorRef ⇒ ActorRefManifest
|
2016-09-28 11:14:33 +02:00
|
|
|
case _: Status.Success ⇒ StatusSuccessManifest
|
|
|
|
|
case _: Status.Failure ⇒ StatusFailureManifest
|
|
|
|
|
case _: Throwable ⇒ ThrowableManifest
|
2016-09-26 15:04:53 +02:00
|
|
|
case _: Identify ⇒ IdentifyManifest
|
|
|
|
|
case _: ActorIdentity ⇒ ActorIdentityManifest
|
|
|
|
|
case _: Option[Any] ⇒ OptionManifest
|
|
|
|
|
case _: PoisonPill.type ⇒ PoisonPillManifest
|
|
|
|
|
case _: Kill.type ⇒ KillManifest
|
2016-04-28 23:33:59 +10:00
|
|
|
case _ ⇒
|
|
|
|
|
throw new IllegalArgumentException(s"Can't serialize object of type ${o.getClass} in [${getClass.getName}]")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef =
|
|
|
|
|
fromBinaryMap.get(manifest) match {
|
|
|
|
|
case Some(deserializer) ⇒ deserializer(bytes)
|
|
|
|
|
case None ⇒ throw new IllegalArgumentException(
|
|
|
|
|
s"Unimplemented deserialization of message with manifest [$manifest] in [${getClass.getName}]")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def deserializeIdentify(bytes: Array[Byte]): Identify = {
|
|
|
|
|
val identifyProto = ContainerFormats.Identify.parseFrom(bytes)
|
2016-09-28 11:14:33 +02:00
|
|
|
val messageId = payloadSupport.deserializePayload(identifyProto.getMessageId)
|
2016-04-28 23:33:59 +10:00
|
|
|
Identify(messageId)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def deserializeActorIdentity(bytes: Array[Byte]): ActorIdentity = {
|
|
|
|
|
val actorIdentityProto = ContainerFormats.ActorIdentity.parseFrom(bytes)
|
2016-09-28 11:14:33 +02:00
|
|
|
val correlationId = payloadSupport.deserializePayload(actorIdentityProto.getCorrelationId)
|
2016-04-28 23:33:59 +10:00
|
|
|
val actorRef =
|
|
|
|
|
if (actorIdentityProto.hasRef)
|
|
|
|
|
Some(deserializeActorRef(actorIdentityProto.getRef))
|
|
|
|
|
else
|
|
|
|
|
None
|
|
|
|
|
ActorIdentity(correlationId, actorRef)
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-27 15:46:22 +02:00
|
|
|
private def deserializeActorRefBytes(bytes: Array[Byte]): ActorRef =
|
|
|
|
|
deserializeActorRef(ContainerFormats.ActorRef.parseFrom(bytes))
|
|
|
|
|
|
2016-04-28 23:33:59 +10:00
|
|
|
private def deserializeActorRef(actorRef: ContainerFormats.ActorRef): ActorRef =
|
|
|
|
|
serialization.system.provider.resolveActorRef(actorRef.getPath)
|
|
|
|
|
|
2016-06-19 17:55:10 +02:00
|
|
|
private def deserializeOption(bytes: Array[Byte]): Option[Any] = {
|
|
|
|
|
if (bytes.length == 0)
|
|
|
|
|
None
|
|
|
|
|
else {
|
|
|
|
|
val optionProto = ContainerFormats.Option.parseFrom(bytes)
|
2016-09-28 11:14:33 +02:00
|
|
|
Some(payloadSupport.deserializePayload(optionProto.getValue))
|
2016-06-19 17:55:10 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-28 11:14:33 +02:00
|
|
|
private def deserializeStatusSuccess(bytes: Array[Byte]): Status.Success =
|
|
|
|
|
Status.Success(payloadSupport.deserializePayload(ContainerFormats.Payload.parseFrom(bytes)))
|
|
|
|
|
|
|
|
|
|
private def deserializeStatusFailure(bytes: Array[Byte]): Status.Failure =
|
|
|
|
|
Status.Failure(payloadSupport.deserializePayload(ContainerFormats.Payload.parseFrom(bytes)).asInstanceOf[Throwable])
|
2016-04-28 23:33:59 +10:00
|
|
|
|
|
|
|
|
}
|