2009-07-21 13:59:12 +02:00
|
|
|
/**
|
|
|
|
|
* Copyright (C) 2009 Scalable Solutions.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package se.scalablesolutions.akka.serialization
|
|
|
|
|
|
2009-07-23 20:01:37 +02:00
|
|
|
import org.codehaus.jackson.map.ObjectMapper
|
|
|
|
|
import com.google.protobuf.Message
|
2009-07-21 13:59:12 +02:00
|
|
|
import com.twitter.commons.Json
|
|
|
|
|
import reflect.Manifest
|
|
|
|
|
import sbinary.DefaultProtocol
|
2009-07-23 20:01:37 +02:00
|
|
|
import java.io.{StringWriter, ByteArrayOutputStream, ObjectOutputStream}
|
2009-07-21 13:59:12 +02:00
|
|
|
|
2009-07-23 20:01:37 +02:00
|
|
|
object SerializationProtocol {
|
|
|
|
|
val SBINARY = 1
|
|
|
|
|
val SCALA_JSON = 2
|
|
|
|
|
val JAVA_JSON = 3
|
|
|
|
|
val PROTOBUF = 4
|
|
|
|
|
val JAVA = 5
|
|
|
|
|
val AVRO = 6
|
|
|
|
|
}
|
2009-07-21 13:59:12 +02:00
|
|
|
|
2009-07-23 20:01:37 +02:00
|
|
|
/**
|
|
|
|
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
|
|
|
|
*/
|
|
|
|
|
trait Serializable {
|
|
|
|
|
def toBytes: Array[Byte]
|
|
|
|
|
}
|
2009-07-21 13:59:12 +02:00
|
|
|
|
2009-07-23 20:01:37 +02:00
|
|
|
/**
|
2009-07-27 21:21:28 +02:00
|
|
|
* Serialization protocols.
|
|
|
|
|
*
|
2009-07-23 20:01:37 +02:00
|
|
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
|
|
|
|
*/
|
|
|
|
|
object Serializable {
|
|
|
|
|
|
2009-07-27 21:21:28 +02:00
|
|
|
/**
|
|
|
|
|
* Example on how to use the SBinary serialization protocol:
|
|
|
|
|
* <pre>
|
|
|
|
|
* case class User(val usernamePassword: Tuple2[String, String],
|
|
|
|
|
* val email: String,
|
|
|
|
|
* val age: Int)
|
|
|
|
|
* extends Serializable.SBinary[User] {
|
|
|
|
|
* def this() = this(null, null, 0)
|
|
|
|
|
* import sbinary.DefaultProtocol._
|
|
|
|
|
* implicit object UserFormat extends Format[User] {
|
|
|
|
|
* def reads(in : Input) = User(
|
|
|
|
|
* read[Tuple2[String, String]](in),
|
|
|
|
|
* read[String](in),
|
|
|
|
|
* read[Int](in))
|
|
|
|
|
* def writes(out: Output, value: User) = {
|
|
|
|
|
* write[Tuple2[String, String]](out, value.usernamePassword)
|
|
|
|
|
* write[String](out, value.email)
|
|
|
|
|
* write[Int](out, value.age)
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* def fromBytes(bytes: Array[Byte]) = fromByteArray[User](bytes)
|
|
|
|
|
* def toBytes: Array[Byte] = toByteArray(this)
|
|
|
|
|
* }
|
|
|
|
|
* </pre>
|
|
|
|
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
|
|
|
|
*/
|
|
|
|
|
trait SBinary[T <: AnyRef] extends Serializable {
|
|
|
|
|
def fromBytes(bytes: Array[Byte]): T
|
|
|
|
|
def toBytes: Array[Byte]
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-23 20:01:37 +02:00
|
|
|
/**
|
|
|
|
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
|
|
|
|
*/
|
2009-07-28 13:28:01 +02:00
|
|
|
trait JSON extends Serializable {
|
2009-07-23 20:01:37 +02:00
|
|
|
def toJSON: String
|
2009-07-21 13:59:12 +02:00
|
|
|
}
|
2009-07-28 13:28:01 +02:00
|
|
|
|
2009-07-23 20:01:37 +02:00
|
|
|
/**
|
|
|
|
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
|
|
|
|
*/
|
2009-07-28 13:28:01 +02:00
|
|
|
abstract class JavaJSON extends JSON {
|
2009-07-21 13:59:12 +02:00
|
|
|
|
|
|
|
|
def toJSON: String = {
|
|
|
|
|
val out = new StringWriter
|
2009-07-28 13:28:01 +02:00
|
|
|
// FIXME: is this mapper expensive to create? Should I cache it away?
|
|
|
|
|
val mapper = new ObjectMapper
|
|
|
|
|
mapper.writeValue(out, this)
|
2009-07-21 13:59:12 +02:00
|
|
|
out.close
|
|
|
|
|
out.toString
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def toBytes: Array[Byte] = {
|
|
|
|
|
val bos = new ByteArrayOutputStream
|
|
|
|
|
val out = new ObjectOutputStream(bos)
|
2009-07-28 13:28:01 +02:00
|
|
|
val mapper = new ObjectMapper
|
|
|
|
|
mapper.writeValue(out, this)
|
2009-07-21 13:59:12 +02:00
|
|
|
out.close
|
|
|
|
|
bos.toByteArray
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-23 20:01:37 +02:00
|
|
|
/**
|
|
|
|
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
|
|
|
|
*/
|
2009-07-28 13:28:01 +02:00
|
|
|
trait ScalaJSON extends JSON {
|
|
|
|
|
def toJSON: String = Json.build(this).toString
|
|
|
|
|
def toBytes: Array[Byte] = toJSON.getBytes("UTF-8")
|
2009-07-23 20:01:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
|
|
|
|
*/
|
2009-07-28 12:55:13 +02:00
|
|
|
trait Protobuf[T] extends Serializable {
|
|
|
|
|
def fromBytes(bytes: Array[Byte]): T = getMessage.toBuilder.mergeFrom(bytes).asInstanceOf[T]
|
|
|
|
|
def toBytes: Array[Byte] = getMessage.toByteArray
|
|
|
|
|
def getMessage: Message
|
2009-07-23 20:01:37 +02:00
|
|
|
}
|
2009-07-27 21:21:28 +02:00
|
|
|
}
|