diff --git a/jvm-serializers-protowar/pom.xml b/jvm-serializers-protowar/pom.xml
new file mode 100644
index 0000000..ba74625
--- /dev/null
+++ b/jvm-serializers-protowar/pom.xml
@@ -0,0 +1,61 @@
+
+
+ 4.0.0
+
+ jvm-serializers
+ jvm-serializers-parent
+ 1.0-SNAPSHOT
+
+ jvm-serializers
+ jvm-serializers-protowar
+ 1.0-SNAPSHOT
+ jvm-serializers-protowar
+ protowar of jvm-serializers Terraformed... by jim@psychosynthintelligence... on x86_64 x86_64 GNU/Linux... for protowar,scala_media_container,tpc...
+ http://psychosynthintelligence/protowar
+
+ HEAD
+
+
+
+
+ jvm-serializers-legacy
+ jvm-serializers-Repo
+ file://${basedir}/../src/main/repository
+ default
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.5
+ 1.5
+ true
+ 1024m
+ 1024m
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ javacc-maven-plugin
+ 2.4.1
+
+
+
+
diff --git a/jvm-serializers-protowar/pom.xml.~1~ b/jvm-serializers-protowar/pom.xml.~1~
new file mode 100644
index 0000000..5c78f0e
--- /dev/null
+++ b/jvm-serializers-protowar/pom.xml.~1~
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ jvm-serializers
+ jvm-serializers-parent
+ 1.0-SNAPSHOT
+
+ jvm-serializers
+ jvm-serializers-protowar
+ 1.0-SNAPSHOT
+ jvm-serializers-protowarprotowar of jvm-serializers Terraformed... by jim@psychosynthintelligence... on x86_64 x86_64 GNU/Linux... for protowar,scala_media_container,tpc...
+ http://psychosynthintelligence/protowarHEAD
+ jvm-serializers-legacyjvm-serializers-Repo file://${basedir}/../src/main/repository defaultorg.apache.maven.pluginsmaven-compiler-plugin1.51.5true1024m1024morg.codehaus.mojojavacc-maven-plugin2.4.1
diff --git a/jvm-serializers-protowar/src/main/java/jvm-serializers/protowar/App.java b/jvm-serializers-protowar/src/main/java/jvm-serializers/protowar/App.java
new file mode 100644
index 0000000..ece3c35
--- /dev/null
+++ b/jvm-serializers-protowar/src/main/java/jvm-serializers/protowar/App.java
@@ -0,0 +1,13 @@
+package jvm-serializers.protowar;
+
+/**
+ * Hello world!
+ *
+ */
+public class App
+{
+ public static void main( String[] args )
+ {
+ System.out.println( "Hello World!" );
+ }
+}
diff --git a/jvm-serializers-protowar/src/main/java/org/protowar/ProtoServerHandler.java b/jvm-serializers-protowar/src/main/java/org/protowar/ProtoServerHandler.java
new file mode 100644
index 0000000..ce6566c
--- /dev/null
+++ b/jvm-serializers-protowar/src/main/java/org/protowar/ProtoServerHandler.java
@@ -0,0 +1,66 @@
+package org.protowar;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import serializers.ObjectSerializer;
+import serializers.ProtobufSerializer;
+import serializers.protobuf.MediaContentHolder.MediaContent;
+import serializers.protobuf.MediaContentHolder.MediaServer;
+
+import com.google.protobuf.Message;
+import com.google.protobuf.RpcCallback;
+import com.google.protobuf.RpcController;
+import com.google.protobuf.Descriptors.MethodDescriptor;
+
+class ProtoServerHandler extends MediaServer
+{
+ private final ObjectSerializer _serializer = new ProtobufSerializer();
+
+ @Override
+ public void updateMedia (RpcController controller, MediaContent request, RpcCallback done)
+ {
+ try
+ {
+ //System.out.println(request.getMedia().getUri());
+ done.run(_serializer.create());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ void handle(final OutputStream os, final InputStream is) throws IOException
+ {
+ RpcCallback done = new RpcCallback()
+ {
+ DataOutputStream dos = new DataOutputStream(os);
+
+ public void run (Message content)
+ {
+ try
+ {
+ byte[] array = _serializer.serialize((MediaContent) content);
+ dos.writeInt(array.length);
+ dos.write(array);
+ dos.flush();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ };
+ DataInputStream dis = new DataInputStream(is);
+ int index = dis.readInt();
+ MethodDescriptor method = getDescriptor().getMethods().get(index);
+ byte[] array = new byte[dis.readInt()];
+ dis.readFully(array);
+ Message request = getRequestPrototype(method).newBuilderForType().mergeFrom(array).build();
+ callMethod(method, null, request, done);
+ }
+}
diff --git a/jvm-serializers-protowar/src/main/java/org/protowar/ProtoWar.java b/jvm-serializers-protowar/src/main/java/org/protowar/ProtoWar.java
new file mode 100644
index 0000000..df39878
--- /dev/null
+++ b/jvm-serializers-protowar/src/main/java/org/protowar/ProtoWar.java
@@ -0,0 +1,50 @@
+package org.protowar;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Servlet implementation class ProtoWar
+ */
+public class ProtoWar extends HttpServlet
+{
+ private static final long serialVersionUID = 1L;
+
+ private ProtoServerHandler _handler = new ProtoServerHandler();
+
+ /**
+ * Default constructor.
+ */
+ public ProtoWar ()
+ {
+ }
+
+ /**
+ * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
+ */
+ protected void doGet (HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ doIt(request, response);
+ }
+
+ /**
+ * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
+ */
+ protected void doPost (HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ doIt(request, response);
+ }
+
+ private void doIt (HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ _handler.handle(response.getOutputStream(), request.getInputStream());
+ }
+
+}
diff --git a/jvm-serializers-protowar/src/test/java/jvm-serializers/protowar/AppTest.java b/jvm-serializers-protowar/src/test/java/jvm-serializers/protowar/AppTest.java
new file mode 100644
index 0000000..0413ea3
--- /dev/null
+++ b/jvm-serializers-protowar/src/test/java/jvm-serializers/protowar/AppTest.java
@@ -0,0 +1,38 @@
+package jvm-serializers.protowar;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+ extends TestCase
+{
+ /**
+ * Create the test case
+ *
+ * @param testName name of the test case
+ */
+ public AppTest( String testName )
+ {
+ super( testName );
+ }
+
+ /**
+ * @return the suite of tests being tested
+ */
+ public static Test suite()
+ {
+ return new TestSuite( AppTest.class );
+ }
+
+ /**
+ * Rigourous Test :-)
+ */
+ public void testApp()
+ {
+ assertTrue( true );
+ }
+}
diff --git a/jvm-serializers-scala_media_container/pom.xml b/jvm-serializers-scala_media_container/pom.xml
new file mode 100644
index 0000000..4c21a42
--- /dev/null
+++ b/jvm-serializers-scala_media_container/pom.xml
@@ -0,0 +1,61 @@
+
+
+ 4.0.0
+
+ jvm-serializers
+ jvm-serializers-parent
+ 1.0-SNAPSHOT
+
+ jvm-serializers
+ jvm-serializers-scala_media_container
+ 1.0-SNAPSHOT
+ jvm-serializers-scala_media_container
+ scala_media_container of jvm-serializers Terraformed... by jim@psychosynthintelligence... on x86_64 x86_64 GNU/Linux... for protowar,scala_media_container,tpc...
+ http://psychosynthintelligence/scala_media_container
+
+ HEAD
+
+
+
+
+ jvm-serializers-legacy
+ jvm-serializers-Repo
+ file://${basedir}/../src/main/repository
+ default
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.5
+ 1.5
+ true
+ 1024m
+ 1024m
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ javacc-maven-plugin
+ 2.4.1
+
+
+
+
diff --git a/jvm-serializers-scala_media_container/pom.xml.~1~ b/jvm-serializers-scala_media_container/pom.xml.~1~
new file mode 100644
index 0000000..a0c360f
--- /dev/null
+++ b/jvm-serializers-scala_media_container/pom.xml.~1~
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ jvm-serializers
+ jvm-serializers-parent
+ 1.0-SNAPSHOT
+
+ jvm-serializers
+ jvm-serializers-scala_media_container
+ 1.0-SNAPSHOT
+ jvm-serializers-scala_media_containerscala_media_container of jvm-serializers Terraformed... by jim@psychosynthintelligence... on x86_64 x86_64 GNU/Linux... for protowar,scala_media_container,tpc...
+ http://psychosynthintelligence/scala_media_containerHEAD
+ jvm-serializers-legacyjvm-serializers-Repo file://${basedir}/../src/main/repository defaultorg.apache.maven.pluginsmaven-compiler-plugin1.51.5true1024m1024morg.codehaus.mojojavacc-maven-plugin2.4.1
diff --git a/jvm-serializers-scala_media_container/src/main/java/jvm-serializers/scala_media_container/App.java b/jvm-serializers-scala_media_container/src/main/java/jvm-serializers/scala_media_container/App.java
new file mode 100644
index 0000000..57650a3
--- /dev/null
+++ b/jvm-serializers-scala_media_container/src/main/java/jvm-serializers/scala_media_container/App.java
@@ -0,0 +1,13 @@
+package jvm-serializers.scala_media_container;
+
+/**
+ * Hello world!
+ *
+ */
+public class App
+{
+ public static void main( String[] args )
+ {
+ System.out.println( "Hello World!" );
+ }
+}
diff --git a/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Image.scala b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Image.scala
new file mode 100644
index 0000000..d595466
--- /dev/null
+++ b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Image.scala
@@ -0,0 +1,4 @@
+package serializers.scala
+
+@serializable
+case class Image(uri: String, title: String, width: Int, height: Int, size: Size.Value)
diff --git a/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Media.scala b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Media.scala
new file mode 100644
index 0000000..4b14c03
--- /dev/null
+++ b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Media.scala
@@ -0,0 +1,23 @@
+package serializers.scala
+
+@serializable
+class Media (val uri: String, val title: String,
+ val width: Int, val height: Int, val format: String,
+ val duration: Long, val size: Long,
+ val bitrate: Int,
+ val copyright: Option[String],
+ val player: Player.Value){
+
+ def this(uri: String, title: String,
+ width: Int, height: Int, format: String,
+ duration: Long, size: Long,
+ bitrate: Int,
+ player: Player.Value) = this(uri, title, width, height, format, duration, size, bitrate, None, player)
+
+ private var _persons: List[String] = Nil
+ def persons = _persons
+
+ def addPerson(persons: String){
+ _persons = persons :: _persons
+ }
+}
diff --git a/jvm-serializers-scala_media_container/src/main/java/serializers/scala/MediaContent.scala b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/MediaContent.scala
new file mode 100644
index 0000000..d9d1fb8
--- /dev/null
+++ b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/MediaContent.scala
@@ -0,0 +1,10 @@
+package serializers.scala
+@serializable
+class MediaContent (val media: Media){
+ var _images: List[Image] = Nil
+ def images = _images
+
+ def addImage(image: Image){
+ _images = image :: _images
+ }
+}
diff --git a/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Player.scala b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Player.scala
new file mode 100644
index 0000000..a821281
--- /dev/null
+++ b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Player.scala
@@ -0,0 +1,5 @@
+package serializers.scala
+@serializable
+object Player extends Enumeration{
+ val JAVA, FLASH = Value
+}
diff --git a/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Runner.scala b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Runner.scala
new file mode 100644
index 0000000..8f08007
--- /dev/null
+++ b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Runner.scala
@@ -0,0 +1,14 @@
+package serializers.scala
+
+object Runner {
+ def main(args: Array[String]){
+ println("start")
+ var image1 = new Image("a", "b", 1, 2, Size.SMALL)
+ var image2 = new Image("a", "b", 1, 2, Size.SMALL)
+ var content = new MediaContent(null)
+ content.addImage(image1)
+ content.addImage(image2)
+
+ println("end")
+ }
+}
diff --git a/jvm-serializers-scala_media_container/src/main/java/serializers/scala/SbinarySerializerSupport.scala b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/SbinarySerializerSupport.scala
new file mode 100644
index 0000000..b82d4c7
--- /dev/null
+++ b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/SbinarySerializerSupport.scala
@@ -0,0 +1,91 @@
+package serializers.scala
+
+import sbinary.DefaultProtocol
+import sbinary.DefaultProtocol._
+
+object MyProtocol extends DefaultProtocol{
+// import sbinary.DefaultProtocol._
+
+// implicit val ImageFormat : Format[Image] = asProduct5(Image)(Image.unapply(_).get)
+ implicit object ImageFormat extends Format[Image]{
+ def reads(in : Input) = {
+ Image(
+ read[String](in),
+ read[String](in),
+ read[Int](in),
+ read[Int](in),
+ read[Size.Value](in)
+ )
+ }
+
+ def writes(out : Output, value : Image) = {
+ write[String](out, value.uri)
+ write[String](out, value.title)
+ write[Int](out, value.width)
+ write[Int](out, value.height)
+ write[Size.Value](out, value.size)
+ }
+ }
+
+ implicit object MediaFormat extends Format[Media]{
+ def reads(in : Input) = {
+ val back = new Media(
+ read[String](in),
+ read[String](in),
+ read[Int](in),
+ read[Int](in),
+ read[String](in),
+ read[Long](in),
+ read[Long](in),
+ read[Int](in),
+ read[Option[String]](in),
+ read[Player.Value](in)
+ )
+ read[List[String]](in).foreach(p => back.addPerson(p))
+ back
+ }
+
+ def writes(out : Output, value : Media) = {
+ write[String](out, value.uri)
+ write[String](out, value.title)
+ write[Int](out, value.width)
+ write[Int](out, value.height)
+ write[String](out, value.format)
+ write[Long](out, value.duration)
+ write[Long](out, value.size)
+ write[Int](out, value.bitrate)
+ write[Option[String]](out, value.copyright)
+ write[Player.Value](out, value.player)
+ write[List[String]](out, value.persons)
+ }
+ }
+
+// implicit object PlayerFormat extends Format[Player.Value] {
+// def reads(in : Input) = Player.Value(read[Int](in))
+// def writed(out : Output, value : Player.Value) = write[Int](out, value)
+// }
+
+ implicit val PlayerFormat = enumerationFormat[Player.Value](Player)
+ implicit val SizeFormat = enumerationFormat[Size.Value](Size)
+
+ implicit object MediaContentFormat extends Format[MediaContent]{
+ def reads(in : Input) = {
+ val back = new MediaContent(read[Media](in))
+ read[List[Image]](in).foreach(i => back.addImage(i))
+ back
+ }
+
+ def writes(out : Output, value : MediaContent) = {
+ write[Media](out, value.media)
+ write[List[Image]](out, value.images)
+ }
+ }
+
+}
+
+
+object SbinarySerializerSupport {
+ import MyProtocol._
+ def deserialize(array : Array[Byte]) : MediaContent = fromByteArray[MediaContent](array)
+ def serialize(content : MediaContent) : Array[Byte] = toByteArray(content)
+}
\ No newline at end of file
diff --git a/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Size.scala b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Size.scala
new file mode 100644
index 0000000..6108663
--- /dev/null
+++ b/jvm-serializers-scala_media_container/src/main/java/serializers/scala/Size.scala
@@ -0,0 +1,5 @@
+package serializers.scala
+@serializable
+object Size extends Enumeration{
+ val SMALL, LARGE = Value
+}
diff --git a/jvm-serializers-scala_media_container/src/test/java/jvm-serializers/scala_media_container/AppTest.java b/jvm-serializers-scala_media_container/src/test/java/jvm-serializers/scala_media_container/AppTest.java
new file mode 100644
index 0000000..923b6df
--- /dev/null
+++ b/jvm-serializers-scala_media_container/src/test/java/jvm-serializers/scala_media_container/AppTest.java
@@ -0,0 +1,38 @@
+package jvm-serializers.scala_media_container;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest
+ extends TestCase
+{
+ /**
+ * Create the test case
+ *
+ * @param testName name of the test case
+ */
+ public AppTest( String testName )
+ {
+ super( testName );
+ }
+
+ /**
+ * @return the suite of tests being tested
+ */
+ public static Test suite()
+ {
+ return new TestSuite( AppTest.class );
+ }
+
+ /**
+ * Rigourous Test :-)
+ */
+ public void testApp()
+ {
+ assertTrue( true );
+ }
+}
diff --git a/jvm-serializers-tpc/pom.xml b/jvm-serializers-tpc/pom.xml
new file mode 100644
index 0000000..6d37ec3
--- /dev/null
+++ b/jvm-serializers-tpc/pom.xml
@@ -0,0 +1,537 @@
+
+
+ 4.0.0
+
+ jvm-serializers
+ jvm-serializers-parent
+ 1.0-SNAPSHOT
+
+ jvm-serializers
+ jvm-serializers-tpc
+ 1.0-SNAPSHOT
+ jvm-serializers-tpc
+ tpc of jvm-serializers Terraformed... by jim@psychosynthintelligence... on x86_64 x86_64 GNU/Linux... for protowar,scala_media_container,tpc...
+ http://psychosynthintelligence/tpc
+
+ HEAD
+
+
+
+
+ jvm-serializers-legacy
+ jvm-serializers-Repo
+ file://${basedir}/../src/main/repository
+ default
+
+
+
+
+ org.hibernate
+ hibernate-entitymanager
+ 3.3.2.GA
+
+
+ javax.transaction
+ jta
+ 1.0.1B
+
+
+ org.mortbay.jetty
+ jetty-management
+ 6.1H.8
+
+
+ com.thoughtworks.xstream
+ xstream
+ 1.3
+
+
+ FastInfoset
+ deprecated
+ 1.2.6
+
+
+ aalto-gpl
+ aalto
+ 0.9.5
+
+
+ activemq-protobuf
+ activemq
+ 1.1-SNAPSHOT
+
+
+ activemq-util
+ activemq
+ 6.0-SNAPSHOT
+
+
+ argo
+ deprecated
+ 2.10
+
+
+ asm
+ deprecated
+ 4.0
+
+
+ asm-commons
+ asm
+ 3.2
+
+
+ avro
+ deprecated
+ 1.7.2
+
+
+ avro-compiler
+ avro
+ 1.7.2
+
+
+ avro-tools
+ avro
+ 1.7.2
+
+
+ bson4jackson
+ deprecated
+ 2.3.0
+
+
+ cakoose-util
+ deprecated
+ 1.0-SNAPSHOT
+
+
+ cks-core
+ deprecated
+ 1.0-SNAPSHOT
+
+
+ cks-text-reader
+ deprecated
+ 1.0-SNAPSHOT
+
+
+ cks-text-writer
+ deprecated
+ 1.0-SNAPSHOT
+
+
+ cks-tool
+ deprecated
+ 1.0-SNAPSHOT
+
+
+ commons-beanutils
+ commons
+ 1.8.3
+
+
+ commons-codec
+ commons
+ 1.3
+
+
+ commons-collections
+ commons
+ 3.2.1
+
+
+ commons-httpclient
+ commons
+ 3.1
+
+
+ commons-lang
+ commons
+ 2.4
+
+
+ commons-logging
+ commons
+ 1.1.1
+
+
+ dsl-clc
+ deprecated
+ 1.0-SNAPSHOT
+
+
+ dsl-json
+ dsl
+ 0.9.0
+
+
+ exi-exificient
+ exi
+ 0.9.1
+
+
+ ezmorph
+ deprecated
+ 1.0.6
+
+
+ fastjson
+ deprecated
+ 1.1.19
+
+
+ flexjson
+ deprecated
+ 2.1
+
+
+ fst
+ deprecated
+ 1.42
+
+
+ gson
+ deprecated
+ 2.2.2
+
+
+ hessian
+ deprecated
+ 4.0.7
+
+
+ jackson-all
+ jackson
+ 1.9.6
+
+
+ jackson-annotations
+ jackson
+ 2.5.0
+
+
+ jackson-core
+ jackson
+ 2.5.0
+
+
+ jackson-databind
+ jackson
+ 2.5.0
+
+
+ jackson-dataformat-avro
+ jackson-dataformat
+ 2.5.0
+
+
+ jackson-dataformat-cbor
+ jackson-dataformat
+ 2.5.0
+
+
+ jackson-dataformat-smile
+ jackson-dataformat
+ 2.5.0
+
+
+ jackson-dataformat-xml
+ jackson-dataformat
+ 2.5.0
+
+
+ jackson-dataformat-yaml
+ jackson-dataformat
+ 2.5.0
+
+
+ jackson-jr-objects
+ jackson-jr
+ 2.5.0
+
+
+ jackson-module-afterburner
+ jackson-module
+ 2.5.0
+
+
+ javassist
+ deprecated
+ 3.15.0-GA
+
+
+ javax.json
+ deprecated
+ 1.0-b06
+
+
+ javolution
+ deprecated
+ 5.5.1
+
+
+ jboss-marshalling-osgi
+ jboss-marshalling
+ 1.3.15.GA
+
+
+ jboss-serialization
+ jboss
+ 1.0.3.GA
+
+
+ jopt-simple
+ jopt
+ 3.2
+
+
+ json
+ deprecated
+ 0.19-tpc
+
+
+ json-lib
+ json
+ 2.4-jdk15
+
+
+ json-smart
+ json
+ 1.0.8
+
+
+ json.org-ref
+ json.org
+ 2011.06.21
+
+
+ json_simple
+ deprecated
+ 1.1
+
+
+ jsonij
+ deprecated
+ 0.2.7
+
+
+ jsonpath
+ deprecated
+ 2011.06.23
+
+
+ kryo
+ deprecated
+ 2.23.0
+
+
+ libthrift
+ deprecated
+ 1.0-SNAPSHOT
+
+
+ log4j
+ deprecated
+ 1.2.8
+
+
+ minlog-none
+ minlog
+ 1.2
+
+
+ mongo
+ deprecated
+ 2.4
+
+
+ msgpack
+ deprecated
+ 0.6.9
+
+
+ objenesis
+ deprecated
+ 1.2
+
+
+ obser
+ deprecated
+ 0.9.0-SNAPSHOT
+
+
+ paranamer
+ deprecated
+ 1.5
+
+
+ protobuf-java
+ protobuf
+ 2.3.0
+
+
+ protostuff-api
+ protostuff
+ 1.0.1
+
+
+ protostuff-collectionschema
+ protostuff
+ 1.0.1
+
+
+ protostuff-compiler
+ protostuff
+ 1.0.1-jarjar
+
+
+ protostuff-core
+ protostuff
+ 1.0.1
+
+
+ protostuff-json
+ protostuff
+ 1.0.1
+
+
+ protostuff-runtime
+ protostuff
+ 1.0.1
+
+
+ protostuff-xml
+ protostuff
+ 1.0.1
+
+
+ reflectasm
+ deprecated
+ 1.05
+
+
+ sbinary_2.11
+ deprecated
+ 0.4.3-SNAPSHOT
+
+
+ scala-library_2.11.2
+ deprecated
+ 1.0-SNAPSHOT
+
+
+ scala-reflect_2.11.2
+ deprecated
+ 1.0-SNAPSHOT
+
+
+ scala-xml_2.11
+ scala
+ 1.0.2
+
+
+ slf4j-api
+ slf4j
+ 1.5.10
+
+
+ slf4j-nop
+ slf4j
+ 1.5.10
+
+
+ snakeyaml
+ deprecated
+ 1.1
+
+
+ stax-api
+ stax
+ 1.0.1
+
+
+ stax2-api
+ stax2
+ 3.0.1
+
+
+ stephenerialization
+ deprecated
+ 3.0.0
+
+
+ svenson
+ deprecated
+ 1.4.0
+
+
+ trove
+ deprecated
+ 1.0.2
+
+
+ velocity
+ deprecated
+ 1.7-dep
+
+
+ velocity
+ deprecated
+ 1.7
+
+
+ wobly-core
+ wobly
+ 1.0
+
+
+ woodstox-core-asl
+ woodstox-core
+ 4.0.7
+
+
+ xpp3_min
+ deprecated
+ 1.1.4c
+
+
+ xstream
+ deprecated
+ 1.3.1
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.5
+ 1.5
+ true
+ 1024m
+ 1024m
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ javacc-maven-plugin
+ 2.4.1
+
+
+
+
diff --git a/jvm-serializers-tpc/pom.xml.~1~ b/jvm-serializers-tpc/pom.xml.~1~
new file mode 100644
index 0000000..ad18c03
--- /dev/null
+++ b/jvm-serializers-tpc/pom.xml.~1~
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ jvm-serializers
+ jvm-serializers-parent
+ 1.0-SNAPSHOT
+
+ jvm-serializers
+ jvm-serializers-tpc
+ 1.0-SNAPSHOT
+ jvm-serializers-tpctpc of jvm-serializers Terraformed... by jim@psychosynthintelligence... on x86_64 x86_64 GNU/Linux... for protowar,scala_media_container,tpc...
+ http://psychosynthintelligence/tpcHEAD
+ jvm-serializers-legacyjvm-serializers-Repo file://${basedir}/../src/main/repository defaultorg.hibernatehibernate-entitymanager3.3.2.GAjavax.transactionjta1.0.1Borg.mortbay.jettyjetty-management6.1H.8com.thoughtworks.xstreamxstream1.3 FastInfoset deprecated 1.2.6 aalto-gpl aalto 0.9.5 activemq-protobuf activemq 1.1-SNAPSHOT activemq-util activemq 6.0-SNAPSHOT argo deprecated 2.10 asm deprecated 4.0 asm-commons asm 3.2 avro deprecated 1.7.2 avro-compiler avro 1.7.2 avro-tools avro 1.7.2 bson4jackson deprecated 2.3.0 cakoose-util deprecated 1.0-SNAPSHOT cks-core deprecated 1.0-SNAPSHOT cks-text-reader deprecated 1.0-SNAPSHOT cks-text-writer deprecated 1.0-SNAPSHOT cks-tool deprecated 1.0-SNAPSHOT commons-beanutils commons 1.8.3 commons-codec commons 1.3 commons-collections commons 3.2.1 commons-httpclient commons 3.1 commons-lang commons 2.4 commons-logging commons 1.1.1 dsl-clc deprecated 1.0-SNAPSHOT dsl-json dsl 0.9.0 exi-exificient exi 0.9.1 ezmorph deprecated 1.0.6 fastjson deprecated 1.1.19 flexjson deprecated 2.1 fst deprecated 1.42 gson deprecated 2.2.2 hessian deprecated 4.0.7 jackson-all jackson 1.9.6 jackson-annotations jackson 2.5.0 jackson-core jackson 2.5.0 jackson-databind jackson 2.5.0 jackson-dataformat-avro jackson-dataformat 2.5.0 jackson-dataformat-cbor jackson-dataformat 2.5.0 jackson-dataformat-smile jackson-dataformat 2.5.0 jackson-dataformat-xml jackson-dataformat 2.5.0 jackson-dataformat-yaml jackson-dataformat 2.5.0 jackson-jr-objects jackson-jr 2.5.0 jackson-module-afterburner jackson-module 2.5.0 javassist deprecated 3.15.0-GA javax.json deprecated 1.0-b06 javolution deprecated 5.5.1 jboss-marshalling-osgi jboss-marshalling 1.3.15.GA jboss-serialization jboss 1.0.3.GA jopt-simple jopt 3.2 json deprecated 0.19-tpc json-lib json 2.4-jdk15 json-smart json 1.0.8 json.org-ref json.org 2011.06.21 json_simple deprecated 1.1 jsonij deprecated 0.2.7 jsonpath deprecated 2011.06.23 kryo deprecated 2.23.0 libthrift deprecated 1.0-SNAPSHOT log4j deprecated 1.2.8 minlog-none minlog 1.2 mongo deprecated 2.4 msgpack deprecated 0.6.9 objenesis deprecated 1.2 obser deprecated 0.9.0-SNAPSHOT paranamer deprecated 1.5 protobuf-java protobuf 2.3.0 protostuff-api protostuff 1.0.1 protostuff-collectionschema protostuff 1.0.1 protostuff-compiler protostuff 1.0.1-jarjar protostuff-core protostuff 1.0.1 protostuff-json protostuff 1.0.1 protostuff-runtime protostuff 1.0.1 protostuff-xml protostuff 1.0.1 reflectasm deprecated 1.05 sbinary_2.11 deprecated 0.4.3-SNAPSHOT scala-library_2.11.2 deprecated 1.0-SNAPSHOT scala-reflect_2.11.2 deprecated 1.0-SNAPSHOT scala-xml_2.11 scala 1.0.2 slf4j-api slf4j 1.5.10 slf4j-nop slf4j 1.5.10 snakeyaml deprecated 1.1 stax-api stax 1.0.1 stax2-api stax2 3.0.1 stephenerialization deprecated 3.0.0 svenson deprecated 1.4.0 trove deprecated 1.0.2 velocity deprecated 1.7-dep velocity deprecated 1.7 wobly-core wobly 1.0 woodstox-core-asl woodstox-core 4.0.7 xpp3_min deprecated 1.1.4c xstream deprecated 1.3.1 org.apache.maven.pluginsmaven-compiler-plugin1.51.5true1024m1024morg.codehaus.mojojavacc-maven-plugin2.4.1
diff --git a/jvm-serializers-tpc/src/main/java/com/google/protobuf/JsonFormat.java b/jvm-serializers-tpc/src/main/java/com/google/protobuf/JsonFormat.java
new file mode 100644
index 0000000..a0a8305
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/com/google/protobuf/JsonFormat.java
@@ -0,0 +1,1395 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.CharBuffer;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.ExtensionRegistry;
+import com.google.protobuf.Message;
+import com.google.protobuf.UnknownFieldSet;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+
+/**
+ * Copied from http://code.google.com/p/protobuf/issues/detail?id=82
+ *
+ * Provide ascii text parsing and formatting support for proto2 instances. The implementation
+ * largely follows google/protobuf/text_format.cc.
+ *
+ * @author aantonov@orbitz.com Alex Antonov
+ *
+ * Based on the original code by:
+ * @author wenboz@google.com Wenbo Zhu
+ * @author kenton@google.com Kenton Varda
+ */
+@SuppressWarnings({"serial"})
+public final class JsonFormat {
+
+ /**
+ * Outputs a textual representation of the Protocol Message supplied into the parameter output.
+ * (This representation is the new version of the classic "ProtocolPrinter" output from the
+ * original Protocol Buffer system)
+ */
+ public static void print(Message message, Appendable output) throws IOException {
+ JsonGenerator generator = new JsonGenerator(output);
+ generator.print("{");
+ print(message, generator);
+ generator.print("}");
+ }
+
+ /**
+ * Outputs a textual representation of {@code fields} to {@code output}.
+ */
+ public static void print(UnknownFieldSet fields, Appendable output) throws IOException {
+ JsonGenerator generator = new JsonGenerator(output);
+ generator.print("{");
+ printUnknownFields(fields, generator);
+ generator.print("}");
+ }
+
+ /**
+ * Like {@code print()}, but writes directly to a {@code String} and returns it.
+ */
+ public static String printToString(Message message) {
+ try {
+ StringBuilder text = new StringBuilder();
+ print(message, text);
+ return text.toString();
+ } catch (IOException e) {
+ throw new RuntimeException("Writing to a StringBuilder threw an IOException (should never "
+ + "happen).",
+ e);
+ }
+ }
+
+ /**
+ * Like {@code print()}, but writes directly to a {@code String} and returns it.
+ */
+ public static String printToString(UnknownFieldSet fields) {
+ try {
+ StringBuilder text = new StringBuilder();
+ print(fields, text);
+ return text.toString();
+ } catch (IOException e) {
+ throw new RuntimeException("Writing to a StringBuilder threw an IOException (should never "
+ + "happen).",
+ e);
+ }
+ }
+
+ private static void print(Message message, JsonGenerator generator) throws IOException {
+
+ for (Iterator> iter = message.getAllFields().entrySet().iterator(); iter.hasNext();) {
+ Map.Entry field = iter.next();
+ printField(field.getKey(), field.getValue(), generator);
+ if (iter.hasNext()) {
+ generator.print(",");
+ }
+ }
+ printUnknownFields(message.getUnknownFields(), generator);
+ }
+
+ public static void printField(FieldDescriptor field, Object value, JsonGenerator generator) throws IOException {
+
+ printSingleField(field, value, generator);
+ }
+
+ private static void printSingleField(FieldDescriptor field,
+ Object value,
+ JsonGenerator generator) throws IOException {
+ if (field.isExtension()) {
+ generator.print("[");
+ generator.print("\"");
+ // We special-case MessageSet elements for compatibility with proto1.
+ if (field.getContainingType().getOptions().getMessageSetWireFormat()
+ && (field.getType() == FieldDescriptor.Type.MESSAGE) && (field.isOptional())
+ // object equality
+ && (field.getExtensionScope() == field.getMessageType())) {
+ generator.print(field.getMessageType().getFullName());
+ } else {
+ generator.print(field.getFullName());
+ }
+ generator.print("\"");
+ generator.print("]");
+ } else {
+ generator.print("\"");
+ if (field.getType() == FieldDescriptor.Type.GROUP) {
+ // Groups must be serialized with their original capitalization.
+ generator.print(field.getMessageType().getName());
+ } else {
+ generator.print(field.getName());
+ }
+ generator.print("\"");
+ }
+
+ // Done with the name, on to the value
+
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ generator.print(": ");
+ generator.indent();
+ } else {
+ generator.print(": ");
+ }
+
+
+ if (field.isRepeated()) {
+ // Repeated field. Print each element.
+ generator.print("[");
+ for (Iterator> iter = ((List>) value).iterator(); iter.hasNext();) {
+ printFieldValue(field, iter.next(), generator);
+ if (iter.hasNext()) {
+ generator.print(",");
+ }
+ }
+ generator.print("]");
+ } else {
+ printFieldValue(field, value, generator);
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ generator.outdent();
+ }
+ }
+ }
+
+ private static void printFieldValue(FieldDescriptor field, Object value, JsonGenerator generator) throws IOException {
+ switch (field.getType()) {
+ case INT32:
+ case INT64:
+ case SINT32:
+ case SINT64:
+ case SFIXED32:
+ case SFIXED64:
+ case FLOAT:
+ case DOUBLE:
+ case BOOL:
+ // Good old toString() does what we want for these types.
+ generator.print(value.toString());
+ break;
+
+ case UINT32:
+ case FIXED32:
+ generator.print(unsignedToString((Integer) value));
+ break;
+
+ case UINT64:
+ case FIXED64:
+ generator.print(unsignedToString((Long) value));
+ break;
+
+ case STRING:
+ generator.print("\"");
+ generator.print(escapeText((String) value));
+ generator.print("\"");
+ break;
+
+ case BYTES: {
+ generator.print("\"");
+ generator.print(escapeBytes((ByteString) value));
+ generator.print("\"");
+ break;
+ }
+
+ case ENUM: {
+ generator.print("\"");
+ generator.print(((EnumValueDescriptor) value).getName());
+ generator.print("\"");
+ break;
+ }
+
+ case MESSAGE:
+ case GROUP:
+ generator.print("{");
+ print((Message) value, generator);
+ generator.print("}");
+ break;
+ }
+ }
+
+ private static void printUnknownFields(UnknownFieldSet unknownFields, JsonGenerator generator) throws IOException {
+ for (Map.Entry entry : unknownFields.asMap().entrySet()) {
+// String prefix = entry.getKey().toString() + ": ";
+ UnknownFieldSet.Field field = entry.getValue();
+
+ for (long value : field.getVarintList()) {
+ generator.print("\"");
+ generator.print(entry.getKey().toString());
+ generator.print("\"");
+ generator.print(": ");
+ generator.print(unsignedToString(value));
+ generator.print("\n");
+ }
+ for (int value : field.getFixed32List()) {
+ generator.print("\"");
+ generator.print(entry.getKey().toString());
+ generator.print("\"");
+ generator.print(": ");
+ generator.print(String.format((Locale) null, "0x%08x", value));
+ generator.print("\n");
+ }
+ for (long value : field.getFixed64List()) {
+ generator.print(entry.getKey().toString());
+ generator.print(": ");
+ generator.print(String.format((Locale) null, "0x%016x", value));
+ generator.print("\n");
+ }
+ for (ByteString value : field.getLengthDelimitedList()) {
+ generator.print(entry.getKey().toString());
+ generator.print(": \"");
+ generator.print(escapeBytes(value));
+ generator.print("\"\n");
+ }
+ for (UnknownFieldSet value : field.getGroupList()) {
+ generator.print(entry.getKey().toString());
+ generator.print(" {\n");
+ generator.indent();
+ printUnknownFields(value, generator);
+ generator.outdent();
+ generator.print("}\n");
+ }
+ }
+ }
+
+ /**
+ * Convert an unsigned 32-bit integer to a string.
+ */
+ private static String unsignedToString(int value) {
+ if (value >= 0) {
+ return Integer.toString(value);
+ } else {
+ return Long.toString((value) & 0x00000000FFFFFFFFL);
+ }
+ }
+
+ /**
+ * Convert an unsigned 64-bit integer to a string.
+ */
+ private static String unsignedToString(long value) {
+ if (value >= 0) {
+ return Long.toString(value);
+ } else {
+ // Pull off the most-significant bit so that BigInteger doesn't think
+ // the number is negative, then set it again using setBit().
+ return BigInteger.valueOf(value & 0x7FFFFFFFFFFFFFFFL).setBit(63).toString();
+ }
+ }
+
+ /**
+ * An inner class for writing text to the output stream.
+ */
+ static private final class JsonGenerator {
+
+ Appendable output;
+ boolean atStartOfLine = true;
+ StringBuilder indent = new StringBuilder();
+
+ public JsonGenerator(Appendable output) {
+ this.output = output;
+ }
+
+ /**
+ * Indent text by two spaces. After calling Indent(), two spaces will be inserted at the
+ * beginning of each line of text. Indent() may be called multiple times to produce deeper
+ * indents.
+ */
+ public void indent() {
+ indent.append(" ");
+ }
+
+ /**
+ * Reduces the current indent level by two spaces, or crashes if the indent level is zero.
+ */
+ public void outdent() {
+ int length = indent.length();
+ if (length == 0) {
+ throw new IllegalArgumentException(" Outdent() without matching Indent().");
+ }
+ indent.delete(length - 2, length);
+ }
+
+ /**
+ * Print text to the output stream.
+ */
+ public void print(CharSequence text) throws IOException {
+ int size = text.length();
+ int pos = 0;
+
+ for (int i = 0; i < size; i++) {
+ if (text.charAt(i) == '\n') {
+ write(text.subSequence(pos, size), i - pos + 1);
+ pos = i + 1;
+ atStartOfLine = true;
+ }
+ }
+ write(text.subSequence(pos, size), size - pos);
+ }
+
+ /**
+ * Appends text to the output stream without starting a new line after it.
+ */
+ @SuppressWarnings("unused")
+ public void append(CharSequence text) throws IOException {
+ int size = text.length();
+ int pos = 0;
+
+ for (int i = 0; i < size; i++) {
+ if (text.charAt(i) == '\n') {
+ write(text.subSequence(pos, size), i - pos + 1);
+ pos = i + 1;
+ atStartOfLine = false;
+ }
+ }
+ write(text.subSequence(pos, size), size - pos);
+ }
+
+ private void write(CharSequence data, int size) throws IOException {
+ if (size == 0) {
+ return;
+ }
+ if (atStartOfLine) {
+ atStartOfLine = false;
+ output.append(indent);
+ }
+ output.append(data);
+ }
+ }
+
+ // =================================================================
+ // Parsing
+
+ /**
+ * Represents a stream of tokens parsed from a {@code String}.
+ *
+ *
+ * The Java standard library provides many classes that you might think would be useful for
+ * implementing this, but aren't. For example:
+ *
+ *
+ *
{@code java.io.StreamTokenizer}: This almost does what we want -- or, at least, something
+ * that would get us close to what we want -- except for one fatal flaw: It automatically
+ * un-escapes strings using Java escape sequences, which do not include all the escape sequences
+ * we need to support (e.g. '\x').
+ *
{@code java.util.Scanner}: This seems like a great way at least to parse regular
+ * expressions out of a stream (so we wouldn't have to load the entire input into a single
+ * string before parsing). Sadly, {@code Scanner} requires that tokens be delimited with some
+ * delimiter. Thus, although the text "foo:" should parse to two tokens ("foo" and ":"), {@code
+ * Scanner} would recognize it only as a single token. Furthermore, {@code Scanner} provides no
+ * way to inspect the contents of delimiters, making it impossible to keep track of line and
+ * column numbers.
+ *
+ *
+ *
+ * Luckily, Java's regular expression support does manage to be useful to us. (Barely: We need
+ * {@code Matcher.usePattern()}, which is new in Java 1.5.) So, we can use that, at least.
+ * Unfortunately, this implies that we need to have the entire input in one contiguous string.
+ */
+ private static final class Tokenizer {
+
+ private final CharSequence text;
+ private final Matcher matcher;
+ private String currentToken;
+
+ // The character index within this.text at which the current token begins.
+ private int pos = 0;
+
+ // The line and column numbers of the current token.
+ private int line = 0;
+ private int column = 0;
+
+ // The line and column numbers of the previous token (allows throwing
+ // errors *after* consuming).
+ private int previousLine = 0;
+ private int previousColumn = 0;
+
+ private static Pattern WHITESPACE = Pattern.compile("(\\s|(#.*$))+", Pattern.MULTILINE);
+ private static Pattern TOKEN = Pattern.compile("[a-zA-Z_][0-9a-zA-Z_+-]*|" + // an
+ // identifier
+ "[0-9+-][0-9a-zA-Z_.+-]*|" + // a number
+ "\"([^\"\n\\\\]|\\\\.)*(\"|\\\\?$)|" + // a
+ // double-quoted
+ // string
+ "\'([^\"\n\\\\]|\\\\.)*(\'|\\\\?$)", // a
+ // single-quoted
+ // string
+ Pattern.MULTILINE);
+
+ private static Pattern DOUBLE_INFINITY = Pattern.compile("-?inf(inity)?",
+ Pattern.CASE_INSENSITIVE);
+ private static Pattern FLOAT_INFINITY = Pattern.compile("-?inf(inity)?f?",
+ Pattern.CASE_INSENSITIVE);
+ private static Pattern FLOAT_NAN = Pattern.compile("nanf?", Pattern.CASE_INSENSITIVE);
+
+ /**
+ * Construct a tokenizer that parses tokens from the given text.
+ */
+ public Tokenizer(CharSequence text) {
+ this.text = text;
+ matcher = WHITESPACE.matcher(text);
+ skipWhitespace();
+ nextToken();
+ }
+
+ /**
+ * Are we at the end of the input?
+ */
+ public boolean atEnd() {
+ return currentToken.length() == 0;
+ }
+
+ /**
+ * Advance to the next token.
+ */
+ public void nextToken() {
+ previousLine = line;
+ previousColumn = column;
+
+ // Advance the line counter to the current position.
+ while (pos < matcher.regionStart()) {
+ if (text.charAt(pos) == '\n') {
+ ++line;
+ column = 0;
+ } else {
+ ++column;
+ }
+ ++pos;
+ }
+
+ // Match the next token.
+ if (matcher.regionStart() == matcher.regionEnd()) {
+ // EOF
+ currentToken = "";
+ } else {
+ matcher.usePattern(TOKEN);
+ if (matcher.lookingAt()) {
+ currentToken = matcher.group();
+ matcher.region(matcher.end(), matcher.regionEnd());
+ } else {
+ // Take one character.
+ currentToken = String.valueOf(text.charAt(pos));
+ matcher.region(pos + 1, matcher.regionEnd());
+ }
+
+ skipWhitespace();
+ }
+ }
+
+ /**
+ * Skip over any whitespace so that the matcher region starts at the next token.
+ */
+ private void skipWhitespace() {
+ matcher.usePattern(WHITESPACE);
+ if (matcher.lookingAt()) {
+ matcher.region(matcher.end(), matcher.regionEnd());
+ }
+ }
+
+ /**
+ * If the next token exactly matches {@code token}, consume it and return {@code true}.
+ * Otherwise, return {@code false} without doing anything.
+ */
+ public boolean tryConsume(String token) {
+ if (currentToken.equals(token)) {
+ nextToken();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * If the next token exactly matches {@code token}, consume it. Otherwise, throw a
+ * {@link ParseException}.
+ */
+ public void consume(String token) throws ParseException {
+ if (!tryConsume(token)) {
+ throw parseException("Expected \"" + token + "\".");
+ }
+ }
+
+ /**
+ * Returns {@code true} if the next token is an integer, but does not consume it.
+ */
+ public boolean lookingAtInteger() {
+ if (currentToken.length() == 0) {
+ return false;
+ }
+
+ char c = currentToken.charAt(0);
+ return (('0' <= c) && (c <= '9')) || (c == '-') || (c == '+');
+ }
+
+ /**
+ * If the next token is an identifier, consume it and return its value. Otherwise, throw a
+ * {@link ParseException}.
+ */
+ public String consumeIdentifier() throws ParseException {
+ for (int i = 0; i < currentToken.length(); i++) {
+ char c = currentToken.charAt(i);
+ if ((('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'))
+ || (('0' <= c) && (c <= '9')) || (c == '_') || (c == '.') || (c == '"')) {
+ // OK
+ } else {
+ throw parseException("Expected identifier. -" + c);
+ }
+ }
+
+ String result = currentToken;
+ // Need to clean-up result to remove quotes of any kind
+ result = result.replaceAll("\"|'", "");
+ nextToken();
+ return result;
+ }
+
+ /**
+ * If the next token is a 32-bit signed integer, consume it and return its value. Otherwise,
+ * throw a {@link ParseException}.
+ */
+ public int consumeInt32() throws ParseException {
+ try {
+ int result = parseInt32(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw integerParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a 32-bit unsigned integer, consume it and return its value.
+ * Otherwise, throw a {@link ParseException}.
+ */
+ public int consumeUInt32() throws ParseException {
+ try {
+ int result = parseUInt32(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw integerParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a 64-bit signed integer, consume it and return its value. Otherwise,
+ * throw a {@link ParseException}.
+ */
+ public long consumeInt64() throws ParseException {
+ try {
+ long result = parseInt64(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw integerParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a 64-bit unsigned integer, consume it and return its value.
+ * Otherwise, throw a {@link ParseException}.
+ */
+ public long consumeUInt64() throws ParseException {
+ try {
+ long result = parseUInt64(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw integerParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a double, consume it and return its value. Otherwise, throw a
+ * {@link ParseException}.
+ */
+ public double consumeDouble() throws ParseException {
+ // We need to parse infinity and nan separately because
+ // Double.parseDouble() does not accept "inf", "infinity", or "nan".
+ if (DOUBLE_INFINITY.matcher(currentToken).matches()) {
+ boolean negative = currentToken.startsWith("-");
+ nextToken();
+ return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if (currentToken.equalsIgnoreCase("nan")) {
+ nextToken();
+ return Double.NaN;
+ }
+ try {
+ double result = Double.parseDouble(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw floatParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a float, consume it and return its value. Otherwise, throw a
+ * {@link ParseException}.
+ */
+ public float consumeFloat() throws ParseException {
+ // We need to parse infinity and nan separately because
+ // Float.parseFloat() does not accept "inf", "infinity", or "nan".
+ if (FLOAT_INFINITY.matcher(currentToken).matches()) {
+ boolean negative = currentToken.startsWith("-");
+ nextToken();
+ return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+ }
+ if (FLOAT_NAN.matcher(currentToken).matches()) {
+ nextToken();
+ return Float.NaN;
+ }
+ try {
+ float result = Float.parseFloat(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw floatParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a boolean, consume it and return its value. Otherwise, throw a
+ * {@link ParseException}.
+ */
+ public boolean consumeBoolean() throws ParseException {
+ if (currentToken.equals("true")) {
+ nextToken();
+ return true;
+ } else if (currentToken.equals("false")) {
+ nextToken();
+ return false;
+ } else {
+ throw parseException("Expected \"true\" or \"false\".");
+ }
+ }
+
+ /**
+ * If the next token is a string, consume it and return its (unescaped) value. Otherwise,
+ * throw a {@link ParseException}.
+ */
+ public String consumeString() throws ParseException {
+ return consumeByteString().toStringUtf8();
+ }
+
+ /**
+ * If the next token is a string, consume it, unescape it as a
+ * {@link com.google.protobuf.ByteString}, and return it. Otherwise, throw a
+ * {@link ParseException}.
+ */
+ public ByteString consumeByteString() throws ParseException {
+ char quote = currentToken.length() > 0 ? currentToken.charAt(0) : '\0';
+ if ((quote != '\"') && (quote != '\'')) {
+ throw parseException("Expected string.");
+ }
+
+ if ((currentToken.length() < 2)
+ || (currentToken.charAt(currentToken.length() - 1) != quote)) {
+ throw parseException("String missing ending quote.");
+ }
+
+ try {
+ String escaped = currentToken.substring(1, currentToken.length() - 1);
+ ByteString result = unescapeBytes(escaped);
+ nextToken();
+ return result;
+ } catch (InvalidEscapeSequence e) {
+ throw parseException(e.getMessage());
+ }
+ }
+
+ /**
+ * Returns a {@link ParseException} with the current line and column numbers in the
+ * description, suitable for throwing.
+ */
+ public ParseException parseException(String description) {
+ // Note: People generally prefer one-based line and column numbers.
+ return new ParseException((line + 1) + ":" + (column + 1) + ": " + description);
+ }
+
+ /**
+ * Returns a {@link ParseException} with the line and column numbers of the previous token
+ * in the description, suitable for throwing.
+ */
+ public ParseException parseExceptionPreviousToken(String description) {
+ // Note: People generally prefer one-based line and column numbers.
+ return new ParseException((previousLine + 1) + ":" + (previousColumn + 1) + ": "
+ + description);
+ }
+
+ /**
+ * Constructs an appropriate {@link ParseException} for the given {@code
+ * NumberFormatException} when trying to parse an integer.
+ */
+ private ParseException integerParseException(NumberFormatException e) {
+ return parseException("Couldn't parse integer: " + e.getMessage());
+ }
+
+ /**
+ * Constructs an appropriate {@link ParseException} for the given {@code
+ * NumberFormatException} when trying to parse a float or double.
+ */
+ private ParseException floatParseException(NumberFormatException e) {
+ return parseException("Couldn't parse number: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Thrown when parsing an invalid text format message.
+ */
+ public static class ParseException extends IOException {
+
+ public ParseException(String message) {
+ super(message);
+ }
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+ */
+ public static void merge(Readable input, Message.Builder builder) throws ParseException,
+ IOException {
+ JsonFormat.merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+ */
+ public static void merge(CharSequence input, Message.Builder builder) throws ParseException {
+ merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+ * Extensions will be recognized if they are registered in {@code extensionRegistry}.
+ */
+ public static void merge(Readable input,
+ ExtensionRegistry extensionRegistry,
+ Message.Builder builder) throws ParseException, IOException {
+ // Read the entire input to a String then parse that.
+
+ // If StreamTokenizer were not quite so crippled, or if there were a kind
+ // of Reader that could read in chunks that match some particular regex,
+ // or if we wanted to write a custom Reader to tokenize our stream, then
+ // we would not have to read to one big String. Alas, none of these is
+ // the case. Oh well.
+
+ merge(toStringBuilder(input), extensionRegistry, builder);
+ }
+
+ private static final int BUFFER_SIZE = 4096;
+
+ // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
+ // overhead is worthwhile
+ private static StringBuilder toStringBuilder(Readable input) throws IOException {
+ StringBuilder text = new StringBuilder();
+ CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE);
+ while (true) {
+ int n = input.read(buffer);
+ if (n == -1) {
+ break;
+ }
+ buffer.flip();
+ text.append(buffer, 0, n);
+ }
+ return text;
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
+ * Extensions will be recognized if they are registered in {@code extensionRegistry}.
+ */
+ public static void merge(CharSequence input,
+ ExtensionRegistry extensionRegistry,
+ Message.Builder builder) throws ParseException {
+ Tokenizer tokenizer = new Tokenizer(input);
+
+ // Based on the state machine @ http://json.org/
+
+ tokenizer.consume("{"); // Needs to happen when the object starts.
+ while (!tokenizer.tryConsume("}")) { // Continue till the object is done
+ mergeField(tokenizer, extensionRegistry, builder);
+ }
+ }
+
+ /**
+ * Parse a single field from {@code tokenizer} and merge it into {@code builder}. If a ',' is
+ * detected after the field ends, the next field will be parsed automatically
+ */
+ private static void mergeField(Tokenizer tokenizer,
+ ExtensionRegistry extensionRegistry,
+ Message.Builder builder) throws ParseException {
+ FieldDescriptor field;
+ Descriptor type = builder.getDescriptorForType();
+ ExtensionRegistry.ExtensionInfo extension = null;
+
+ if (tokenizer.tryConsume("[")) {
+ // An extension.
+ StringBuilder name = new StringBuilder(tokenizer.consumeIdentifier());
+ while (tokenizer.tryConsume(".")) {
+ name.append(".");
+ name.append(tokenizer.consumeIdentifier());
+ }
+
+ extension = extensionRegistry.findExtensionByName(name.toString());
+
+ if (extension == null) {
+ throw tokenizer.parseExceptionPreviousToken("Extension \""
+ + name
+ + "\" not found in the ExtensionRegistry.");
+ } else if (extension.descriptor.getContainingType() != type) {
+ throw tokenizer.parseExceptionPreviousToken("Extension \"" + name
+ + "\" does not extend message type \""
+ + type.getFullName() + "\".");
+ }
+
+ tokenizer.consume("]");
+
+ field = extension.descriptor;
+ } else {
+ String name = tokenizer.consumeIdentifier();
+ field = type.findFieldByName(name);
+
+ // Group names are expected to be capitalized as they appear in the
+ // .proto file, which actually matches their type names, not their field
+ // names.
+ if (field == null) {
+ // Explicitly specify US locale so that this code does not break when
+ // executing in Turkey.
+ String lowerName = name.toLowerCase(Locale.US);
+ field = type.findFieldByName(lowerName);
+ // If the case-insensitive match worked but the field is NOT a group,
+ if ((field != null) && (field.getType() != FieldDescriptor.Type.GROUP)) {
+ field = null;
+ }
+ }
+ // Again, special-case group names as described above.
+ if ((field != null) && (field.getType() == FieldDescriptor.Type.GROUP)
+ && !field.getMessageType().getName().equals(name)) {
+ field = null;
+ }
+
+ if (field == null) {
+ throw tokenizer.parseExceptionPreviousToken("Message type \"" + type.getFullName()
+ + "\" has no field named \"" + name
+ + "\".");
+ }
+ }
+
+ tokenizer.consume(":");
+ boolean array = tokenizer.tryConsume("[");
+
+ if (array) {
+ while (!tokenizer.tryConsume("]")) {
+ handleValue(tokenizer, extensionRegistry, builder, field, extension);
+ tokenizer.tryConsume(",");
+ }
+ } else {
+ handleValue(tokenizer, extensionRegistry, builder, field, extension);
+ }
+
+ if (tokenizer.tryConsume(",")) {
+ // Continue with the next field
+ mergeField(tokenizer, extensionRegistry, builder);
+ }
+ }
+
+ private static void handleValue(Tokenizer tokenizer,
+ ExtensionRegistry extensionRegistry,
+ Message.Builder builder,
+ FieldDescriptor field,
+ ExtensionRegistry.ExtensionInfo extension) throws ParseException {
+
+ Object value = null;
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ value = handleObject(tokenizer, extensionRegistry, builder, field, extension);
+ } else {
+ value = handlePrimitive(tokenizer, field);
+ }
+ if (field.isRepeated()) {
+ builder.addRepeatedField(field, value);
+ } else {
+ builder.setField(field, value);
+ }
+ }
+
+ private static Object handlePrimitive(Tokenizer tokenizer, FieldDescriptor field) throws ParseException {
+ Object value = null;
+ switch (field.getType()) {
+ case INT32:
+ case SINT32:
+ case SFIXED32:
+ value = tokenizer.consumeInt32();
+ break;
+
+ case INT64:
+ case SINT64:
+ case SFIXED64:
+ value = tokenizer.consumeInt64();
+ break;
+
+ case UINT32:
+ case FIXED32:
+ value = tokenizer.consumeUInt32();
+ break;
+
+ case UINT64:
+ case FIXED64:
+ value = tokenizer.consumeUInt64();
+ break;
+
+ case FLOAT:
+ value = tokenizer.consumeFloat();
+ break;
+
+ case DOUBLE:
+ value = tokenizer.consumeDouble();
+ break;
+
+ case BOOL:
+ value = tokenizer.consumeBoolean();
+ break;
+
+ case STRING:
+ value = tokenizer.consumeString();
+ break;
+
+ case BYTES:
+ value = tokenizer.consumeByteString();
+ break;
+
+ case ENUM: {
+ EnumDescriptor enumType = field.getEnumType();
+
+ if (tokenizer.lookingAtInteger()) {
+ int number = tokenizer.consumeInt32();
+ value = enumType.findValueByNumber(number);
+ if (value == null) {
+ throw tokenizer.parseExceptionPreviousToken("Enum type \""
+ + enumType.getFullName()
+ + "\" has no value with number "
+ + number + ".");
+ }
+ } else {
+ String id = tokenizer.consumeIdentifier();
+ value = enumType.findValueByName(id);
+ if (value == null) {
+ throw tokenizer.parseExceptionPreviousToken("Enum type \""
+ + enumType.getFullName()
+ + "\" has no value named \""
+ + id + "\".");
+ }
+ }
+
+ break;
+ }
+
+ case MESSAGE:
+ case GROUP:
+ throw new RuntimeException("Can't get here.");
+ }
+ return value;
+ }
+
+ private static Object handleObject(Tokenizer tokenizer,
+ ExtensionRegistry extensionRegistry,
+ Message.Builder builder,
+ FieldDescriptor field,
+ ExtensionRegistry.ExtensionInfo extension) throws ParseException {
+
+ Object value;
+ Message.Builder subBuilder;
+ if (extension == null) {
+ subBuilder = builder.newBuilderForField(field);
+ } else {
+ subBuilder = extension.defaultInstance.newBuilderForType();
+ }
+
+ tokenizer.consume("{");
+ String endToken = "}";
+
+ while (!tokenizer.tryConsume(endToken)) {
+ if (tokenizer.atEnd()) {
+ throw tokenizer.parseException("Expected \"" + endToken + "\".");
+ }
+ mergeField(tokenizer, extensionRegistry, subBuilder);
+ if (tokenizer.tryConsume(",")) {
+ // there are more fields in the object, so continue
+ continue;
+ }
+ }
+
+ value = subBuilder.build();
+ return value;
+ }
+
+ // =================================================================
+ // Utility functions
+ //
+ // Some of these methods are package-private because Descriptors.java uses
+ // them.
+
+ /**
+ * Escapes bytes in the format used in protocol buffer text format, which is the same as the
+ * format used for C string literals. All bytes that are not printable 7-bit ASCII characters
+ * are escaped, as well as backslash, single-quote, and double-quote characters. Characters for
+ * which no defined short-hand escape sequence is defined will be escaped using 3-digit octal
+ * sequences.
+ */
+ static String escapeBytes(ByteString input) {
+ StringBuilder builder = new StringBuilder(input.size());
+ for (int i = 0; i < input.size(); i++) {
+ byte b = input.byteAt(i);
+ switch (b) {
+ // Java does not recognize \a or \v, apparently.
+ case 0x07:
+ builder.append("\\a");
+ break;
+ case '\b':
+ builder.append("\\b");
+ break;
+ case '\f':
+ builder.append("\\f");
+ break;
+ case '\n':
+ builder.append("\\n");
+ break;
+ case '\r':
+ builder.append("\\r");
+ break;
+ case '\t':
+ builder.append("\\t");
+ break;
+ case 0x0b:
+ builder.append("\\v");
+ break;
+ case '\\':
+ builder.append("\\\\");
+ break;
+ case '\'':
+ builder.append("\\\'");
+ break;
+ case '"':
+ builder.append("\\\"");
+ break;
+ default:
+ if (b >= 0x20) {
+ builder.append((char) b);
+ } else {
+ builder.append('\\');
+ builder.append((char) ('0' + ((b >>> 6) & 3)));
+ builder.append((char) ('0' + ((b >>> 3) & 7)));
+ builder.append((char) ('0' + (b & 7)));
+ }
+ break;
+ }
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Un-escape a byte sequence as escaped using
+ * {@link #escapeBytes(com.google.protobuf.ByteString)}. Two-digit hex escapes (starting with
+ * "\x") are also recognized.
+ */
+ static ByteString unescapeBytes(CharSequence input) throws InvalidEscapeSequence {
+ byte[] result = new byte[input.length()];
+ int pos = 0;
+ for (int i = 0; i < input.length(); i++) {
+ char c = input.charAt(i);
+ if (c == '\\') {
+ if (i + 1 < input.length()) {
+ ++i;
+ c = input.charAt(i);
+ if (isOctal(c)) {
+ // Octal escape.
+ int code = digitValue(c);
+ if ((i + 1 < input.length()) && isOctal(input.charAt(i + 1))) {
+ ++i;
+ code = code * 8 + digitValue(input.charAt(i));
+ }
+ if ((i + 1 < input.length()) && isOctal(input.charAt(i + 1))) {
+ ++i;
+ code = code * 8 + digitValue(input.charAt(i));
+ }
+ result[pos++] = (byte) code;
+ } else {
+ switch (c) {
+ case 'a':
+ result[pos++] = 0x07;
+ break;
+ case 'b':
+ result[pos++] = '\b';
+ break;
+ case 'f':
+ result[pos++] = '\f';
+ break;
+ case 'n':
+ result[pos++] = '\n';
+ break;
+ case 'r':
+ result[pos++] = '\r';
+ break;
+ case 't':
+ result[pos++] = '\t';
+ break;
+ case 'v':
+ result[pos++] = 0x0b;
+ break;
+ case '\\':
+ result[pos++] = '\\';
+ break;
+ case '\'':
+ result[pos++] = '\'';
+ break;
+ case '"':
+ result[pos++] = '\"';
+ break;
+
+ case 'x':
+ // hex escape
+ int code = 0;
+ if ((i + 1 < input.length()) && isHex(input.charAt(i + 1))) {
+ ++i;
+ code = digitValue(input.charAt(i));
+ } else {
+ throw new InvalidEscapeSequence("Invalid escape sequence: '\\x' with no digits");
+ }
+ if ((i + 1 < input.length()) && isHex(input.charAt(i + 1))) {
+ ++i;
+ code = code * 16 + digitValue(input.charAt(i));
+ }
+ result[pos++] = (byte) code;
+ break;
+
+ default:
+ throw new InvalidEscapeSequence("Invalid escape sequence: '\\" + c
+ + "'");
+ }
+ }
+ } else {
+ throw new InvalidEscapeSequence("Invalid escape sequence: '\\' at end of string.");
+ }
+ } else {
+ result[pos++] = (byte) c;
+ }
+ }
+
+ return ByteString.copyFrom(result, 0, pos);
+ }
+
+ /**
+ * Thrown by {@link JsonFormat#unescapeBytes} and {@link JsonFormat#unescapeText} when an
+ * invalid escape sequence is seen.
+ */
+ static class InvalidEscapeSequence extends IOException {
+
+ public InvalidEscapeSequence(String description) {
+ super(description);
+ }
+ }
+
+ /**
+ * Like {@link #escapeBytes(com.google.protobuf.ByteString)}, but escapes a text string.
+ * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped individually as a
+ * 3-digit octal escape. Yes, it's weird.
+ */
+ static String escapeText(String input) {
+ return escapeBytes(ByteString.copyFromUtf8(input));
+ }
+
+ /**
+ * Un-escape a text string as escaped using {@link #escapeText(String)}. Two-digit hex escapes
+ * (starting with "\x") are also recognized.
+ */
+ static String unescapeText(String input) throws InvalidEscapeSequence {
+ return unescapeBytes(input).toStringUtf8();
+ }
+
+ /**
+ * Is this an octal digit?
+ */
+ private static boolean isOctal(char c) {
+ return ('0' <= c) && (c <= '7');
+ }
+
+ /**
+ * Is this a hex digit?
+ */
+ private static boolean isHex(char c) {
+ return (('0' <= c) && (c <= '9')) || (('a' <= c) && (c <= 'f'))
+ || (('A' <= c) && (c <= 'F'));
+ }
+
+ /**
+ * Interpret a character as a digit (in any base up to 36) and return the numeric value. This is
+ * like {@code Character.digit()} but we don't accept non-ASCII digits.
+ */
+ private static int digitValue(char c) {
+ if (('0' <= c) && (c <= '9')) {
+ return c - '0';
+ } else if (('a' <= c) && (c <= 'z')) {
+ return c - 'a' + 10;
+ } else {
+ return c - 'A' + 10;
+ }
+ }
+
+ /**
+ * Parse a 32-bit signed integer from the text. Unlike the Java standard {@code
+ * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify
+ * hexidecimal and octal numbers, respectively.
+ */
+ static int parseInt32(String text) throws NumberFormatException {
+ return (int) parseInteger(text, true, false);
+ }
+
+ /**
+ * Parse a 32-bit unsigned integer from the text. Unlike the Java standard {@code
+ * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify
+ * hexidecimal and octal numbers, respectively. The result is coerced to a (signed) {@code int}
+ * when returned since Java has no unsigned integer type.
+ */
+ static int parseUInt32(String text) throws NumberFormatException {
+ return (int) parseInteger(text, false, false);
+ }
+
+ /**
+ * Parse a 64-bit signed integer from the text. Unlike the Java standard {@code
+ * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify
+ * hexidecimal and octal numbers, respectively.
+ */
+ static long parseInt64(String text) throws NumberFormatException {
+ return parseInteger(text, true, true);
+ }
+
+ /**
+ * Parse a 64-bit unsigned integer from the text. Unlike the Java standard {@code
+ * Integer.parseInt()}, this function recognizes the prefixes "0x" and "0" to signify
+ * hexidecimal and octal numbers, respectively. The result is coerced to a (signed) {@code long}
+ * when returned since Java has no unsigned long type.
+ */
+ static long parseUInt64(String text) throws NumberFormatException {
+ return parseInteger(text, false, true);
+ }
+
+ private static long parseInteger(String text, boolean isSigned, boolean isLong) throws NumberFormatException {
+ int pos = 0;
+
+ boolean negative = false;
+ if (text.startsWith("-", pos)) {
+ if (!isSigned) {
+ throw new NumberFormatException("Number must be positive: " + text);
+ }
+ ++pos;
+ negative = true;
+ }
+
+ int radix = 10;
+ if (text.startsWith("0x", pos)) {
+ pos += 2;
+ radix = 16;
+ } else if (text.startsWith("0", pos)) {
+ radix = 8;
+ }
+
+ String numberText = text.substring(pos);
+
+ long result = 0;
+ if (numberText.length() < 16) {
+ // Can safely assume no overflow.
+ result = Long.parseLong(numberText, radix);
+ if (negative) {
+ result = -result;
+ }
+
+ // Check bounds.
+ // No need to check for 64-bit numbers since they'd have to be 16 chars
+ // or longer to overflow.
+ if (!isLong) {
+ if (isSigned) {
+ if ((result > Integer.MAX_VALUE) || (result < Integer.MIN_VALUE)) {
+ throw new NumberFormatException("Number out of range for 32-bit signed integer: "
+ + text);
+ }
+ } else {
+ if ((result >= (1L << 32)) || (result < 0)) {
+ throw new NumberFormatException("Number out of range for 32-bit unsigned integer: "
+ + text);
+ }
+ }
+ }
+ } else {
+ BigInteger bigValue = new BigInteger(numberText, radix);
+ if (negative) {
+ bigValue = bigValue.negate();
+ }
+
+ // Check bounds.
+ if (!isLong) {
+ if (isSigned) {
+ if (bigValue.bitLength() > 31) {
+ throw new NumberFormatException("Number out of range for 32-bit signed integer: "
+ + text);
+ }
+ } else {
+ if (bigValue.bitLength() > 32) {
+ throw new NumberFormatException("Number out of range for 32-bit unsigned integer: "
+ + text);
+ }
+ }
+ } else {
+ if (isSigned) {
+ if (bigValue.bitLength() > 63) {
+ throw new NumberFormatException("Number out of range for 64-bit signed integer: "
+ + text);
+ }
+ } else {
+ if (bigValue.bitLength() > 64) {
+ throw new NumberFormatException("Number out of range for 64-bit unsigned integer: "
+ + text);
+ }
+ }
+ }
+
+ result = bigValue.longValue();
+ }
+
+ return result;
+ }
+}
diff --git a/jvm-serializers-tpc/src/main/java/data/ReprUtil.java b/jvm-serializers-tpc/src/main/java/data/ReprUtil.java
new file mode 100644
index 0000000..4593071
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/data/ReprUtil.java
@@ -0,0 +1,23 @@
+package data;
+
+public class ReprUtil
+{
+ public static String repr(String s)
+ {
+ if (s == null) return "null";
+ return '"' + s + '"';
+ }
+
+ public static String repr(Iterable it)
+ {
+ StringBuilder buf = new StringBuilder();
+ buf.append('[');
+ String sep = "";
+ for (String s : it) {
+ buf.append(sep); sep = ", ";
+ buf.append(repr(s));
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+}
diff --git a/jvm-serializers-tpc/src/main/java/data/media/FieldMapping.java b/jvm-serializers-tpc/src/main/java/data/media/FieldMapping.java
new file mode 100644
index 0000000..b57946f
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/data/media/FieldMapping.java
@@ -0,0 +1,85 @@
+package data.media;
+
+import java.util.HashMap;
+
+public final class FieldMapping
+{
+ public final static int FIELD_IX_MEDIA = 1;
+ public final static String FULL_FIELD_NAME_MEDIA = "media";
+ public final static int FIELD_IX_IMAGES = 2;
+ public final static String FULL_FIELD_NAME_IMAGES = "images";
+ public final static int FIELD_IX_PLAYER = 3;
+ public final static String FULL_FIELD_NAME_PLAYER = "player";
+ public final static int FIELD_IX_URI = 4;
+ public final static String FULL_FIELD_NAME_URI = "uri";
+ public final static int FIELD_IX_TITLE = 5;
+ public final static String FULL_FIELD_NAME_TITLE = "title";
+ public final static int FIELD_IX_WIDTH = 6;
+ public final static String FULL_FIELD_NAME_WIDTH = "width";
+ public final static int FIELD_IX_HEIGHT = 7;
+ public final static String FULL_FIELD_NAME_HEIGHT = "height";
+ public final static int FIELD_IX_FORMAT = 8;
+ public final static String FULL_FIELD_NAME_FORMAT = "format";
+ public final static int FIELD_IX_DURATION = 9;
+ public final static String FULL_FIELD_NAME_DURATION = "duration";
+ public final static int FIELD_IX_SIZE = 10;
+ public final static String FULL_FIELD_NAME_SIZE = "size";
+ public final static int FIELD_IX_BITRATE = 11;
+ public final static String FULL_FIELD_NAME_BITRATE = "bitrate";
+ public final static int FIELD_IX_PERSONS = 12;
+ public final static String FULL_FIELD_NAME_PERSONS = "persons";
+ public final static int FIELD_IX_COPYRIGHT = 13;
+ public final static String FULL_FIELD_NAME_COPYRIGHT = "copyright";
+
+ // 25-Jun-2011, tatu: Some earlier tests used minimal names; not in use any more
+ /*
+
+// public final static String FIELD_NAME_MEDIA = "md";
+// public final static String FIELD_NAME_IMAGES = "im";
+// public final static String FIELD_NAME_PLAYER = "pl";
+// public final static String FIELD_NAME_URI = "ul";
+// public final static String FIELD_NAME_TITLE = "tl";
+// public final static String FIELD_NAME_WIDTH = "wd";
+// public final static String FIELD_NAME_HEIGHT = "hg";
+// public final static String FIELD_NAME_FORMAT = "fr";
+// public final static String FIELD_NAME_DURATION = "dr";
+// public final static String FIELD_NAME_SIZE = "sz";
+// public final static String FIELD_NAME_BITRATE = "br";
+// public final static String FIELD_NAME_PERSONS = "pr";
+// public final static String FIELD_NAME_COPYRIGHT = "cp";
+
+ public static final HashMap fieldToIndex = new HashMap();
+ static {
+ fieldToIndex.put(FIELD_NAME_MEDIA, FIELD_IX_MEDIA);
+ fieldToIndex.put(FIELD_NAME_IMAGES, FIELD_IX_IMAGES);
+ fieldToIndex.put(FIELD_NAME_PLAYER, FIELD_IX_PLAYER);
+ fieldToIndex.put(FIELD_NAME_URI, FIELD_IX_URI);
+ fieldToIndex.put(FIELD_NAME_TITLE, FIELD_IX_TITLE);
+ fieldToIndex.put(FIELD_NAME_WIDTH, FIELD_IX_WIDTH);
+ fieldToIndex.put(FIELD_NAME_HEIGHT, FIELD_IX_HEIGHT);
+ fieldToIndex.put(FIELD_NAME_FORMAT, FIELD_IX_FORMAT);
+ fieldToIndex.put(FIELD_NAME_DURATION, FIELD_IX_DURATION);
+ fieldToIndex.put(FIELD_NAME_SIZE, FIELD_IX_SIZE);
+ fieldToIndex.put(FIELD_NAME_BITRATE, FIELD_IX_BITRATE);
+ fieldToIndex.put(FIELD_NAME_PERSONS, FIELD_IX_PERSONS);
+ fieldToIndex.put(FIELD_NAME_COPYRIGHT, FIELD_IX_COPYRIGHT);
+ }
+ */
+
+ public static final HashMap fullFieldToIndex = new HashMap();
+ static {
+ fullFieldToIndex.put(FULL_FIELD_NAME_MEDIA, FIELD_IX_MEDIA);
+ fullFieldToIndex.put(FULL_FIELD_NAME_IMAGES, FIELD_IX_IMAGES);
+ fullFieldToIndex.put(FULL_FIELD_NAME_PLAYER, FIELD_IX_PLAYER);
+ fullFieldToIndex.put(FULL_FIELD_NAME_URI, FIELD_IX_URI);
+ fullFieldToIndex.put(FULL_FIELD_NAME_TITLE, FIELD_IX_TITLE);
+ fullFieldToIndex.put(FULL_FIELD_NAME_WIDTH, FIELD_IX_WIDTH);
+ fullFieldToIndex.put(FULL_FIELD_NAME_HEIGHT, FIELD_IX_HEIGHT);
+ fullFieldToIndex.put(FULL_FIELD_NAME_FORMAT, FIELD_IX_FORMAT);
+ fullFieldToIndex.put(FULL_FIELD_NAME_DURATION, FIELD_IX_DURATION);
+ fullFieldToIndex.put(FULL_FIELD_NAME_SIZE, FIELD_IX_SIZE);
+ fullFieldToIndex.put(FULL_FIELD_NAME_BITRATE, FIELD_IX_BITRATE);
+ fullFieldToIndex.put(FULL_FIELD_NAME_PERSONS, FIELD_IX_PERSONS);
+ fullFieldToIndex.put(FULL_FIELD_NAME_COPYRIGHT, FIELD_IX_COPYRIGHT);
+ }
+}
diff --git a/jvm-serializers-tpc/src/main/java/data/media/Image.java b/jvm-serializers-tpc/src/main/java/data/media/Image.java
new file mode 100644
index 0000000..1446acf
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/data/media/Image.java
@@ -0,0 +1,113 @@
+package data.media;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+
+import static data.ReprUtil.repr;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Image implements java.io.Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ public enum Size {
+ SMALL, LARGE
+ }
+
+ public String uri;
+
+ public String title; // Can be null
+ public int width;
+ public int height;
+ public Size size;
+
+ public Image() {}
+
+ public Image (String uri, String title, int width, int height, Size size) {
+ this.height = height;
+ this.title = title;
+ this.uri = uri;
+ this.width = width;
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Image image = (Image) o;
+
+ if (height != image.height) return false;
+ if (width != image.width) return false;
+ if (size != image.size) return false;
+ if (title != null ? !title.equals(image.title) : image.title != null) return false;
+ if (uri != null ? !uri.equals(image.uri) : image.uri != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = uri != null ? uri.hashCode() : 0;
+ result = 31 * result + (title != null ? title.hashCode() : 0);
+ result = 31 * result + width;
+ result = 31 * result + height;
+ result = 31 * result + (size != null ? size.hashCode() : 0);
+ return result;
+ }
+
+ public String toString () {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[Image ");
+ sb.append("uri=").append(repr(uri));
+ sb.append(", title=").append(repr(title));
+ sb.append(", width=").append(width);
+ sb.append(", height=").append(height);
+ sb.append(", size=").append(size);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ public void setSize(Size size) {
+ this.size = size;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public Size getSize() {
+ return size;
+ }
+}
diff --git a/jvm-serializers-tpc/src/main/java/data/media/Media.java b/jvm-serializers-tpc/src/main/java/data/media/Media.java
new file mode 100644
index 0000000..a590092
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/data/media/Media.java
@@ -0,0 +1,214 @@
+package data.media;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+import java.util.List;
+
+import static data.ReprUtil.repr;
+
+@SuppressWarnings("serial")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "JaxbMedia")
+public class Media implements java.io.Serializable {
+ public enum Player {
+ JAVA, FLASH;
+
+ public static Player find(String str) {
+ if (str == "JAVA") return JAVA;
+ if (str == "FLASH") return FLASH;
+ if ("JAVA".equals(str)) return JAVA;
+ if ("FLASH".equals(str)) return FLASH;
+ String desc = (str == null) ? "NULL" : String.format("'%s'", str);
+ throw new IllegalArgumentException("No Player value of "+desc);
+ }
+ }
+
+ public String uri;
+ public String title; // Can be unset.
+ public int width;
+ public int height;
+ public String format;
+ public long duration;
+ public long size;
+ public int bitrate; // Can be unset.
+
+ @jsonij.json.annotation.JSONIgnore // required by JSONiJ
+ @org.codehaus.jackson.annotate.JsonIgnore // Jackson 1.x
+ @com.fasterxml.jackson.annotation.JsonIgnore // Jackson 2.x
+ public boolean hasBitrate;
+
+ public List persons;
+
+ public Player player;
+
+ public String copyright; // Can be unset.
+
+ public Media() {}
+
+ public Media(String uri, String title, int width, int height, String format, long duration, long size, int bitrate, boolean hasBitrate, List persons, Player player, String copyright)
+ {
+ this.uri = uri;
+ this.title = title;
+ this.width = width;
+ this.height = height;
+ this.format = format;
+ this.duration = duration;
+ this.size = size;
+ this.bitrate = bitrate;
+ this.hasBitrate = hasBitrate;
+ this.persons = persons;
+ this.player = player;
+ this.copyright = copyright;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Media media = (Media) o;
+
+ if (bitrate != media.bitrate) return false;
+ if (duration != media.duration) return false;
+ if (hasBitrate != media.hasBitrate) return false;
+ if (height != media.height) return false;
+ if (size != media.size) return false;
+ if (width != media.width) return false;
+ if (copyright != null ? !copyright.equals(media.copyright) : media.copyright != null) return false;
+ if (format != null ? !format.equals(media.format) : media.format != null) return false;
+ if (persons != null ? !persons.equals(media.persons) : media.persons != null) return false;
+ if (player != media.player) return false;
+ if (title != null ? !title.equals(media.title) : media.title != null) return false;
+ if (uri != null ? !uri.equals(media.uri) : media.uri != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = uri != null ? uri.hashCode() : 0;
+ result = 31 * result + (title != null ? title.hashCode() : 0);
+ result = 31 * result + width;
+ result = 31 * result + height;
+ result = 31 * result + (format != null ? format.hashCode() : 0);
+ result = 31 * result + (int) (duration ^ (duration >>> 32));
+ result = 31 * result + (int) (size ^ (size >>> 32));
+ result = 31 * result + bitrate;
+ result = 31 * result + (hasBitrate ? 1 : 0);
+ result = 31 * result + (persons != null ? persons.hashCode() : 0);
+ result = 31 * result + (player != null ? player.hashCode() : 0);
+ result = 31 * result + (copyright != null ? copyright.hashCode() : 0);
+ return result;
+ }
+
+ public String toString () {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[Media ");
+ sb.append("uri=").append(repr(uri));
+ sb.append(", title=").append(repr(title));
+ sb.append(", width=").append(width);
+ sb.append(", height=").append(height);
+ sb.append(", format=").append(repr(format));
+ sb.append(", duration=").append(duration);
+ sb.append(", size=").append(size);
+ sb.append(", hasBitrate=").append(hasBitrate);
+ sb.append(", bitrate=").append(String.valueOf(bitrate));
+ sb.append(", persons=").append(repr(persons));
+ sb.append(", player=").append(player);
+ sb.append(", copyright=").append(repr(copyright));
+ sb.append("]");
+ return sb.toString();
+ }
+
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ public void setDuration(long duration) {
+ this.duration = duration;
+ }
+
+ public void setSize(long size) {
+ this.size = size;
+ }
+
+ public void setBitrate(int bitrate) {
+ this.bitrate = bitrate;
+ this.hasBitrate = true;
+ }
+
+ public void setPersons(List persons) {
+ this.persons = persons;
+ }
+
+ public void setPlayer(Player player) {
+ this.player = player;
+ }
+
+ public void setCopyright(String copyright) {
+ this.copyright = copyright;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public String getFormat() {
+ return format;
+ }
+
+ public long getDuration() {
+ return duration;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public int getBitrate() {
+ return bitrate;
+ }
+
+ public List getPersons() {
+ return persons;
+ }
+
+ public Player getPlayer() {
+ return player;
+ }
+
+ public String getCopyright() {
+ return copyright;
+ }
+}
diff --git a/jvm-serializers-tpc/src/main/java/data/media/MediaContent.java b/jvm-serializers-tpc/src/main/java/data/media/MediaContent.java
new file mode 100644
index 0000000..06c4aee
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/data/media/MediaContent.java
@@ -0,0 +1,69 @@
+package data.media;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.List;
+
+@SuppressWarnings("serial")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class MediaContent implements java.io.Serializable
+{
+ public Media media;
+ public List images;
+
+ public MediaContent() {}
+
+ public MediaContent (Media media, List images) {
+ this.media = media;
+ this.images = images;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ MediaContent that = (MediaContent) o;
+
+ if (images != null ? !images.equals(that.images) : that.images != null) return false;
+ if (media != null ? !media.equals(that.media) : that.media != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = media != null ? media.hashCode() : 0;
+ result = 31 * result + (images != null ? images.hashCode() : 0);
+ return result;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[MediaContent: ");
+ sb.append("media=").append(media);
+ sb.append(", images=").append(images);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ public void setMedia(Media media) {
+ this.media = media;
+ }
+
+ public void setImages(List images) {
+ this.images = images;
+ }
+
+ public Media getMedia() {
+ return media;
+ }
+
+ public List getImages() {
+ return images;
+ }
+}
diff --git a/jvm-serializers-tpc/src/main/java/data/media/MediaContentCustom.java b/jvm-serializers-tpc/src/main/java/data/media/MediaContentCustom.java
new file mode 100644
index 0000000..d873ec6
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/data/media/MediaContentCustom.java
@@ -0,0 +1,137 @@
+package data.media;
+
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+// I _think_ this is for "obser" package -- should be renamed to reflect that
+
+public class MediaContentCustom {
+ private MediaContent content;
+
+ public MediaContentCustom(MediaContent content) {
+ this.content = content;
+ }
+
+ public MediaContent getContent() {
+ return content;
+ }
+
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
+ writeMediaContent(s, content);
+ }
+
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
+ content = readMediaContent(s);
+ }
+
+ public static MediaContent readMediaContent(ObjectInputStream in) throws IOException
+ {
+ Media media = readMedia(in);
+ int numImages = in.readInt();
+ ArrayList images = new ArrayList(numImages);
+ for (int i = 0; i < numImages; i++) {
+ images.add(readImage(in));
+ }
+ return new MediaContent(media, images);
+ }
+
+
+ public static void writeMediaContent(ObjectOutputStream out, MediaContent m) throws IOException {
+ writeMedia(out, m.getMedia());
+ out.writeInt(m.getImages().size());
+ for (Image im : m.getImages()) {
+ writeImage(out, im);
+ }
+ }
+
+ // Media
+
+ private static Media readMedia(ObjectInputStream in) throws IOException {
+ String uri = in.readUTF();
+ String title = readMaybeString(in);
+ int width = in.readInt();
+ int height = in.readInt();
+ String format = in.readUTF();
+ long duration = in.readLong();
+ long size = in.readLong();
+ boolean hasBitrate = in.readBoolean();
+ int bitrate = 0;
+ if (hasBitrate)
+ bitrate = in.readInt();
+ int numPersons = in.readInt();
+ ArrayList persons = new ArrayList(numPersons);
+ for (int i = 0; i < numPersons; i++) {
+ persons.add(in.readUTF());
+ }
+ Media.Player player = Media.Player.values()[in.readByte()];
+ String copyright = readMaybeString(in);
+
+ return new Media(uri, title, width, height, format, duration, size, bitrate, hasBitrate, persons, player, copyright);
+ }
+
+ private static void writeMedia(ObjectOutputStream out, Media m) throws IOException {
+ out.writeUTF(m.getUri());
+ writeMaybeString(out, m.getTitle());
+ out.writeInt(m.getWidth());
+ out.writeInt(m.getHeight());
+ out.writeUTF(m.getFormat());
+ out.writeLong(m.getDuration());
+ out.writeLong(m.getSize());
+ writeMaybeInt(out, m.hasBitrate, m.getBitrate());
+ out.writeInt(m.getPersons().size());
+ for (String p : m.getPersons()) {
+ out.writeUTF(p);
+ }
+ out.writeByte(m.getPlayer().ordinal());
+ writeMaybeString(out, m.getCopyright());
+ }
+
+ // Image
+
+ private static Image readImage(ObjectInputStream in) throws IOException {
+ String uri = in.readUTF();
+ String title = readMaybeString(in);
+ int width = in.readInt();
+ int height = in.readInt();
+ Image.Size size = Image.Size.values()[in.readByte()];
+
+ return new Image(uri, title, width, height, size);
+ }
+
+ private static void writeImage(ObjectOutputStream out, Image im) throws IOException {
+ out.writeUTF(im.getUri());
+ writeMaybeString(out, im.getTitle());
+ out.writeInt(im.getWidth());
+ out.writeInt(im.getHeight());
+ out.writeByte(im.getSize().ordinal());
+ }
+
+ public static void writeMaybeString(ObjectOutputStream out, String s) throws IOException {
+ if (s != null) {
+ out.writeBoolean(true);
+ out.writeUTF(s);
+ } else {
+ out.writeBoolean(false);
+ }
+ }
+
+ public static String readMaybeString(ObjectInputStream in) throws IOException {
+ if (in.readBoolean()) {
+ return in.readUTF();
+ } else {
+ return null;
+ }
+ }
+
+ public static void writeMaybeInt(ObjectOutputStream out, boolean exists, int value) throws IOException {
+ if (exists) {
+ out.writeBoolean(true);
+ out.writeInt(value);
+ } else {
+ out.writeBoolean(false);
+ }
+ }
+
+}
diff --git a/jvm-serializers-tpc/src/main/java/data/media/MediaTransformer.java b/jvm-serializers-tpc/src/main/java/data/media/MediaTransformer.java
new file mode 100644
index 0000000..b53e567
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/data/media/MediaTransformer.java
@@ -0,0 +1,11 @@
+package data.media;
+
+import serializers.Transformer;
+
+public abstract class MediaTransformer extends Transformer
+{
+ public MediaContent[] sourceArray(int size) { return new MediaContent[size]; }
+
+ // just defined to work around Scala issue
+ public B[] resultArray(int size) { throw new UnsupportedOperationException("Please implement for "+getClass().getName()); }
+}
diff --git a/jvm-serializers-tpc/src/main/java/jvm-serializers/tpc/App.java b/jvm-serializers-tpc/src/main/java/jvm-serializers/tpc/App.java
new file mode 100644
index 0000000..0325a97
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/jvm-serializers/tpc/App.java
@@ -0,0 +1,13 @@
+package jvm-serializers.tpc;
+
+/**
+ * Hello world!
+ *
+ */
+public class App
+{
+ public static void main( String[] args )
+ {
+ System.out.println( "Hello World!" );
+ }
+}
diff --git a/jvm-serializers-tpc/src/main/java/log4j.xml b/jvm-serializers-tpc/src/main/java/log4j.xml
new file mode 100644
index 0000000..177a459
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/log4j.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jvm-serializers-tpc/src/main/java/serializers/BenchmarkBase.java b/jvm-serializers-tpc/src/main/java/serializers/BenchmarkBase.java
new file mode 100644
index 0000000..6447287
--- /dev/null
+++ b/jvm-serializers-tpc/src/main/java/serializers/BenchmarkBase.java
@@ -0,0 +1,820 @@
+package serializers;
+
+import java.io.*;
+import java.net.URLEncoder;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.zip.DeflaterOutputStream;
+
+/**
+ * Common base class for various benchmark implementations.
+ */
+abstract class BenchmarkBase
+{
+ public final static int DEFAULT_ITERATIONS = 2000;
+ public final static int DEFAULT_TEST_RUN_MILLIS = 10000; // 10 seconds
+
+ /**
+ * Number of milliseconds to warm up for each operation type for each serializer. Let's
+ * start with 3 seconds.
+ */
+ final static long DEFAULT_WARMUP_MSECS = 10000;
+
+ // These tests aren't included by default. Use the "-hidden" flag to enable them.
+ protected static final HashSet HIDDEN = new HashSet();
+ static {
+ // CKS is not included because it's not really publicly released.
+ HIDDEN.add("cks");
+ HIDDEN.add("cks-text");
+ }
+
+ protected static final String ERROR_DIVIDER = "-------------------------------------------------------------------";
+
+ // ------------------------------------------------------------------------------------
+ // Helper classes, enums
+ // ------------------------------------------------------------------------------------
+
+ public enum measurements
+ {
+ totalTime("total (nanos)"), timeSerialize("ser (nanos)"),
+ timeDeserialize("deser (nanos)"),
+ length("size (bytes)"), lengthDeflate("size+dfl (bytes)"),
+ timeCreate("create (nanos)")
+ ;
+
+ public final String displayName;
+
+ measurements(String displayName)
+ {
+ this.displayName = displayName;
+ }
+ }
+
+ // Simple container class for config parameters from command-line
+ protected final static class Params
+ {
+ public int iterations = DEFAULT_ITERATIONS;
+ public int testRunMillis = DEFAULT_TEST_RUN_MILLIS;
+ public long warmupTime = DEFAULT_WARMUP_MSECS;
+ public boolean prewarm = true;
+ public Boolean filterIsInclude;
+ public Set filterStrings;
+ public boolean printChart = false;
+ public boolean enableHidden = false;
+
+ // Information in input data file:
+ public String dataFileName;
+ public String dataType; // from first part of file name (comma-separated)
+ public String dataExtra; // from second part
+ public String dataExtension; // from last part of file name
+ }
+
+
+ // ------------------------------------------------------------------------------------
+ // Actual benchmark flow
+ // ------------------------------------------------------------------------------------
+
+ protected void runBenchmark(String[] args,
+ TestCase testCreate,
+ TestCase testSerialize,
+ TestCase testDeserialize)
+ {
+ Params params = new Params();
+ findParameters(args, params);
+ TestGroups groups = new TestGroups();
+ addTests(groups);
+ runTests(groups, params,
+ testCreate,
+ testSerialize,
+ testDeserialize);
+ }
+
+ /**
+ * Method called to find add actual test codecs
+ */
+ protected abstract void addTests(TestGroups groups);
+
+ protected void findParameters(String[] args, Params params)
+ {
+ Set optionsSeen = new HashSet();
+
+ for (String arg : args) {
+ String remainder;
+ if (arg.startsWith("--")) {
+ remainder = arg.substring(2);
+ }
+ else if (arg.startsWith("-")) {
+ remainder = arg.substring(1);
+ }
+ else if (params.dataFileName == null) {
+ params.dataFileName = arg;
+ continue;
+ }
+ else {
+ System.err.println("Expecting only one non-option argument ( = \"" + params.dataFileName + "\").");
+ System.err.println("Found a second one: \"" + arg + "\"");
+ System.err.println("Use \"-help\" for usage information.");
+ System.exit(1); return;
+ }
+ String option, value;
+ int eqPos = remainder.indexOf('=');
+ if (eqPos >= 0) {
+ option = remainder.substring(0, eqPos);
+ value = remainder.substring(eqPos+1);
+ } else {
+ option = remainder;
+ value = null;
+ }
+ if (!optionsSeen.add(option)) {
+ System.err.println("Repeated option: \"" + arg + "\"");
+ System.exit(1);
+ }
+ if (option.equals("include")) {
+ if (value == null) {
+ System.err.println("The \"include\" option requires a value.");
+ System.exit(1);
+ }
+ if (params.filterIsInclude == null) {
+ params.filterIsInclude = true;
+ params.filterStrings = new HashSet(Arrays.asList(value.split(",")));
+ } else {
+ System.err.println("Can't use 'include' and 'exclude' options at the same time.");
+ System.exit(1);
+ }
+ }
+ else if (option.equals("exclude")) {
+ if (value == null) {
+ System.err.println("The \"exclude\" option requires a value.");
+ System.exit(1);
+ }
+ if (params.filterIsInclude == null) {
+ params.filterIsInclude = false;
+ params.filterStrings = new HashSet(Arrays.asList(value.split(",")));
+ } else {
+ System.err.println("Can't use 'include' and 'exclude' options at the same time.");
+ System.exit(1);
+ }
+ }
+ else if (option.equals("iterations")) {
+ if (value == null) {
+ System.err.println("The \"iterations\" option requires a value.");
+ System.exit(1);
+ }
+ try {
+ params.iterations = Integer.parseInt(value);
+ } catch (NumberFormatException ex) {
+ System.err.println("Invalid value for \"iterations\" option: \"" + value + "\"");
+ System.exit(1);
+ }
+ if (params.iterations < 1) {
+ System.err.println("Invalid value for \"iterations\" option: \"" + value + "\"");
+ System.exit(1);
+ }
+ }
+ else if (option.equals("testRunMillis")) {
+ if (value == null) {
+ System.err.println("The \"testRunMillis\" option requires a value.");
+ System.exit(1);
+ }
+ try {
+ params.testRunMillis = Integer.parseInt(value);
+ } catch (NumberFormatException ex) {
+ System.err.println("Invalid value for \"testRunMillis\" option: \"" + value + "\"");
+ System.exit(1);
+ }
+ if (params.testRunMillis < 1) {
+ System.err.println("Invalid value for \"testRunMillis\" option: \"" + value + "\"");
+ System.exit(1);
+ }
+ }
+ else if (option.equals("warmup-time")) {
+ if (value == null) {
+ System.err.println("The \"warmup-time\" option requires a value.");
+ System.exit(1);
+ }
+ try {
+ params.warmupTime = Long.parseLong(value);
+ } catch (NumberFormatException ex) {
+ System.err.println("Invalid value for \"warmup-time\" option: \"" + value + "\"");
+ System.exit(1);
+ }
+ if (params.warmupTime < 0) {
+ System.err.println("Invalid value for \"warmup-time\" option: \"" + value + "\"");
+ System.exit(1);
+ }
+ }
+ else if (option.equals("skip-pre-warmup")) {
+ if (value != null) {
+ System.err.println("The \"skip-pre-warmup\" option does not take a value: \"" + arg + "\"");
+ System.exit(1);
+ }
+ params.prewarm = false;
+ }
+ else if (option.equals("chart")) {
+ if (value != null) {
+ System.err.println("The \"chart\" option does not take a value: \"" + arg + "\"");
+ System.exit(1);
+ }
+ params.printChart = true;
+ }
+ else if (option.equals("hidden")) {
+ if (value != null) {
+ System.err.println("The \"hidden\" option does not take a value: \"" + arg + "\"");
+ System.exit(1);
+ }
+ params.enableHidden = true;
+ }
+ else if (option.equals("help")) {
+ if (value != null) {
+ System.err.println("The \"help\" option does not take a value: \"" + arg + "\"");
+ System.exit(1);
+ }
+ if (args.length != 1) {
+ System.err.println("The \"help\" option cannot be combined with any other option.");
+ System.exit(1);
+ }
+ System.out.println();
+ System.out.println("Usage: run [options] ");
+ System.out.println();
+ System.out.println("Options:");
+ System.out.println(" -iterations=n [default=" + DEFAULT_ITERATIONS + "]");
+ System.out.println(" -testRunMillis=n [default=" + DEFAULT_TEST_RUN_MILLIS + "ms]");
+ System.out.println(" -warmup-time=millis [default=" + DEFAULT_WARMUP_MSECS + "]");
+ System.out.println(" -skip-pre-warmup (don't warm all serializers before the first measurement)");
+ System.out.println(" -chart (generate a Google Chart URL for the results)");
+ System.out.println(" -include=impl1,impl2,impl3,...");
+ System.out.println(" -exclude=impl1,impl2,impl3,...");
+ System.out.println(" -hidden (enable \"hidden\" serializers)");
+ System.out.println(" -help");
+ System.out.println();
+ System.out.println("Example: run -chart -include=protobuf,thrift data/media.1.cks");
+ System.out.println();
+ System.exit(0);
+ }
+ else {
+ System.err.println("Unknown option: \"" + arg + "\"");
+ System.err.println("Use \"-help\" for usage information.");
+ System.exit(1);
+ }
+ }
+
+ if (params.dataFileName == null) {
+ System.err.println("Missing argument.");
+ System.err.println("Use \"-help\" for usage information.");
+ System.exit(1);
+ }
+
+ // And then let's verify input data file bit more...
+ File dataFile = new File(params.dataFileName);
+ if (!dataFile.exists()) {
+ System.out.println("Couldn't find data file \"" + dataFile.getPath() + "\"");
+ System.exit(1);
+ }
+ String[] parts = dataFile.getName().split("\\.");
+ if (parts.length < 3) {
+ System.out.println("Data file \"" + dataFile.getName() + "\" should be of the form \"..\"");
+ System.exit(1);
+ }
+ params.dataType = parts[0];
+ params.dataExtra = parts[1];
+ params.dataExtension = parts[parts.length-1];
+ }
+
+ /**
+ * Method called to run individual test cases
+ */
+ protected void runTests(TestGroups groups, Params params,
+ TestCase testCreate,
+ TestCase testSerialize,
+ TestCase testDeserialize)
+ {
+ TestGroup> bootstrapGroup = findGroupForTestData(groups, params);
+ Object testData = loadTestData(bootstrapGroup, params);
+ Iterable> matchingEntries
+ = findApplicableTests(groups, params, bootstrapGroup);
+
+ StringWriter errors = new StringWriter();
+ PrintWriter errorsPW = new PrintWriter(errors);
+ try {
+ EnumMap> values = runMeasurements(errorsPW, params, matchingEntries, testData,
+ testCreate,
+ testSerialize,
+ testDeserialize
+ );
+
+ if (params.printChart) {
+ printImages(values);
+ }
+ }
+ catch (Exception ex) {
+ ex.printStackTrace(System.err);
+ System.exit(1); return;
+ }
+
+ // Print errors after chart. That way you can't miss it.
+ String errorsString = errors.toString();
+ if (errorsString.length() > 0) {
+ System.out.println(ERROR_DIVIDER);
+ System.out.println("Errors occurred during benchmarking:");
+ System.out.print(errorsString);
+ System.exit(1); return;
+ }
+ }
+
+ protected TestGroup> findGroupForTestData(TestGroups groups, Params params)
+ {
+ TestGroup> group = groups.groupMap.get(params.dataType);
+ if (group == null) {
+ System.out.println("Data file \"" + params.dataFileName + "\" can't be loaded.");
+ System.out.println("Don't know about data type \"" + params.dataType + "\"");
+ System.exit(1);
+ }
+ return group;
+ }
+
+ protected abstract Object convertTestData(TestGroup.Entry,Object> loader, Params params, byte[] data)
+ throws Exception;
+
+ protected Object loadTestData(TestGroup> bootstrapGroup, Params params)
+ {
+ TestGroup.Entry,Object> loader = bootstrapGroup.extensionMap.get(params.dataExtension);
+ if (loader == null) {
+ System.out.println("Data file \"" + params.dataFileName + "\" can't be loaded.");
+ System.out.println("No deserializer registered for data type \"" + params.dataType
+ + "\" and file extension \"." + params.dataExtension + "\"");
+ System.exit(1);
+ }
+ byte[] fileBytes;
+ try {
+ fileBytes = readFile(new File(params.dataFileName)); // Load entire file into a byte array.
+ }
+ catch (Exception ex) {
+ System.err.println("Error loading data from file \"" + params.dataFileName + "\".");
+ System.err.println(ex.getMessage());
+ System.exit(1); return null;
+ }
+ try {
+ return convertTestData(loader, params, fileBytes);
+ } catch (Exception ex) {
+ System.err.println("Error converting test data from file \"" + params.dataFileName + "\".");
+ System.err.println(ex.getMessage());
+ System.exit(1); return null;
+ }
+ }
+
+ /**
+ * Method called to both load in test data and figure out which tests should
+ * actually be run, from all available test cases.
+ */
+ protected Iterable> findApplicableTests(TestGroups groups, Params params,
+ TestGroup> bootstrapGroup)
+ {
+ @SuppressWarnings("unchecked")
+ TestGroup