2010-06-24 08:48:48 +02:00
|
|
|
/**
|
2010-12-22 15:35:50 +01:00
|
|
|
* Copyright (C) 2009-2011 Scalable Solutions AB <http://scalablesolutions.se>
|
2010-06-24 08:48:48 +02:00
|
|
|
*/
|
|
|
|
|
|
2010-10-26 12:49:25 +02:00
|
|
|
package akka.remote
|
2010-06-24 08:48:48 +02:00
|
|
|
|
2010-10-26 12:49:25 +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}
|
|
|
|
|
|
2010-07-04 01:34:16 +05:30
|
|
|
object MessageSerializer extends Logging {
|
2010-12-20 11:21:05 +01:00
|
|
|
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) = {
|
2010-12-20 11:21:05 +01:00
|
|
|
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))
|
2010-09-22 16:19:42 +05:30
|
|
|
|
2010-06-30 16:06:09 +02:00
|
|
|
case SerializationSchemeType.PROTOBUF =>
|
|
|
|
|
val clazz = loadManifest(SERIALIZER_PROTOBUF.classLoader, messageProtocol)
|
|
|
|
|
SERIALIZER_PROTOBUF.fromBinary(messageProtocol.getMessage.toByteArray, Some(clazz))
|
2010-09-22 16:19:42 +05:30
|
|
|
|
2010-06-24 08:48:48 +02:00
|
|
|
case SerializationSchemeType.SBINARY =>
|
2010-06-30 16:06:09 +02:00
|
|
|
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-09-22 16:19:42 +05:30
|
|
|
|
2010-06-24 08:48:48 +02:00
|
|
|
case SerializationSchemeType.SCALA_JSON =>
|
2010-06-30 16:06:09 +02:00
|
|
|
val clazz = loadManifest(SERIALIZER_SCALA_JSON.classLoader, messageProtocol)
|
2010-09-22 16:19:42 +05:30
|
|
|
val renderer = clazz.newInstance.asInstanceOf[Serializable.ScalaJSON[_]]
|
|
|
|
|
renderer.fromBytes(messageProtocol.getMessage.toByteArray)
|
|
|
|
|
|
2010-06-24 08:48:48 +02:00
|
|
|
case SerializationSchemeType.JAVA_JSON =>
|
2010-06-30 16:06:09 +02:00
|
|
|
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
|
2010-06-30 16:06:09 +02:00
|
|
|
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))
|
2010-06-30 16:06:09 +02:00
|
|
|
builder.setMessageManifest(ByteString.copyFromUtf8(serializable.getClass.getName))
|
2010-09-22 16:19:42 +05:30
|
|
|
} else if (message.isInstanceOf[Serializable.ScalaJSON[_]]) {
|
2010-06-24 08:48:48 +02:00
|
|
|
builder.setSerializationScheme(SerializationSchemeType.SCALA_JSON)
|
2010-09-22 16:19:42 +05:30
|
|
|
setMessageAndManifest(builder, message.asInstanceOf[Serializable.ScalaJSON[_ <: Any]])
|
2010-06-30 16:06:09 +02:00
|
|
|
} 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)
|
2010-06-30 16:06:09 +02:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-30 16:06:09 +02:00
|
|
|
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)
|
2010-06-30 16:06:09 +02:00
|
|
|
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 {
|
2010-06-30 16:06:09 +02:00
|
|
|
case value: java.lang.Boolean => value.booleanValue
|
2010-06-24 08:48:48 +02:00
|
|
|
case value: java.lang.Character => value.charValue
|
2010-06-30 16:06:09 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
|
}
|