summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorMuga Nishizawa <muga@f11vm.(none)>2010-09-12 22:21:33 +0900
committerMuga Nishizawa <muga@f11vm.(none)>2010-09-12 22:21:33 +0900
commita9566b31be76ebc8aaf9149c1a09d3720c3f2ec9 (patch)
tree66a352ac70afdcae32a00e1604715a573f290e4a /java
parentf30837d72621fbf16d9e7709ca2225fcdd6190d7 (diff)
downloadmsgpack-python-a9566b31be76ebc8aaf9149c1a09d3720c3f2ec9.tar.gz
add annotation utilities for Java
Diffstat (limited to 'java')
-rw-r--r--java/src/main/java/org/msgpack/tmp/DynamicCodeGenerator.java206
-rw-r--r--java/src/main/java/org/msgpack/tmp/Image1.java47
-rw-r--r--java/src/main/java/org/msgpack/tmp/Image2.java85
-rw-r--r--java/src/main/java/org/msgpack/tmp/Image3.java38
-rw-r--r--java/src/main/java/org/msgpack/tmp/ImagePackUnpackPerfTest.java134
-rw-r--r--java/src/main/java/org/msgpack/util/annotation/MessagePackOptional.java12
-rw-r--r--java/src/main/java/org/msgpack/util/annotation/MessagePackRequired.java12
-rw-r--r--java/src/main/java/org/msgpack/util/annotation/MessagePackUnpackable.java11
-rw-r--r--java/src/main/java/org/msgpack/util/annotation/PackUnpackUtil.java498
-rw-r--r--java/src/main/java/org/msgpack/util/annotation/PackUnpackUtilException.java12
10 files changed, 545 insertions, 510 deletions
diff --git a/java/src/main/java/org/msgpack/tmp/DynamicCodeGenerator.java b/java/src/main/java/org/msgpack/tmp/DynamicCodeGenerator.java
deleted file mode 100644
index 78238b4..0000000
--- a/java/src/main/java/org/msgpack/tmp/DynamicCodeGenerator.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package org.msgpack.tmp;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.lang.reflect.Field;
-import java.util.HashMap;
-
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.CtConstructor;
-import javassist.CtMethod;
-import javassist.CtNewConstructor;
-import javassist.CtNewMethod;
-
-import org.msgpack.Packer;
-import org.msgpack.Unpacker;
-
-public class DynamicCodeGenerator {
-
- private static final String ENHANCED_CLASS_NAME_POSTFIX = "_$$_Enhanced";
-
- private static final String SPACE = " ";
-
- private static final String MODIFIER_PUBLIC = "public";
-
- private static final String METHOD_NAME_MESSAGEPACK = "messagePack";
-
- private static final String METHOD_NAME_MESSAGEUNPACK = "messageUnpack";
-
- private static final String PACKER_CLASS_TYPE_NAME = Packer.class.getName();
-
- private static final String VOID_TYPE_NAME = "void";
-
- private static final String PACKER_OBJECT_NAME = "pk";
-
- private static final String UNPACKER_CLASS_TYPE_NAME = Unpacker.class
- .getName();
-
- private static final String UNPACKER_OBJECT_NAME = "pk";
-
- private HashMap<String, Class<?>> classMap;
-
- private HashMap<String, Object> objectCacheMap;
-
- private ClassPool pool;
-
- public DynamicCodeGenerator() {
- classMap = new HashMap<String, Class<?>>();
- objectCacheMap = new HashMap<String, Object>();
- pool = ClassPool.getDefault();
- }
-
- public Object newEnhancedInstance(Class<?> targetClass) throws Exception {
- String targetClassName = targetClass.getName();
- // Class<?> enhancedClass = classMap.get(targetClassName);
- Object enhancedObject = objectCacheMap.get(targetClassName);
- // if (enhancedClass == null) {
- if (enhancedObject == null) {
- CtClass enhancedCtClass = createEnhancedCtClass(targetClassName);
- // System.out.println("enhanced class name: "
- // + enhancedCtClass.getName());
- addSuperclass(enhancedCtClass, targetClassName);
- addConstructor(enhancedCtClass);
- createMessagePackMethod(enhancedCtClass, targetClass);
- createMessageUnpackMethod(enhancedCtClass, targetClass);
- Class enhancedClass = loadEnhancedClass(enhancedCtClass);
- // classMap.put(targetClassName, enhancedClass);
- enhancedObject = enhancedClass.newInstance();
- objectCacheMap.put(targetClassName, enhancedObject);
- }
- // return newEnhancedInstance0(enhancedClass);
- return enhancedObject;
- }
-
- private CtClass createEnhancedCtClass(final String targetClassName)
- throws Exception {
- return pool.makeClass(targetClassName + ENHANCED_CLASS_NAME_POSTFIX);
- }
-
- private void addSuperclass(CtClass enhancedCtClass,
- final String targetClassName) throws Exception {
- CtClass targetCtClass = pool.get(targetClassName);
- enhancedCtClass.setSuperclass(targetCtClass);
- }
-
- private void addConstructor(CtClass enhancedCtClass) throws Exception {
- CtConstructor newCtConstructor = CtNewConstructor
- .defaultConstructor(enhancedCtClass);
- enhancedCtClass.addConstructor(newCtConstructor);
- }
-
- private void createMessagePackMethod(CtClass enhancedCtClass,
- Class<?> targetClass) throws Exception {
- StringBuilder sb = new StringBuilder();
- sb.append(MODIFIER_PUBLIC).append(SPACE).append(VOID_TYPE_NAME).append(
- SPACE).append(METHOD_NAME_MESSAGEPACK).append("(").append(
- PACKER_CLASS_TYPE_NAME).append(SPACE)
- .append(PACKER_OBJECT_NAME).append(")").append(SPACE).append(
- "throws").append(SPACE).append("java.io.IOException")
- .append(SPACE).append("{");
- Field[] fields = targetClass.getFields();
- sb.append(PACKER_OBJECT_NAME).append(".").append("packArray").append(
- "(").append(fields.length).append(")").append(";");
- for (Field field : fields) {
- insertCodeOfMessagePack(field, sb);
- }
- sb.append("}");
- // System.out.println("messagePack method: " + sb.toString());
- CtMethod newCtMethod = CtNewMethod.make(sb.toString(), enhancedCtClass);
- enhancedCtClass.addMethod(newCtMethod);
- }
-
- private void insertCodeOfMessagePack(Field field, StringBuilder sb) {
- Class<?> type = field.getType();
- if (type.equals(int.class)) {
- sb.append(PACKER_OBJECT_NAME).append(".").append("pack")
- .append("(").append(field.getName()).append(")")
- .append(";");
- } else if (type.equals(String.class)) {
- sb.append(PACKER_OBJECT_NAME).append(".").append("pack")
- .append("(").append(field.getName()).append(")")
- .append(";");
- } else {
- throw new UnsupportedOperationException();
- }
- }
-
- private void createMessageUnpackMethod(CtClass enhancedCtClass,
- Class<?> targetClass) throws Exception {
- StringBuilder sb = new StringBuilder();
- sb
- .append(MODIFIER_PUBLIC)
- .append(SPACE)
- .append(VOID_TYPE_NAME)
- .append(SPACE)
- .append(METHOD_NAME_MESSAGEUNPACK)
- .append("(")
- .append(UNPACKER_CLASS_TYPE_NAME)
- .append(SPACE)
- .append(UNPACKER_OBJECT_NAME)
- .append(")")
- .append(SPACE)
- .append("throws")
- .append(SPACE)
- .append("org.msgpack.MessageTypeException, java.io.IOException")
- .append(SPACE).append("{");
- Field[] fields = targetClass.getFields();
- sb.append(UNPACKER_OBJECT_NAME).append(".").append("unpackArray()")
- .append(";");
- // TODO
- for (Field field : fields) {
- insertCodeOfMessageUnpack(field, sb);
- }
- sb.append("}");
- // System.out.println("messageUnpack method: " + sb.toString());
- CtMethod newCtMethod = CtNewMethod.make(sb.toString(), enhancedCtClass);
- enhancedCtClass.addMethod(newCtMethod);
- }
-
- private void insertCodeOfMessageUnpack(Field field, StringBuilder sb) {
- Class<?> type = field.getType();
- if (type.equals(int.class)) {
- sb.append(field.getName()).append(SPACE).append("=").append(SPACE)
- .append(PACKER_OBJECT_NAME).append(".").append("unpackInt")
- .append("(").append(")").append(";");
- } else if (type.equals(String.class)) {
- sb.append(field.getName()).append(SPACE).append("=").append(SPACE)
- .append(PACKER_OBJECT_NAME).append(".").append(
- "unpackString").append("(").append(")").append(";");
- } else {
- throw new UnsupportedOperationException();
- }
- }
-
- private Class<?> loadEnhancedClass(CtClass enhancedCtClass)
- throws Exception {
- return enhancedCtClass.toClass(null, null);
- }
-
- private Object newEnhancedInstance0(Class<?> enhancedClass) {
- try {
- return enhancedClass.newInstance();
- } catch (Exception e) {
- throw new UnsupportedOperationException();
- }
- }
-
- public static void main(String[] args) throws Exception {
- DynamicCodeGenerator gen = new DynamicCodeGenerator();
- Image3 src = (Image3) gen.newEnhancedInstance(Image3.class);
- src.title = "msgpack";
- src.uri = "http://msgpack.org/";
- src.width = 2560;
- src.height = 1600;
- src.size = 4096000;
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- src.messagePack(new Packer(out));
- Image3 dst = (Image3) gen.newEnhancedInstance(Image3.class);
- ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
- Unpacker pac = new Unpacker(in);
- dst.messageUnpack(pac);
-
-// System.out.println(dst.equals(src));
- }
-}
diff --git a/java/src/main/java/org/msgpack/tmp/Image1.java b/java/src/main/java/org/msgpack/tmp/Image1.java
deleted file mode 100644
index f1819ed..0000000
--- a/java/src/main/java/org/msgpack/tmp/Image1.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.msgpack.tmp;
-
-import org.msgpack.*;
-import java.io.*;
-
-public class Image1 implements MessagePackable, MessageUnpackable {
- public String uri = "";
- public String title = "";
- public int width = 0;
- public int height = 0;
- public int size = 0;
-
- public void messagePack(Packer pk) throws IOException {
- pk.packArray(5);
- pk.pack(uri);
- pk.pack(title);
- pk.pack(width);
- pk.pack(height);
- pk.pack(size);
- }
-
- public void messageUnpack(Unpacker pac) throws IOException,
- MessageTypeException {
- int length = pac.unpackArray();
- if (length != 5) {
- throw new MessageTypeException();
- }
- uri = pac.unpackString();
- title = pac.unpackString();
- width = pac.unpackInt();
- height = pac.unpackInt();
- size = pac.unpackInt();
- }
-
- public boolean equals(Image1 obj) {
- return uri.equals(obj.uri) && title.equals(obj.title)
- && width == obj.width && height == obj.height
- && size == obj.size;
- }
-
- public boolean equals(Object obj) {
- if (obj.getClass() != Image1.class) {
- return false;
- }
- return equals((Image1) obj);
- }
-}
diff --git a/java/src/main/java/org/msgpack/tmp/Image2.java b/java/src/main/java/org/msgpack/tmp/Image2.java
deleted file mode 100644
index 9c357bf..0000000
--- a/java/src/main/java/org/msgpack/tmp/Image2.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package org.msgpack.tmp;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-
-import org.msgpack.MessageTypeException;
-import org.msgpack.Packer;
-import org.msgpack.Unpacker;
-
-public class Image2 {
- public String uri = "";
- public String title = "";
- public int width = 0;
- public int height = 0;
- public int size = 0;
-
- public void messagePack(Packer pk) throws IOException {
- messagePackWithReflection(pk);
- }
-
- public void messagePackWithReflection(Packer pk) throws IOException {
- Class<?> cl = this.getClass();
- Field[] fields = cl.getFields();
- pk.packArray(fields.length);
- for (Field field : fields) {
- try {
- Object obj = field.get(this);
- pk.pack(obj);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
- }
-
- public void messageUnpack(Unpacker pac) throws IOException,
- MessageTypeException {
- messageUnpackWithReflection(pac);
- }
-
- public void messageUnpackWithReflection(Unpacker pac) throws IOException,
- MessageTypeException {
- Class<?> cl = this.getClass();
- Field[] fields = cl.getFields();
- int length = pac.unpackArray();
- if (length != fields.length) {
- throw new MessageTypeException();
- }
- for (Field field : fields) {
- try {
- field.set(this, unpack(pac, field.getType()));
- } catch (IOException e) {
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
- }
-
- public static Object unpack(Unpacker pk, Class<?> cl) throws IOException {
- if (cl == int.class) {
- return pk.unpackInt();
- } else if (cl == String.class) {
- return pk.unpackString();
- } else {
- throw new UnsupportedOperationException();
- }
- }
-
- public boolean equals(Image2 obj) {
- return uri.equals(obj.uri) && title.equals(obj.title)
- && width == obj.width && height == obj.height
- && size == obj.size;
- }
-
- public boolean equals(Object obj) {
- if (obj.getClass() != Image2.class) {
- return false;
- }
- return equals((Image2) obj);
- }
-}
diff --git a/java/src/main/java/org/msgpack/tmp/Image3.java b/java/src/main/java/org/msgpack/tmp/Image3.java
deleted file mode 100644
index a28ff53..0000000
--- a/java/src/main/java/org/msgpack/tmp/Image3.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.msgpack.tmp;
-
-import java.io.IOException;
-import org.msgpack.MessagePackable;
-import org.msgpack.MessageTypeException;
-import org.msgpack.MessageUnpackable;
-import org.msgpack.Packer;
-import org.msgpack.Unpacker;
-
-public class Image3 implements MessagePackable, MessageUnpackable {
- public String uri = "";
- public String title = "";
- public int width = 0;
- public int height = 0;
- public int size = 0;
-
- public void messagePack(Packer pk) throws IOException {
- // empty
- }
-
- public void messageUnpack(Unpacker pac) throws IOException,
- MessageTypeException {
- // empty
- }
-
- public boolean equals(Image3 obj) {
- return uri.equals(obj.uri) && title.equals(obj.title)
- && width == obj.width && height == obj.height
- && size == obj.size;
- }
-
- public boolean equals(Object obj) {
- if (obj.getClass() != Image3.class) {
- return false;
- }
- return equals((Image3) obj);
- }
-} \ No newline at end of file
diff --git a/java/src/main/java/org/msgpack/tmp/ImagePackUnpackPerfTest.java b/java/src/main/java/org/msgpack/tmp/ImagePackUnpackPerfTest.java
deleted file mode 100644
index 1f27c1b..0000000
--- a/java/src/main/java/org/msgpack/tmp/ImagePackUnpackPerfTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package org.msgpack.tmp;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-
-import org.msgpack.Packer;
-import org.msgpack.Unpacker;
-
-public class ImagePackUnpackPerfTest {
-
- private static int BIG_LOOP = 5;
-
- private static int SMALL_LOOP = 50000;
-
- private static DynamicCodeGenerator gen;
-
- private static void doGc() {
- try {
- Thread.sleep(50L);
- } catch (InterruptedException ie) {
- System.err
- .println("Interrupted while sleeping in serializers.BenchmarkRunner.doGc()");
- }
- System.gc();
- try { // longer sleep afterwards (not needed by GC, but may help with
- // scheduling)
- Thread.sleep(200L);
- } catch (InterruptedException ie) {
- System.err
- .println("Interrupted while sleeping in serializers.BenchmarkRunner.doGc()");
- }
- }
-
- public void doIt(int versionID) {
- try {
- doIt0(versionID);
- } catch (Exception e) {
- e.printStackTrace();
- }
- try {
- for (int j = 0; j < BIG_LOOP; ++j) {
- long t = System.currentTimeMillis();
- doIt0(versionID);
- t = System.currentTimeMillis() - t;
- System.out.println("time: " + t);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void doIt0(int versionID) throws Exception {
- for (int i = 0; i < SMALL_LOOP; ++i) {
- switch (versionID) {
- case 0:
- doCurrentVersion();
- break;
- case 1:
- doWithReflection();
- break;
- case 2:
- doWithDynamicCodeGeneration();
- break;
- default:
- throw new RuntimeException();
- }
- }
- }
-
- public void doCurrentVersion() throws Exception {
- Image1 src = new Image1();
- src.title = "msgpack";
- src.uri = "http://msgpack.org/";
- src.width = 2560;
- src.height = 1600;
- src.size = 4096000;
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- src.messagePack(new Packer(out));
- Image1 dst = new Image1();
- ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
- Unpacker pac = new Unpacker(in);
- dst.messageUnpack(pac);
- }
-
- public void doWithReflection() throws Exception {
- Image2 src = new Image2();
- src.title = "msgpack";
- src.uri = "http://msgpack.org/";
- src.width = 2560;
- src.height = 1600;
- src.size = 4096000;
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- src.messagePack(new Packer(out));
- Image2 dst = new Image2();
- ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
- Unpacker pac = new Unpacker(in);
- dst.messageUnpack(pac);
- }
-
- public void doWithDynamicCodeGeneration() throws Exception {
- Image3 src = (Image3) gen.newEnhancedInstance(Image3.class);
- src.title = "msgpack";
- src.uri = "http://msgpack.org/";
- src.width = 2560;
- src.height = 1600;
- src.size = 4096000;
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- src.messagePack(new Packer(out));
- Image3 dst = (Image3) gen.newEnhancedInstance(Image3.class);
- ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
- Unpacker pac = new Unpacker(in);
- dst.messageUnpack(pac);
- }
-
- public static void main(String[] args) {
- ImagePackUnpackPerfTest test = new ImagePackUnpackPerfTest();
-
- doGc();
- System.out.println("test current version");
- test.doIt(0);
-
- doGc();
- System.out.println("test with reflection");
- test.doIt(1);
-
- doGc();
- System.out.println("test with dynamic codegen");
- gen = new DynamicCodeGenerator();
- test.doIt(2);
- }
-}
diff --git a/java/src/main/java/org/msgpack/util/annotation/MessagePackOptional.java b/java/src/main/java/org/msgpack/util/annotation/MessagePackOptional.java
new file mode 100644
index 0000000..a565292
--- /dev/null
+++ b/java/src/main/java/org/msgpack/util/annotation/MessagePackOptional.java
@@ -0,0 +1,12 @@
+package org.msgpack.util.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.CLASS)
+public @interface MessagePackOptional {
+ int value() default -1;
+} \ No newline at end of file
diff --git a/java/src/main/java/org/msgpack/util/annotation/MessagePackRequired.java b/java/src/main/java/org/msgpack/util/annotation/MessagePackRequired.java
new file mode 100644
index 0000000..03e50cf
--- /dev/null
+++ b/java/src/main/java/org/msgpack/util/annotation/MessagePackRequired.java
@@ -0,0 +1,12 @@
+package org.msgpack.util.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.CLASS)
+public @interface MessagePackRequired {
+ int value() default -1;
+} \ No newline at end of file
diff --git a/java/src/main/java/org/msgpack/util/annotation/MessagePackUnpackable.java b/java/src/main/java/org/msgpack/util/annotation/MessagePackUnpackable.java
new file mode 100644
index 0000000..473b541
--- /dev/null
+++ b/java/src/main/java/org/msgpack/util/annotation/MessagePackUnpackable.java
@@ -0,0 +1,11 @@
+package org.msgpack.util.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.CLASS)
+public @interface MessagePackUnpackable {
+}
diff --git a/java/src/main/java/org/msgpack/util/annotation/PackUnpackUtil.java b/java/src/main/java/org/msgpack/util/annotation/PackUnpackUtil.java
new file mode 100644
index 0000000..37b9e0d
--- /dev/null
+++ b/java/src/main/java/org/msgpack/util/annotation/PackUnpackUtil.java
@@ -0,0 +1,498 @@
+package org.msgpack.util.annotation;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.CtNewConstructor;
+import javassist.CtNewMethod;
+import javassist.NotFoundException;
+
+import org.msgpack.MessageConvertable;
+import org.msgpack.MessagePackable;
+import org.msgpack.MessageTypeException;
+import org.msgpack.MessageUnpackable;
+import org.msgpack.Packer;
+import org.msgpack.Unpacker;
+
+public class PackUnpackUtil {
+ static class Constants {
+ static final String POSTFIX_TYPE_NAME_ENHANCER = "_$$_Enhanced";
+
+ static final String KEYWORD_MODIFIER_PUBLIC = "public";
+
+ static final String KEYWORD_THROWS = "throws";
+
+ static final String TYPE_NAME_VOID = void.class.getName();
+
+ static final String TYPE_NAME_BOOLEAN = boolean.class.getName();
+
+ static final String TYPE_NAME_BYTE = byte.class.getName();
+
+ static final String TYPE_NAME_DOUBLE = double.class.getName();
+
+ static final String TYPE_NAME_FLOAT = float.class.getName();
+
+ static final String TYPE_NAME_INT = int.class.getName();
+
+ static final String TYPE_NAME_LONG = long.class.getName();
+
+ static final String TYPE_NAME_SHORT = short.class.getName();
+
+ static final String TYPE_NAME_OBJECT = Object.class.getName();
+
+ static final String TYPE_NAME_BIGINTEGER = BigInteger.class.getName();
+
+ static final String TYPE_NAME_STRING = String.class.getName();
+
+ static final String TYPE_NAME_BOOLEAN2 = Boolean.class.getName();
+
+ static final String TYPE_NAME_BYTE2 = Byte.class.getName();
+
+ static final String TYPE_NAME_DOUBLE2 = Double.class.getName();
+
+ static final String TYPE_NAME_FLOAT2 = Float.class.getName();
+
+ static final String TYPE_NAME_INT2 = Integer.class.getName();
+
+ static final String TYPE_NAME_LONG2 = Long.class.getName();
+
+ static final String TYPE_NAME_SHORT2 = Short.class.getName();
+
+ static final String TYPE_NAME_BYTEARRAY = byte[].class.getName();
+
+ static final String TYPE_NAME_LIST = List.class.getName();
+
+ static final String TYPE_NAME_MAP = Map.class.getName();
+
+ static final String TYPE_NAME_IOEXCEPTION = IOException.class.getName();
+
+ static final String TYPE_NAME_PACKER = Packer.class.getName();
+
+ static final String TYPE_NAME_UNPACKER = Unpacker.class.getName();
+
+ static final String TYPE_NAME_MSGPACKABLE = MessagePackable.class
+ .getName();
+
+ static final String TYPE_NAME_MSGUNPACKABLE = MessageUnpackable.class
+ .getName();
+
+ static final String TYPE_NAME_MSGCONVERTABLE = MessageConvertable.class
+ .getName();
+
+ static final String TYPE_NAME_MSGTYPEEXCEPTION = MessageTypeException.class
+ .getName();
+
+ static final String TYPE_NAME_MSGPACKUNPACKABLE = MessagePackUnpackable.class
+ .getName();
+
+ static final String TYPE_NAME_MSGPACKOPTIONAL = MessagePackOptional.class
+ .getName();
+
+ static final String TYPE_NAME_MSGPACKOREQUIRED = MessagePackRequired.class
+ .getName();
+
+ static final String CHAR_NAME_SPACE = " ";
+
+ static final String CHAR_NAME_COMMA = ",";
+
+ static final String CHAR_NAME_EQUAL = "=";
+
+ static final String CHAR_NAME_RIGHT_PARENTHESIS = ")";
+
+ static final String CHAR_NAME_LEFT_PARENTHESIS = "(";
+
+ static final String CHAR_NAME_RIGHT_CURLY_BRACHET = "}";
+
+ static final String CHAR_NAME_LEFT_CURLY_BRACHET = "{";
+
+ static final String CHAR_NAME_DOT = ".";
+
+ static final String CHAR_NAME_SEMICOLON = ";";
+
+ static final String VARIABLE_NAME_PK = "pk";
+
+ static final String VARIABLE_NAME_OBJ = "obj";
+
+ static final String METHOD_NAME_MSGPACK = "messagePack";
+
+ static final String METHOD_NAME_MSGUNPACK = "messageUnpack";
+
+ static final String METHOD_NAME_MSGCONVERT = "messageConvert";
+
+ static final String METHOD_NAME_PACK = "pack";
+
+ static final String METHOD_NAME_PACKARRAY = "packArray";
+
+ static final String METHOD_NAME_UNPACK = "unpack";
+
+ static final String METHOD_NAME_UNPACKBOOLEAN = "unpackBoolean";
+
+ static final String METHOD_NAME_UNPACKBYTE = "unpackByte";
+
+ static final String METHOD_NAME_UNPACKDOUBLE = "unpackDouble";
+
+ static final String METHOD_NAME_UNPACKFLOAT = "unpackFloat";
+
+ static final String METHOD_NAME_UNPACKINT = "unpackInt";
+
+ static final String METHOD_NAME_UNPACKLONG = "unpackLong";
+
+ static final String METHOD_NAME_UNPACKSHORT = "unpackShort";
+
+ static final String METHOD_NAME_UNPACKSTRING = "unpackString";
+
+ static final String METHOD_NAME_UNPACKBIGINTEGER = "unpackBigInteger";
+
+ static final String METHOD_NAME_UNPACKOBJECT = "unpackObject";
+
+ static final String METHOD_NAME_UNPACKBYTEARRAY = "unpackByteArray";
+
+ static final String METHOD_NAME_UNPACKARRAY = "unpackArray";
+
+ static final String METHOD_NAME_UNPACKMAP = "unpackMap";
+ }
+
+ public static class Enhancer {
+
+ private ConcurrentHashMap<String, Class<?>> classCache;
+
+ private ClassPool pool;
+
+ protected Enhancer() {
+ classCache = new ConcurrentHashMap<String, Class<?>>();
+ pool = ClassPool.getDefault();
+ }
+
+ protected Class<?> getCache(String origName) {
+ return classCache.get(origName);
+ }
+
+ protected void setCache(String origName, Class<?> enhClass) {
+ classCache.putIfAbsent(origName, enhClass);
+ }
+
+ protected Class<?> generate(Class<?> origClass)
+ throws NotFoundException, CannotCompileException {
+ String origName = origClass.getName();
+ String enhName = origName + Constants.POSTFIX_TYPE_NAME_ENHANCER;
+ CtClass origCtClass = pool.get(origName);
+ checkPackUnpackAnnotation(origCtClass);
+ CtClass enhCtClass = pool.makeClass(enhName);
+ setSuperclass(enhCtClass, origCtClass);
+ setInterfaces(enhCtClass);
+ addConstructor(enhCtClass);
+ addMessagePackMethod(enhCtClass, origCtClass);
+ addMessageUnpackMethod(enhCtClass, origCtClass);
+ addMessageConvertMethod(enhCtClass, origCtClass);
+ return createClass(enhCtClass);
+ }
+
+ private void checkPackUnpackAnnotation(CtClass origCtClass) {
+ try {
+ Object[] objs = origCtClass.getAnnotations();
+ for (Object obj : objs) {
+ if (obj instanceof MessagePackUnpackable) {
+ return;
+ }
+ }
+ throw new PackUnpackUtilException(
+ "Not annotated with this class: "
+ + origCtClass.getName());
+ } catch (ClassNotFoundException e) {
+ throw new PackUnpackUtilException(e.getMessage(), e);
+ }
+ }
+
+ private void setSuperclass(CtClass enhCtClass, CtClass origCtClass)
+ throws CannotCompileException {
+ enhCtClass.setSuperclass(origCtClass);
+ }
+
+ private void setInterfaces(CtClass enhCtClass) throws NotFoundException {
+ CtClass pacCtClass = pool.get(Constants.TYPE_NAME_MSGPACKABLE);
+ enhCtClass.addInterface(pacCtClass);
+ CtClass unpacCtClass = pool.get(Constants.TYPE_NAME_MSGUNPACKABLE);
+ enhCtClass.addInterface(unpacCtClass);
+ CtClass convCtClass = pool.get(Constants.TYPE_NAME_MSGCONVERTABLE);
+ enhCtClass.addInterface(convCtClass);
+ }
+
+ private void addConstructor(CtClass enhCtClass)
+ throws CannotCompileException {
+ CtConstructor newCtCons = CtNewConstructor
+ .defaultConstructor(enhCtClass);
+ enhCtClass.addConstructor(newCtCons);
+ }
+
+ private void addMessagePackMethod(CtClass enhCtClass,
+ CtClass origCtClass) throws CannotCompileException,
+ NotFoundException {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Constants.KEYWORD_MODIFIER_PUBLIC).append(
+ Constants.CHAR_NAME_SPACE).append(Constants.TYPE_NAME_VOID)
+ .append(Constants.CHAR_NAME_SPACE).append(
+ Constants.METHOD_NAME_MSGPACK).append(
+ Constants.CHAR_NAME_LEFT_PARENTHESIS).append(
+ Constants.TYPE_NAME_PACKER).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.VARIABLE_NAME_PK).append(
+ Constants.CHAR_NAME_RIGHT_PARENTHESIS).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.KEYWORD_THROWS).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.TYPE_NAME_IOEXCEPTION).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.CHAR_NAME_LEFT_CURLY_BRACHET).append(
+ Constants.CHAR_NAME_SPACE);
+ CtField[] fields = origCtClass.getDeclaredFields();
+ sb.append(Constants.VARIABLE_NAME_PK).append(
+ Constants.CHAR_NAME_DOT).append(
+ Constants.METHOD_NAME_PACKARRAY).append(
+ Constants.CHAR_NAME_LEFT_PARENTHESIS).append(fields.length)
+ .append(Constants.CHAR_NAME_RIGHT_PARENTHESIS).append(
+ Constants.CHAR_NAME_SEMICOLON).append(
+ Constants.CHAR_NAME_SPACE);
+ for (CtField field : fields) {
+ insertCodeOfMessagePack(field, sb);
+ }
+ sb.append(Constants.CHAR_NAME_RIGHT_CURLY_BRACHET);
+ System.out.println("messagePack method: " + sb.toString());
+ CtMethod newCtMethod = CtNewMethod.make(sb.toString(), enhCtClass);
+ enhCtClass.addMethod(newCtMethod);
+ }
+
+ private void insertCodeOfMessagePack(CtField field, StringBuilder sb)
+ throws NotFoundException {
+ sb.append(Constants.VARIABLE_NAME_PK).append(
+ Constants.CHAR_NAME_DOT).append(Constants.METHOD_NAME_PACK)
+ .append(Constants.CHAR_NAME_LEFT_PARENTHESIS).append(
+ field.getName()).append(
+ Constants.CHAR_NAME_RIGHT_PARENTHESIS).append(
+ Constants.CHAR_NAME_SEMICOLON).append(
+ Constants.CHAR_NAME_SPACE);
+ }
+
+ private void addMessageUnpackMethod(CtClass enhCtClass,
+ CtClass origCtClass) throws CannotCompileException,
+ NotFoundException {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Constants.KEYWORD_MODIFIER_PUBLIC).append(
+ Constants.CHAR_NAME_SPACE).append(Constants.TYPE_NAME_VOID)
+ .append(Constants.CHAR_NAME_SPACE).append(
+ Constants.METHOD_NAME_MSGUNPACK).append(
+ Constants.CHAR_NAME_LEFT_PARENTHESIS).append(
+ Constants.TYPE_NAME_UNPACKER).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.VARIABLE_NAME_PK).append(
+ Constants.CHAR_NAME_RIGHT_PARENTHESIS).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.KEYWORD_THROWS).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.TYPE_NAME_MSGTYPEEXCEPTION).append(
+ Constants.CHAR_NAME_COMMA).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.TYPE_NAME_IOEXCEPTION).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.CHAR_NAME_LEFT_CURLY_BRACHET).append(
+ Constants.CHAR_NAME_SPACE);
+ CtField[] fields = origCtClass.getFields();
+ sb.append(Constants.VARIABLE_NAME_PK).append(
+ Constants.CHAR_NAME_DOT).append(
+ Constants.METHOD_NAME_UNPACKARRAY).append(
+ Constants.CHAR_NAME_LEFT_PARENTHESIS).append(
+ Constants.CHAR_NAME_RIGHT_PARENTHESIS).append(
+ Constants.CHAR_NAME_SEMICOLON).append(
+ Constants.CHAR_NAME_SPACE);
+ for (CtField field : fields) {
+ insertCodeOfMessageUnpack(field, sb);
+ }
+ sb.append(Constants.CHAR_NAME_RIGHT_CURLY_BRACHET);
+ System.out.println("messageUnpack method: " + sb.toString());
+ CtMethod newCtMethod = CtNewMethod.make(sb.toString(), enhCtClass);
+ enhCtClass.addMethod(newCtMethod);
+ }
+
+ private void insertCodeOfMessageUnpack(CtField field, StringBuilder sb)
+ throws NotFoundException {
+ CtClass type = field.getType();
+ sb.append(field.getName()).append(Constants.CHAR_NAME_SPACE)
+ .append(Constants.CHAR_NAME_EQUAL).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.VARIABLE_NAME_PK).append(
+ Constants.CHAR_NAME_DOT);
+ if (type.equals(CtClass.booleanType)) { // boolean
+ sb.append(Constants.METHOD_NAME_UNPACKBOOLEAN);
+ } else if (type.equals(CtClass.byteType)) { // byte
+ sb.append(Constants.METHOD_NAME_UNPACKBYTE);
+ } else if (type.equals(CtClass.doubleType)) { // double
+ sb.append(Constants.METHOD_NAME_UNPACKDOUBLE);
+ } else if (type.equals(CtClass.floatType)) { // float
+ sb.append(Constants.METHOD_NAME_UNPACKFLOAT);
+ } else if (type.equals(CtClass.intType)) { // int
+ sb.append(Constants.METHOD_NAME_UNPACKINT);
+ } else if (type.equals(CtClass.longType)) { // long
+ sb.append(Constants.METHOD_NAME_UNPACKLONG);
+ } else if (type.equals(CtClass.shortType)) { // short
+ sb.append(Constants.METHOD_NAME_UNPACKSHORT);
+ } else { // reference type
+ if (type.equals(pool.get(Constants.TYPE_NAME_BOOLEAN2))) { // Boolean
+ sb.append(Constants.METHOD_NAME_UNPACKBOOLEAN);
+ } else if (type.equals(pool.get(Constants.TYPE_NAME_BYTE2))) { // Byte
+ sb.append(Constants.METHOD_NAME_UNPACKBYTE);
+ } else if (type.equals(pool.get(Constants.TYPE_NAME_DOUBLE2))) { // Double
+ sb.append(Constants.METHOD_NAME_UNPACKDOUBLE);
+ } else if (type.equals(pool.get(Constants.TYPE_NAME_FLOAT2))) { // Float
+ sb.append(Constants.METHOD_NAME_UNPACKFLOAT);
+ } else if (type.equals(pool.get(Constants.TYPE_NAME_INT2))) { // Integer
+ sb.append(Constants.METHOD_NAME_UNPACKINT);
+ } else if (type.equals(pool.get(Constants.TYPE_NAME_LONG2))) { // Long
+ sb.append(Constants.METHOD_NAME_UNPACKLONG);
+ } else if (type.equals(pool.get(Constants.TYPE_NAME_SHORT2))) { // Short
+ sb.append(Constants.METHOD_NAME_UNPACKSHORT);
+ } else if (type
+ .equals(pool.get(Constants.TYPE_NAME_BIGINTEGER))) { // BigInteger
+ sb.append(Constants.METHOD_NAME_UNPACKBIGINTEGER);
+ } else if (type.equals(pool.get(Constants.TYPE_NAME_STRING))) { // String
+ sb.append(Constants.METHOD_NAME_UNPACKSTRING);
+ } else if (type.equals(pool.get(Constants.TYPE_NAME_BYTEARRAY))) { // byte[]
+ sb.append(Constants.METHOD_NAME_UNPACKBYTEARRAY);
+ } else if (type.subtypeOf(pool.get(Constants.TYPE_NAME_LIST))) { // List
+ sb.append(Constants.METHOD_NAME_UNPACKARRAY);
+ } else if (type.subtypeOf(pool.get(Constants.TYPE_NAME_MAP))) { // Map
+ sb.append(Constants.METHOD_NAME_UNPACKMAP);
+ } else if (type.subtypeOf(pool
+ .get(Constants.TYPE_NAME_MSGUNPACKABLE))) { // MessageUnpackable
+ sb.append(Constants.METHOD_NAME_UNPACKOBJECT);
+ } else {
+ throw new NotFoundException("unknown type: "
+ + type.getName());
+ }
+ }
+ sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS).append(
+ Constants.CHAR_NAME_RIGHT_PARENTHESIS).append(
+ Constants.CHAR_NAME_SEMICOLON).append(
+ Constants.CHAR_NAME_SPACE);
+ }
+
+ private void addMessageConvertMethod(CtClass enhCtClass,
+ CtClass origCtClass) throws CannotCompileException {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Constants.KEYWORD_MODIFIER_PUBLIC).append(
+ Constants.CHAR_NAME_SPACE).append(Constants.TYPE_NAME_VOID)
+ .append(Constants.CHAR_NAME_SPACE).append(
+ Constants.METHOD_NAME_MSGCONVERT).append(
+ Constants.CHAR_NAME_LEFT_PARENTHESIS).append(
+ Constants.TYPE_NAME_OBJECT).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.VARIABLE_NAME_OBJ).append(
+ Constants.CHAR_NAME_RIGHT_PARENTHESIS).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.KEYWORD_THROWS).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.TYPE_NAME_MSGTYPEEXCEPTION).append(
+ Constants.CHAR_NAME_SPACE).append(
+ Constants.CHAR_NAME_LEFT_CURLY_BRACHET).append(
+ Constants.CHAR_NAME_SPACE);
+ // TODO
+ sb.append(Constants.CHAR_NAME_RIGHT_CURLY_BRACHET);
+ System.out.println("messageConvert method: " + sb.toString());
+ CtMethod newCtMethod = CtNewMethod.make(sb.toString(), enhCtClass);
+ enhCtClass.addMethod(newCtMethod);
+ }
+
+ private Class<?> createClass(CtClass enhCtClass)
+ throws CannotCompileException {
+ return enhCtClass.toClass(null, null);
+ }
+ }
+
+ private static Enhancer enhancer;
+
+ public static Class<?> getEnhancedClass(Class<?> origClass) {
+ if (enhancer == null) {
+ enhancer = new Enhancer();
+ }
+
+ String origName = origClass.getName();
+ Class<?> enhClass = enhancer.getCache(origName);
+ if (enhClass == null) {
+ // generate a class object related to the original class
+ try {
+ enhClass = enhancer.generate(origClass);
+ } catch (NotFoundException e) {
+ throw new PackUnpackUtilException(e.getMessage(), e);
+ } catch (CannotCompileException e) {
+ throw new PackUnpackUtilException(e.getMessage(), e);
+ }
+ // set the generated class to the cache
+ enhancer.setCache(origName, enhClass);
+ }
+ return enhClass;
+ }
+
+ public static Object newEnhancedInstance(Class<?> origClass) {
+ try {
+ Class<?> enhClass = getEnhancedClass(origClass);
+ // create a new object of the generated class
+ return enhClass.newInstance();
+ } catch (InstantiationException e) {
+ throw new PackUnpackUtilException(e.getMessage(), e);
+ } catch (IllegalAccessException e) {
+ throw new PackUnpackUtilException(e.getMessage(), e);
+ }
+ }
+
+ public static void main(final String[] args) throws Exception {
+ @MessagePackUnpackable
+ class Image {
+ public String uri = "";
+
+ public String title = "";
+
+ public int width = 0;
+
+ public int height = 0;
+
+ public int size = 0;
+
+ public boolean equals(Image obj) {
+ return uri.equals(obj.uri) && title.equals(obj.title)
+ && width == obj.width && height == obj.height
+ && size == obj.size;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj.getClass() != Image.class) {
+ return false;
+ }
+ return equals((Image) obj);
+ }
+ }
+
+ PackUnpackUtil.getEnhancedClass(Image.class);
+ Image src = (Image) PackUnpackUtil.newEnhancedInstance(Image.class);
+ src.title = "msgpack";
+ src.uri = "http://msgpack.org/";
+ src.width = 2560;
+ src.height = 1600;
+ src.size = 4096000;
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ new Packer(out).pack(src);
+ Image dst = (Image) PackUnpackUtil.newEnhancedInstance(Image.class);
+ ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+ Unpacker pac = new Unpacker(in);
+ pac.unpack((MessageUnpackable) dst);
+ System.out.println(src.equals(dst));
+ }
+}
diff --git a/java/src/main/java/org/msgpack/util/annotation/PackUnpackUtilException.java b/java/src/main/java/org/msgpack/util/annotation/PackUnpackUtilException.java
new file mode 100644
index 0000000..df3af05
--- /dev/null
+++ b/java/src/main/java/org/msgpack/util/annotation/PackUnpackUtilException.java
@@ -0,0 +1,12 @@
+package org.msgpack.util.annotation;
+
+public class PackUnpackUtilException extends RuntimeException {
+
+ public PackUnpackUtilException(String reason) {
+ super(reason);
+ }
+
+ public PackUnpackUtilException(String reason, Throwable t) {
+ super(reason, t);
+ }
+}