diff --git a/java/src/main/java/org/msgpack/MessageUnpacker.java b/java/src/main/java/org/msgpack/MessageUnpacker.java index 18172697..2a89e457 100644 --- a/java/src/main/java/org/msgpack/MessageUnpacker.java +++ b/java/src/main/java/org/msgpack/MessageUnpacker.java @@ -20,6 +20,6 @@ package org.msgpack; import java.io.IOException; public interface MessageUnpacker { - public Object unpack(Unpacker pac) throws IOException, MessageTypeException; + Object unpack(Unpacker pac) throws IOException, MessageTypeException; } diff --git a/java/src/main/java/org/msgpack/Packer.java b/java/src/main/java/org/msgpack/Packer.java index 9ea4ea21..52bd29de 100644 --- a/java/src/main/java/org/msgpack/Packer.java +++ b/java/src/main/java/org/msgpack/Packer.java @@ -22,7 +22,6 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.List; import java.util.Map; -import java.lang.annotation.Annotation; import java.math.BigInteger; import org.msgpack.annotation.MessagePackDelegate; diff --git a/java/src/main/java/org/msgpack/Unpacker.java b/java/src/main/java/org/msgpack/Unpacker.java index 33c7d4ce..d91fc0ef 100644 --- a/java/src/main/java/org/msgpack/Unpacker.java +++ b/java/src/main/java/org/msgpack/Unpacker.java @@ -18,7 +18,6 @@ package org.msgpack; import java.lang.Iterable; -import java.lang.annotation.Annotation; import java.io.InputStream; import java.io.IOException; import java.util.Iterator; diff --git a/java/src/main/java/org/msgpack/util/codegen/BasicConstants.java b/java/src/main/java/org/msgpack/util/codegen/BasicConstants.java index 53a8a4ce..f675f815 100644 --- a/java/src/main/java/org/msgpack/util/codegen/BasicConstants.java +++ b/java/src/main/java/org/msgpack/util/codegen/BasicConstants.java @@ -2,29 +2,31 @@ package org.msgpack.util.codegen; public interface BasicConstants { - String KEYWORD_MODIFIER_PUBLIC = "public"; + String KEYWORD_MODIFIER_PUBLIC = "public"; - String KEYWORD_CATCH = "catch"; + String KEYWORD_CATCH = "catch"; - String KEYWORD_ELSE = "else"; + String KEYWORD_ELSE = "else"; - String KEYWORD_ELSEIF = "else if"; + String KEYWORD_ELSEIF = "else if"; - String KEYWORD_FOR = "for"; + String KEYWORD_FOR = "for"; - String KEYWORD_IF = "if"; + String KEYWORD_IF = "if"; - String KEYWORD_INSTANCEOF = "instanceof"; + String KEYWORD_INSTANCEOF = "instanceof"; - String KEYWORD_NEW = "new"; + String KEYWORD_NEW = "new"; - String KEYWORD_NULL = "null"; + String KEYWORD_NULL = "null"; + + String KEYWORD_RETURN = "return"; - String KEYWORD_THROW = "throw"; + String KEYWORD_THROW = "throw"; - String KEYWORD_THROWS = "throws"; + String KEYWORD_THROWS = "throws"; - String KEYWORD_TRY = "try"; + String KEYWORD_TRY = "try"; String CHAR_NAME_SPACE = " "; @@ -34,28 +36,30 @@ public interface BasicConstants { String CHAR_NAME_PLUS = "+"; + String CHAR_NAME_MINUS = "-"; + String CHAR_NAME_LESSTHAN = "<"; - String CHAR_NAME_RIGHT_PARENTHESIS = ")"; + String CHAR_NAME_RIGHT_PARENTHESIS = ")"; - String CHAR_NAME_LEFT_PARENTHESIS = "("; + String CHAR_NAME_LEFT_PARENTHESIS = "("; - String CHAR_NAME_RIGHT_CURLY_BRACKET = "}"; + String CHAR_NAME_RIGHT_CURLY_BRACKET = "}"; - String CHAR_NAME_LEFT_CURLY_BRACKET = "{"; + String CHAR_NAME_LEFT_CURLY_BRACKET = "{"; - String CHAR_NAME_RIGHT_SQUARE_BRACKET = "]"; + String CHAR_NAME_RIGHT_SQUARE_BRACKET = "]"; - String CHAR_NAME_LEFT_SQUARE_BRACKET = "["; + String CHAR_NAME_LEFT_SQUARE_BRACKET = "["; String CHAR_NAME_DOT = "."; String CHAR_NAME_SEMICOLON = ";"; String VARIABLE_NAME_PK = "_$$_pk"; - - String VARIABLE_NAME_OBJ = "_$$_obj"; - + + String VARIABLE_NAME_OBJECT = "_$$_obj"; + String VARIABLE_NAME_TARGET = "_$$_target"; String VARIABLE_NAME_SIZE = "_$$_len"; @@ -153,8 +157,8 @@ public interface BasicConstants { String METHOD_NAME_ASBYTEARRAY = "asByteArray"; String METHOD_NAME_ASBIGINTEGER = "asBigInteger"; - + String METHOD_NAME_ASLIST = "asList"; - + String METHOD_NAME_ASMAP = "asMap"; } diff --git a/java/src/main/java/org/msgpack/util/codegen/Constants.java b/java/src/main/java/org/msgpack/util/codegen/Constants.java index ddeef31f..22265946 100644 --- a/java/src/main/java/org/msgpack/util/codegen/Constants.java +++ b/java/src/main/java/org/msgpack/util/codegen/Constants.java @@ -2,6 +2,8 @@ package org.msgpack.util.codegen; public interface Constants extends BasicConstants { String POSTFIX_TYPE_NAME_PACKER = "_$$_Packer"; - - String POSTFIX_TYPE_NAME_ENHANCER = "_$$_Enhanced"; + + String POSTFIX_TYPE_NAME_UNPACKER = "_$$_Unpacker"; + + String POSTFIX_TYPE_NAME_TEMPLATE = "_$$_Template"; } diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java index 9f63242d..bd010eac 100644 --- a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java +++ b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java @@ -4,8 +4,12 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.math.BigInteger; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import javassist.CannotCompileException; @@ -17,15 +21,24 @@ import javassist.CtNewConstructor; import javassist.CtNewMethod; import javassist.NotFoundException; +import org.msgpack.MessagePackObject; import org.msgpack.MessagePacker; +import org.msgpack.MessageTypeException; +import org.msgpack.MessageUnpackable; +import org.msgpack.MessageUnpacker; import org.msgpack.Packer; import org.msgpack.Template; +import org.msgpack.Unpacker; public class DynamicCodeGen extends DynamicCodeGenBase implements Constants { private static DynamicCodeGen INSTANCE; - private static AtomicInteger COUNTER; + private static AtomicInteger COUNTER = new AtomicInteger(0); + + private static int inc() { + return COUNTER.addAndGet(1); + } public static DynamicCodeGen getInstance() { if (INSTANCE == null) { @@ -43,7 +56,7 @@ public class DynamicCodeGen extends DynamicCodeGenBase implements Constants { public Class generateMessagePackerClass(Class origClass) { try { String origName = origClass.getName(); - String packerName = origName + POSTFIX_TYPE_NAME_PACKER; + String packerName = origName + POSTFIX_TYPE_NAME_PACKER + inc(); checkClassValidation(origClass); checkDefaultConstructorValidation(origClass); CtClass packerCtClass = pool.makeClass(packerName); @@ -59,18 +72,38 @@ public class DynamicCodeGen extends DynamicCodeGenBase implements Constants { } } + public Class generateMessageUnpackerClass(Class origClass) { + try { + String origName = origClass.getName(); + String unpackerName = origName + POSTFIX_TYPE_NAME_UNPACKER + inc(); + checkClassValidation(origClass); + checkDefaultConstructorValidation(origClass); + CtClass unpackerCtClass = pool.makeClass(unpackerName); + setInterface(unpackerCtClass, MessageUnpacker.class); + addDefaultConstructor(unpackerCtClass); + Field[] fields = getDeclaredFields(origClass); + addUnpackMethod(unpackerCtClass, origClass, fields); + return createClass(unpackerCtClass); + } catch (NotFoundException e) { + throw new DynamicCodeGenException(e.getMessage(), e); + } catch (CannotCompileException e) { + throw new DynamicCodeGenException(e.getMessage(), e); + } + } + public Class generateTemplateClass(Class origClass) { try { String origName = origClass.getName(); - String packerName = origName + POSTFIX_TYPE_NAME_PACKER; + String tmplName = origName + POSTFIX_TYPE_NAME_TEMPLATE + inc(); checkClassValidation(origClass); checkDefaultConstructorValidation(origClass); - CtClass packerCtClass = pool.makeClass(packerName); - setInterface(packerCtClass, Template.class); - addDefaultConstructor(packerCtClass); + CtClass tmplCtClass = pool.makeClass(tmplName); + setInterface(tmplCtClass, Template.class); + addDefaultConstructor(tmplCtClass); Field[] fields = getDeclaredFields(origClass); - addPackMethod(packerCtClass, origClass, fields); - return createClass(packerCtClass); + addUnpackMethod(tmplCtClass, origClass, fields); + addConvertMethod(tmplCtClass, origClass, fields); + return createClass(tmplCtClass); } catch (NotFoundException e) { throw new DynamicCodeGenException(e.getMessage(), e); } catch (CannotCompileException e) { @@ -172,31 +205,13 @@ public class DynamicCodeGen extends DynamicCodeGenBase implements Constants { private void addPackMethod(CtClass packerCtClass, Class c, Field[] fs) throws CannotCompileException, NotFoundException { StringBuilder sb = new StringBuilder(); - sb.append(KEYWORD_MODIFIER_PUBLIC); - sb.append(CHAR_NAME_SPACE); - sb.append(void.class.getName()); - sb.append(CHAR_NAME_SPACE); - sb.append(METHOD_NAME_PACK); - sb.append(CHAR_NAME_LEFT_PARENTHESIS); - sb.append(Packer.class.getName()); - sb.append(CHAR_NAME_SPACE); - sb.append(VARIABLE_NAME_PK); - sb.append(CHAR_NAME_COMMA); - sb.append(CHAR_NAME_SPACE); - sb.append(Object.class.getName()); - sb.append(CHAR_NAME_SPACE); - sb.append(VARIABLE_NAME_OBJ); - sb.append(CHAR_NAME_RIGHT_PARENTHESIS); - sb.append(CHAR_NAME_SPACE); - sb.append(KEYWORD_THROWS); - sb.append(CHAR_NAME_SPACE); - sb.append(IOException.class.getName()); - sb.append(CHAR_NAME_SPACE); - sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); - sb.append(CHAR_NAME_SPACE); - insertPackMethodBody(sb, c, fs); - sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); - // System.out.println("pack method: " + sb.toString()); + StringBuilder bsb = new StringBuilder(); + insertPackMethodBody(bsb, c, fs); + addPublicMethodDecl(sb, METHOD_NAME_PACK, void.class, new Class[] { + Packer.class, Object.class }, new String[] { VARIABLE_NAME_PK, + VARIABLE_NAME_OBJECT }, new Class[] { IOException.class }, bsb + .toString()); + System.out.println("pack method: " + sb.toString()); CtMethod newCtMethod = CtNewMethod.make(sb.toString(), packerCtClass); packerCtClass.addMethod(newCtMethod); } @@ -204,7 +219,7 @@ public class DynamicCodeGen extends DynamicCodeGenBase implements Constants { private void insertPackMethodBody(StringBuilder sb, Class c, Field[] fs) { insertLocalVariableDecl(sb, c, VARIABLE_NAME_TARGET); StringBuilder mc = new StringBuilder(); - insertTypeCast(mc, c, VARIABLE_NAME_OBJ); + insertTypeCast(mc, c, VARIABLE_NAME_OBJECT); insertValueInsertion(sb, mc.toString()); insertSemicolon(sb); insertMethodCall(sb, VARIABLE_NAME_PK, METHOD_NAME_PACKARRAY, @@ -225,6 +240,319 @@ public class DynamicCodeGen extends DynamicCodeGenBase implements Constants { insertSemicolon(sb); } + private void addUnpackMethod(CtClass unpackerCtClass, Class c, Field[] fs) + throws CannotCompileException, NotFoundException { + // Object unpack(Unpacker pac) throws IOException, MessageTypeException; + StringBuilder sb = new StringBuilder(); + StringBuilder bsb = new StringBuilder(); + insertUnpackMethodBody(bsb, c, fs); + addPublicMethodDecl(sb, METHOD_NAME_UNPACK, Object.class, + new Class[] { Unpacker.class }, + new String[] { VARIABLE_NAME_PK }, new Class[] { + MessageTypeException.class, IOException.class }, bsb + .toString()); + System.out.println("unpack method: " + sb.toString()); + CtMethod newCtMethod = CtNewMethod.make(sb.toString(), unpackerCtClass); + unpackerCtClass.addMethod(newCtMethod); + } + + private void insertUnpackMethodBody(StringBuilder sb, Class c, Field[] fs) { + insertLocalVariableDecl(sb, c, VARIABLE_NAME_TARGET); + StringBuilder mc = new StringBuilder(); + insertDefaultConsCall(mc, c); + insertValueInsertion(sb, mc.toString()); + insertSemicolon(sb); + insertMethodCall(sb, VARIABLE_NAME_PK, METHOD_NAME_UNPACKARRAY, + new String[0]); + insertSemicolon(sb); + for (Field f : fs) { + insertCodeOfUnpackMethodCall(sb, f, f.getType()); + } + insertReturnStat(sb, VARIABLE_NAME_TARGET); + insertSemicolon(sb); + } + + private void insertCodeOfUnpackMethodCall(StringBuilder sb, Field f, + Class c) { + if (c.isPrimitive()) { + // primitive type + insertCodeOfUnpackMethodCallForPrimTypes(sb, f, c); + } else if (c.equals(Boolean.class) || // Boolean + c.equals(Byte.class) || // Byte + c.equals(Double.class) || // Double + c.equals(Float.class) || // Float + c.equals(Integer.class) || // Integer + c.equals(Long.class) || // Long + c.equals(Short.class)) { // Short + // reference type (wrapper type) + insertCodeOfUnpackMethodCallForWrapTypes(sb, f, c); + } else if (c.equals(BigInteger.class) || // BigInteger + c.equals(String.class) || // String + c.equals(byte[].class)) { // byte[] + // reference type (other type) + insertCodeOfUnpackMethodCallForPrimTypes(sb, f, c); + } else if (List.class.isAssignableFrom(c)) { + // List + insertCodeOfUnpackMethodCallForListType(sb, f, c); + } else if (Map.class.isAssignableFrom(c)) { + // Map + insertCodeOfUnpackMethodCallForMapType(sb, f, c); + } else if (MessageUnpackable.class.isAssignableFrom(c)) { + // MessageUnpackable + insertCodeOfMessageUnpackCallForMsgUnpackableType(sb, f, c); + } else { + throw new MessageTypeException("unknown type: " + c.getName()); + } + } + + private void insertCodeOfUnpackMethodCallForPrimTypes(StringBuilder sb, + Field f, Class c) { + if (f != null) { + sb.append(VARIABLE_NAME_TARGET); + sb.append(CHAR_NAME_DOT); + sb.append(f.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + } + insertMethodCall(sb, VARIABLE_NAME_PK, getUnpackMethodName(c), + new String[0]); + if (f != null) { + insertSemicolon(sb); + } + } + + private void insertCodeOfUnpackMethodCallForWrapTypes(StringBuilder sb, + Field f, Class c) { + if (f != null) { + sb.append(VARIABLE_NAME_TARGET); + sb.append(f.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + } + StringBuilder mc = new StringBuilder(); + insertMethodCall(mc, VARIABLE_NAME_PK, getUnpackMethodName(c), + new String[0]); + insertMethodCall(sb, c.getName(), METHOD_NAME_VALUEOF, + new String[] { mc.toString() }); + if (f != null) { + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + } + } + + private void insertCodeOfUnpackMethodCallForListType(StringBuilder sb, + Field field, Class type) { + ParameterizedType generic = (ParameterizedType) field.getGenericType(); + Class genericType = (Class) generic.getActualTypeArguments()[0]; + + // len + sb.append(int.class.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(VARIABLE_NAME_SIZE); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + sb.append(VARIABLE_NAME_PK); + sb.append(CHAR_NAME_DOT); + sb.append(METHOD_NAME_UNPACKARRAY); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + + // field initializer + sb.append(field.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + sb.append(KEYWORD_NEW); + sb.append(CHAR_NAME_SPACE); + sb.append(ArrayList.class.getName()); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + + // for loop + sb.append(KEYWORD_FOR); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(int.class.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(VARIABLE_NAME_I); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + sb.append(0); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + sb.append(VARIABLE_NAME_I); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LESSTHAN); + sb.append(CHAR_NAME_SPACE); + sb.append(VARIABLE_NAME_SIZE); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_PLUS); + sb.append(CHAR_NAME_PLUS); + sb.append(VARIABLE_NAME_I); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + + // block + sb.append(field.getName()); + sb.append(CHAR_NAME_DOT); + sb.append(METHOD_NAME_ADD); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + insertCodeOfUnpackMethodCall(sb, null, genericType); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + + sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + } + + private void insertCodeOfUnpackMethodCallForMapType(StringBuilder sb, + Field field, Class type) { + ParameterizedType generic = (ParameterizedType) field.getGenericType(); + Class genericType0 = (Class) generic.getActualTypeArguments()[0]; + Class genericType1 = (Class) generic.getActualTypeArguments()[1]; + + // len + sb.append(int.class.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(VARIABLE_NAME_SIZE); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + sb.append(VARIABLE_NAME_PK); + sb.append(CHAR_NAME_DOT); + sb.append(METHOD_NAME_UNPACKMAP); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + + // field initializer + sb.append(field.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + sb.append(KEYWORD_NEW); + sb.append(CHAR_NAME_SPACE); + sb.append(HashMap.class.getName()); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + + // for loop + sb.append(KEYWORD_FOR); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(int.class.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(VARIABLE_NAME_I); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + sb.append(0); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + sb.append(VARIABLE_NAME_I); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LESSTHAN); + sb.append(CHAR_NAME_SPACE); + sb.append(VARIABLE_NAME_SIZE); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_PLUS); + sb.append(CHAR_NAME_PLUS); + sb.append(VARIABLE_NAME_I); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + + // block map. + sb.append(field.getName()); + sb.append(CHAR_NAME_DOT); + sb.append(METHOD_NAME_PUT); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + insertCodeOfUnpackMethodCall(sb, null, genericType0); + sb.append(CHAR_NAME_COMMA); + sb.append(CHAR_NAME_SPACE); + insertCodeOfUnpackMethodCall(sb, null, genericType1); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + + sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + } + + // private void insertCodeOfMessageUnpackCallForEnhancedType(StringBuilder + // sb, + // Field f, Class c) { + // c = this.getCache(c.getName()); + // insertCodeOfMessageUnpackCallForMsgUnpackableType(sb, f, c); + // } + + private void insertCodeOfMessageUnpackCallForMsgUnpackableType( + StringBuilder sb, Field f, Class c) { + // if (fi == null) { fi = new Foo_$$_Enhanced(); } + sb.append(KEYWORD_IF); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(f.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + sb.append(KEYWORD_NULL); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + sb.append(f.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + sb.append(KEYWORD_NEW); + sb.append(CHAR_NAME_SPACE); + sb.append(c.getName()); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + + // insert a right variable // ignore + sb.append(VARIABLE_NAME_PK); + sb.append(CHAR_NAME_DOT); + sb.append(METHOD_NAME_UNPACK); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(MessageUnpackable.class.getName()); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(f.getName()); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + } + + private void addConvertMethod(CtClass tmplCtClass, Class c, Field[] fs) + throws CannotCompileException, NotFoundException { + // Object convert(MessagePackObject from) throws MessageTypeException; + // FIXME + } + private Class createClass(CtClass packerCtClass) throws CannotCompileException { return packerCtClass.toClass(null, null); diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java index 24ae579a..1c907a23 100644 --- a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java +++ b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java @@ -5,185 +5,245 @@ import java.util.List; import java.util.Map; public class DynamicCodeGenBase implements BasicConstants { - public DynamicCodeGenBase() { - } + public DynamicCodeGenBase() { + } - public void insertSemicolon(StringBuilder sb) { - sb.append(CHAR_NAME_SEMICOLON); - sb.append(CHAR_NAME_SPACE); - } + public void addPublicFieldDecl(StringBuilder sb, Class type, String name) { + sb.append(KEYWORD_MODIFIER_PUBLIC); + sb.append(CHAR_NAME_SPACE); + sb.append(type.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(name); + } + + public void addPublicMethodDecl(StringBuilder sb, String mname, + Class returnType, Class[] paramTypes, String[] anames, + Class[] exceptTypes, String methodBody) { + sb.append(KEYWORD_MODIFIER_PUBLIC); + sb.append(CHAR_NAME_SPACE); + sb.append(returnType.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(mname); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + for (int i = 0; i < paramTypes.length; ++i) { + sb.append(paramTypes[i].getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(anames[i]); + if (i + 1 != paramTypes.length) { + sb.append(CHAR_NAME_COMMA); + sb.append(CHAR_NAME_SPACE); + } + } + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SPACE); + sb.append(KEYWORD_THROWS); + sb.append(CHAR_NAME_SPACE); + for (int i = 0; i < exceptTypes.length; ++i) { + sb.append(exceptTypes[i].getName()); + if (i + 1 != exceptTypes.length) { + sb.append(CHAR_NAME_COMMA); + sb.append(CHAR_NAME_SPACE); + } + } + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + sb.append(methodBody); + sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + } - public void insertPublicFieldDecl(StringBuilder sb, Class type, - String name) { - sb.append(KEYWORD_MODIFIER_PUBLIC); - sb.append(CHAR_NAME_SPACE); - sb.append(type.getName()); - sb.append(CHAR_NAME_SPACE); - sb.append(name); - } + public void insertSemicolon(StringBuilder sb) { + sb.append(CHAR_NAME_SEMICOLON); + sb.append(CHAR_NAME_SPACE); + } - public void insertLocalVariableDecl(StringBuilder sb, Class type, - String name) { - sb.append(type.getName()); - sb.append(CHAR_NAME_SPACE); - sb.append(name); - } - - public void insertValueInsertion(StringBuilder sb, String expr) { - // = expr - sb.append(CHAR_NAME_SPACE); - sb.append(CHAR_NAME_EQUAL); - sb.append(CHAR_NAME_SPACE); - sb.append(expr); - } + public void insertLocalVariableDecl(StringBuilder sb, Class type, + String name) { + sb.append(type.getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(name); + } - public void insertDefaultConsCall(StringBuilder sb, Class type) { - // new tname() - insertConsCall(sb, type, null); - } + public void insertValueInsertion(StringBuilder sb, String expr) { + // = expr + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_EQUAL); + sb.append(CHAR_NAME_SPACE); + sb.append(expr); + } - public void insertConsCall(StringBuilder sb, Class type, String expr) { - // new tname(expr) - sb.append(KEYWORD_NEW); - sb.append(CHAR_NAME_SPACE); - sb.append(type.getName()); - sb.append(CHAR_NAME_LEFT_PARENTHESIS); - if (expr != null) { - sb.append(expr); - } - sb.append(CHAR_NAME_RIGHT_PARENTHESIS); - } + public void insertDefaultConsCall(StringBuilder sb, Class type) { + // new tname() + insertConsCall(sb, type, null); + } - public void insertMethodCall(StringBuilder sb, String tname, String mname, - String[] anames) { - // tname.mname(anames[0], anames[1], ...) - int len = anames.length; - sb.append(tname); - sb.append(CHAR_NAME_DOT); - sb.append(mname); - sb.append(CHAR_NAME_LEFT_PARENTHESIS); - for (int i = 0; i < len; ++i) { - sb.append(anames[i]); - if (i + 1 != len) { - sb.append(CHAR_NAME_COMMA); - sb.append(CHAR_NAME_SPACE); - } - } - sb.append(CHAR_NAME_RIGHT_PARENTHESIS); - } - - public void insertTypeCast(StringBuilder sb, Class type) { - // (type) - sb.append(CHAR_NAME_LEFT_PARENTHESIS); - sb.append(type.getName()); - sb.append(CHAR_NAME_RIGHT_PARENTHESIS); - } - - public void insertTypeCast(StringBuilder sb, Class type, String varName) { - // ((type)var) - sb.append(CHAR_NAME_LEFT_PARENTHESIS); - sb.append(CHAR_NAME_LEFT_PARENTHESIS); - sb.append(type.getName()); - sb.append(CHAR_NAME_RIGHT_PARENTHESIS); - sb.append(varName); - sb.append(CHAR_NAME_RIGHT_PARENTHESIS); - } - - public void insertTypeConvToObjectType(StringBuilder sb, Class type, - String expr) throws DynamicCodeGenException { - if (type.isPrimitive()) { // primitive type - if (type.equals(boolean.class)) { - // new Boolean(expr) - insertConsCall(sb, Boolean.class, expr); - } else if (type.equals(byte.class)) { - insertConsCall(sb, Byte.class, expr); - } else if (type.equals(short.class)) { - insertConsCall(sb, Short.class, expr); - } else if (type.equals(int.class)) { - insertConsCall(sb, Integer.class, expr); - } else if (type.equals(long.class)) { - insertConsCall(sb, Long.class, expr); - } else if (type.equals(float.class)) { - insertConsCall(sb, Float.class, expr); - } else if (type.equals(double.class)) { - insertConsCall(sb, Double.class, expr); - } else { - throw new DynamicCodeGenException("Type error: " - + type.getName()); - } - } else { // reference type - sb.append(expr); - } - } + public void insertConsCall(StringBuilder sb, Class type, String expr) { + // new tname(expr) + sb.append(KEYWORD_NEW); + sb.append(CHAR_NAME_SPACE); + sb.append(type.getName()); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + if (expr != null) { + sb.append(expr); + } + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + } - public void insertTryCatchBlocks(StringBuilder sb, String tryBody, - List> types, List names, List catchBodies) { - int len = types.size(); - sb.append(KEYWORD_TRY); - sb.append(CHAR_NAME_SPACE); - sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); - sb.append(CHAR_NAME_SPACE); - sb.append(tryBody); - sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); - sb.append(CHAR_NAME_SPACE); - for (int i = 0; i < len; ++i) { - sb.append(KEYWORD_CATCH); - sb.append(CHAR_NAME_SPACE); - sb.append(CHAR_NAME_LEFT_PARENTHESIS); - sb.append(types.get(i).getName()); - sb.append(CHAR_NAME_SPACE); - sb.append(names.get(i)); - sb.append(CHAR_NAME_RIGHT_PARENTHESIS); - sb.append(CHAR_NAME_SPACE); - sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); - sb.append(CHAR_NAME_SPACE); - sb.append(catchBodies.get(i)); - sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); - sb.append(CHAR_NAME_SPACE); - } - } + public void insertMethodCall(StringBuilder sb, String tname, String mname, + String[] anames) { + // tname.mname(anames[0], anames[1], ...) + int len = anames.length; + sb.append(tname); + sb.append(CHAR_NAME_DOT); + sb.append(mname); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + for (int i = 0; i < len; ++i) { + sb.append(anames[i]); + if (i + 1 != len) { + sb.append(CHAR_NAME_COMMA); + sb.append(CHAR_NAME_SPACE); + } + } + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + } - public String getAsMethod(Class c) throws DynamicCodeGenException { - if (c.equals(boolean.class)) { - return METHOD_NAME_ASBOOLEAN; - } else if (c.equals(byte.class)) { - return METHOD_NAME_ASBYTE; - } else if (c.equals(short.class)) { - return METHOD_NAME_ASSHORT; - } else if (c.equals(int.class)) { - return METHOD_NAME_ASINT; - } else if (c.equals(float.class)) { - return METHOD_NAME_ASFLOAT; - } else if (c.equals(long.class)) { - return METHOD_NAME_ASLONG; - } else if (c.equals(double.class)) { - return METHOD_NAME_ASDOUBLE; - } else if (c.equals(Boolean.class)) { - return METHOD_NAME_ASBOOLEAN; - } else if (c.equals(Byte.class)) { - return METHOD_NAME_ASBYTE; - } else if (c.equals(Short.class)) { - return METHOD_NAME_ASSHORT; - } else if (c.equals(Integer.class)) { - return METHOD_NAME_ASINT; - } else if (c.equals(Float.class)) { - return METHOD_NAME_ASFLOAT; - } else if (c.equals(Long.class)) { - return METHOD_NAME_ASLONG; - } else if (c.equals(Double.class)) { - return METHOD_NAME_ASDOUBLE; - } else if (c.equals(String.class)) { - return METHOD_NAME_ASSTRING; - } else if (c.equals(byte[].class)) { - return METHOD_NAME_ASBYTEARRAY; - } else if (c.equals(BigInteger.class)) { - return METHOD_NAME_ASBIGINTEGER; - } else if (List.class.isAssignableFrom(c)) { - return METHOD_NAME_ASLIST; - } else if (Map.class.isAssignableFrom(c)) { - return METHOD_NAME_ASMAP; - } else { - throw new DynamicCodeGenException("Type error: " + c.getName()); - } - } + public void insertTypeCast(StringBuilder sb, Class type) { + // (type) + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(type.getName()); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + } + + public void insertTypeCast(StringBuilder sb, Class type, String varName) { + // ((type)var) + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(type.getName()); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(varName); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + } + + public void insertReturnStat(StringBuilder sb, String expr) { + // return expr + sb.append(KEYWORD_RETURN); + sb.append(CHAR_NAME_SPACE); + sb.append(expr); + } + + public void insertTypeConvToObjectType(StringBuilder sb, Class type, + String expr) throws DynamicCodeGenException { + if (type.isPrimitive()) { // primitive type + if (type.equals(boolean.class)) { + // new Boolean(expr) + insertConsCall(sb, Boolean.class, expr); + } else if (type.equals(byte.class)) { + insertConsCall(sb, Byte.class, expr); + } else if (type.equals(short.class)) { + insertConsCall(sb, Short.class, expr); + } else if (type.equals(int.class)) { + insertConsCall(sb, Integer.class, expr); + } else if (type.equals(long.class)) { + insertConsCall(sb, Long.class, expr); + } else if (type.equals(float.class)) { + insertConsCall(sb, Float.class, expr); + } else if (type.equals(double.class)) { + insertConsCall(sb, Double.class, expr); + } else { + throw new DynamicCodeGenException("Type error: " + + type.getName()); + } + } else { // reference type + sb.append(expr); + } + } + + public void insertTryCatchBlocks(StringBuilder sb, String tryBody, + List> types, List names, List catchBodies) { + int len = types.size(); + sb.append(KEYWORD_TRY); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + sb.append(tryBody); + sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + for (int i = 0; i < len; ++i) { + sb.append(KEYWORD_CATCH); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LEFT_PARENTHESIS); + sb.append(types.get(i).getName()); + sb.append(CHAR_NAME_SPACE); + sb.append(names.get(i)); + sb.append(CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(CHAR_NAME_SPACE); + sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + sb.append(catchBodies.get(i)); + sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); + sb.append(CHAR_NAME_SPACE); + } + } + + public String getUnpackMethodName(Class c) + throws DynamicCodeGenException { + if (c.equals(boolean.class) || c.equals(Boolean.class)) { + return METHOD_NAME_UNPACKBOOLEAN; + } else if (c.equals(byte.class) || c.equals(Byte.class)) { + return METHOD_NAME_UNPACKBYTE; + } else if (c.equals(short.class) || c.equals(Short.class)) { + return METHOD_NAME_UNPACKSHORT; + } else if (c.equals(int.class) || c.equals(Integer.class)) { + return METHOD_NAME_UNPACKINT; + } else if (c.equals(float.class) || c.equals(Float.class)) { + return METHOD_NAME_UNPACKFLOAT; + } else if (c.equals(long.class) || c.equals(Long.class)) { + return METHOD_NAME_UNPACKLONG; + } else if (c.equals(double.class) || c.equals(Double.class)) { + return METHOD_NAME_UNPACKDOUBLE; + } else if (c.equals(String.class)) { + return METHOD_NAME_UNPACKSTRING; + } else if (c.equals(byte[].class)) { + return METHOD_NAME_UNPACKBYTEARRAY; + } else if (c.equals(BigInteger.class)) { + return METHOD_NAME_UNPACKBIGINTEGER; + } else if (List.class.isAssignableFrom(c)) { + return METHOD_NAME_UNPACK; + } else if (Map.class.isAssignableFrom(c)) { + return METHOD_NAME_UNPACK; + } else { + throw new DynamicCodeGenException("Type error: " + c.getName()); + } + } + + public String getAsMethodName(Class c) throws DynamicCodeGenException { + if (c.equals(boolean.class) || c.equals(Boolean.class)) { + return METHOD_NAME_ASBOOLEAN; + } else if (c.equals(byte.class) || c.equals(Byte.class)) { + return METHOD_NAME_ASBYTE; + } else if (c.equals(short.class) || c.equals(Short.class)) { + return METHOD_NAME_ASSHORT; + } else if (c.equals(int.class) || c.equals(Integer.class)) { + return METHOD_NAME_ASINT; + } else if (c.equals(float.class) || c.equals(Float.class)) { + return METHOD_NAME_ASFLOAT; + } else if (c.equals(long.class) || c.equals(Long.class)) { + return METHOD_NAME_ASLONG; + } else if (c.equals(double.class) || c.equals(Double.class)) { + return METHOD_NAME_ASDOUBLE; + } else if (c.equals(String.class)) { + return METHOD_NAME_ASSTRING; + } else if (c.equals(byte[].class)) { + return METHOD_NAME_ASBYTEARRAY; + } else if (c.equals(BigInteger.class)) { + return METHOD_NAME_ASBIGINTEGER; + } else if (List.class.isAssignableFrom(c)) { + return METHOD_NAME_ASLIST; + } else if (Map.class.isAssignableFrom(c)) { + return METHOD_NAME_ASMAP; + } else { + throw new DynamicCodeGenException("Type error: " + c.getName()); + } + } } diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenUnpacker.java b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenUnpacker.java new file mode 100644 index 00000000..e4fe76bd --- /dev/null +++ b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenUnpacker.java @@ -0,0 +1,17 @@ +package org.msgpack.util.codegen; + +import org.msgpack.MessageUnpacker; + +public class DynamicCodeGenUnpacker { + public static MessageUnpacker create(Class c) { + try { + DynamicCodeGen gen = DynamicCodeGen.getInstance(); + Class unpackerClass = gen.generateMessageUnpackerClass(c); + return (MessageUnpacker) unpackerClass.newInstance(); + } catch (InstantiationException e) { + throw new DynamicCodeGenException(e.getMessage(), e); + } catch (IllegalAccessException e) { + throw new DynamicCodeGenException(e.getMessage(), e); + } + } +} diff --git a/java/src/test/java/org/msgpack/util/codegen/TestDynamicCodeGenPacker.java b/java/src/test/java/org/msgpack/util/codegen/TestDynamicCodeGenPacker.java index d4e9c166..88515378 100644 --- a/java/src/test/java/org/msgpack/util/codegen/TestDynamicCodeGenPacker.java +++ b/java/src/test/java/org/msgpack/util/codegen/TestDynamicCodeGenPacker.java @@ -1,50 +1,60 @@ package org.msgpack.util.codegen; -import static org.msgpack.Templates.tString; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import org.junit.Test; import org.msgpack.MessagePacker; +import org.msgpack.MessageUnpacker; import org.msgpack.Packer; -import org.msgpack.ReflectionPacker; -import org.msgpack.ReflectionTemplate; import org.msgpack.Template; import org.msgpack.Unpacker; import junit.framework.TestCase; - public class TestDynamicCodeGenPacker extends TestCase { public static class StringFieldClass { public String s1; public String s2; - public StringFieldClass() { } + + public StringFieldClass() { + } } @Test - public void testPackConvert() throws Exception { - tString(); // FIXME link StringTemplate - + public void testPackConvert01() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); - MessagePacker packer = DynamicCodeGenPacker.create(StringFieldClass.class); + MessagePacker packer = DynamicCodeGenPacker + .create(StringFieldClass.class); + MessageUnpacker unpacker = DynamicCodeGenUnpacker + .create(StringFieldClass.class); StringFieldClass src = new StringFieldClass(); - - src.s1 = "kumofs"; - src.s2 = "frsyuki"; - + src.s1 = "muga"; + src.s2 = "nishizawa"; packer.pack(new Packer(out), src); - Template tmpl = ReflectionTemplate.create(StringFieldClass.class); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + StringFieldClass dst = (StringFieldClass) new Unpacker(in) + .unpack(unpacker); + assertEquals(src.s1, dst.s1); + assertEquals(src.s2, dst.s2); + } + + @Test + public void testPackConvert02() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + MessagePacker packer = DynamicCodeGenPacker + .create(StringFieldClass.class); + Template tmpl = DynamicCodeGenTemplate.create(StringFieldClass.class); + + StringFieldClass src = new StringFieldClass(); + src.s1 = "muga"; + src.s2 = "nishizawa"; + packer.pack(new Packer(out), src); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - - Object obj = tmpl.unpack(new Unpacker(in)); - assertEquals(obj.getClass(), StringFieldClass.class); - - StringFieldClass dst = (StringFieldClass)obj; + StringFieldClass dst = (StringFieldClass) tmpl.unpack(new Unpacker(in)); assertEquals(src.s1, dst.s1); assertEquals(src.s2, dst.s2); }