pekko/akka-remote/src/main/scala/akka/remote/MessageSerializer.scala

112 lines
5.1 KiB
Scala
Raw Normal View History

2010-06-24 08:48:48 +02:00
/**
* Copyright (C) 2009-2011 Scalable Solutions AB <http://scalablesolutions.se>
2010-06-24 08:48:48 +02:00
*/
package akka.remote
2010-06-24 08:48:48 +02:00
import akka.serialization.{Serializer, Serializable}
import akka.remote.protocol.RemoteProtocol._
import akka.util._
2010-06-24 08:48:48 +02:00
import com.google.protobuf.{Message, ByteString}
object MessageSerializer extends Logging {
private def SERIALIZER_JAVA: Serializer.Java = Serializer.Java
private def SERIALIZER_JAVA_JSON: Serializer.JavaJSON = Serializer.JavaJSON
private def SERIALIZER_SCALA_JSON: Serializer.ScalaJSON = Serializer.ScalaJSON
private def SERIALIZER_SBINARY: Serializer.SBinary = Serializer.SBinary
private def SERIALIZER_PROTOBUF: Serializer.Protobuf = Serializer.Protobuf
2010-06-24 08:48:48 +02:00
def setClassLoader(cl: ClassLoader) = {
val someCl = Some(cl)
SERIALIZER_JAVA.classLoader = someCl
SERIALIZER_JAVA_JSON.classLoader = someCl
SERIALIZER_SCALA_JSON.classLoader = someCl
SERIALIZER_SBINARY.classLoader = someCl
2010-06-24 08:48:48 +02:00
}
def deserialize(messageProtocol: MessageProtocol): Any = {
messageProtocol.getSerializationScheme match {
case SerializationSchemeType.JAVA =>
unbox(SERIALIZER_JAVA.fromBinary(messageProtocol.getMessage.toByteArray, None))
case SerializationSchemeType.PROTOBUF =>
val clazz = loadManifest(SERIALIZER_PROTOBUF.classLoader, messageProtocol)
SERIALIZER_PROTOBUF.fromBinary(messageProtocol.getMessage.toByteArray, Some(clazz))
2010-06-24 08:48:48 +02:00
case SerializationSchemeType.SBINARY =>
val clazz = loadManifest(SERIALIZER_SBINARY.classLoader, messageProtocol)
2010-06-24 08:48:48 +02:00
val renderer = clazz.newInstance.asInstanceOf[Serializable.SBinary[_ <: AnyRef]]
renderer.fromBytes(messageProtocol.getMessage.toByteArray)
2010-06-24 08:48:48 +02:00
case SerializationSchemeType.SCALA_JSON =>
val clazz = loadManifest(SERIALIZER_SCALA_JSON.classLoader, messageProtocol)
val renderer = clazz.newInstance.asInstanceOf[Serializable.ScalaJSON[_]]
renderer.fromBytes(messageProtocol.getMessage.toByteArray)
2010-06-24 08:48:48 +02:00
case SerializationSchemeType.JAVA_JSON =>
val clazz = loadManifest(SERIALIZER_JAVA_JSON.classLoader, messageProtocol)
SERIALIZER_JAVA_JSON.fromBinary(messageProtocol.getMessage.toByteArray, Some(clazz))
2010-06-24 08:48:48 +02:00
}
}
def serialize(message: Any): MessageProtocol = {
val builder = MessageProtocol.newBuilder
if (message.isInstanceOf[Message]) {
2010-06-24 08:48:48 +02:00
val serializable = message.asInstanceOf[Message]
builder.setSerializationScheme(SerializationSchemeType.PROTOBUF)
builder.setMessage(ByteString.copyFrom(serializable.toByteArray))
builder.setMessageManifest(ByteString.copyFromUtf8(serializable.getClass.getName))
} else if (message.isInstanceOf[Serializable.ScalaJSON[_]]) {
2010-06-24 08:48:48 +02:00
builder.setSerializationScheme(SerializationSchemeType.SCALA_JSON)
setMessageAndManifest(builder, message.asInstanceOf[Serializable.ScalaJSON[_ <: Any]])
} else if (message.isInstanceOf[Serializable.SBinary[_]]) {
builder.setSerializationScheme(SerializationSchemeType.SBINARY)
setMessageAndManifest(builder, message.asInstanceOf[Serializable.SBinary[_ <: Any]])
2010-06-24 08:48:48 +02:00
} else if (message.isInstanceOf[Serializable.JavaJSON]) {
builder.setSerializationScheme(SerializationSchemeType.JAVA_JSON)
setMessageAndManifest(builder, message.asInstanceOf[Serializable.JavaJSON])
2010-06-24 08:48:48 +02:00
} else {
// default, e.g. if no protocol used explicitly then use Java serialization
builder.setSerializationScheme(SerializationSchemeType.JAVA)
builder.setMessage(ByteString.copyFrom(SERIALIZER_JAVA.toBinary(box(message))))
}
builder.build
}
private def loadManifest(classLoader: Option[ClassLoader], messageProtocol: MessageProtocol): Class[_] = {
val manifest = messageProtocol.getMessageManifest.toStringUtf8
if (classLoader.isDefined) classLoader.get.loadClass(manifest)
else Class.forName(manifest)
}
private def setMessageAndManifest(builder: MessageProtocol.Builder, serializable: Serializable) = {
builder.setMessage(ByteString.copyFrom(serializable.toBytes))
builder.setMessageManifest(ByteString.copyFromUtf8(serializable.getClass.getName))
}
2010-06-30 16:26:15 +02:00
2010-06-24 08:48:48 +02:00
private def box(value: Any): AnyRef = value match {
case value: Boolean => new java.lang.Boolean(value)
case value: Char => new java.lang.Character(value)
case value: Short => new java.lang.Short(value)
case value: Int => new java.lang.Integer(value)
case value: Long => new java.lang.Long(value)
case value: Float => new java.lang.Float(value)
case value: Double => new java.lang.Double(value)
case value: Byte => new java.lang.Byte(value)
case value => value.asInstanceOf[AnyRef]
2010-06-24 08:48:48 +02:00
}
private def unbox(value: AnyRef): Any = value match {
case value: java.lang.Boolean => value.booleanValue
2010-06-24 08:48:48 +02:00
case value: java.lang.Character => value.charValue
case value: java.lang.Short => value.shortValue
case value: java.lang.Integer => value.intValue
case value: java.lang.Long => value.longValue
case value: java.lang.Float => value.floatValue
case value: java.lang.Double => value.doubleValue
case value: java.lang.Byte => value.byteValue
case value => value
2010-06-24 08:48:48 +02:00
}
}