From 9eeb702ca536f0e97e53202b177d9db5ac9e322f Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Wed, 15 Sep 2010 22:28:46 +0900 Subject: [PATCH] change an annotation-utility in Java. it allows users to pack and unpack a List object. --- .../annotation/MessagePackUnpackable.java | 2 +- .../util/annotation/PackUnpackUtil.java | 705 ++++++++++-------- .../annotation/TestMessagePackUnpackable.java | 105 ++- 3 files changed, 499 insertions(+), 313 deletions(-) diff --git a/java/src/main/java/org/msgpack/util/annotation/MessagePackUnpackable.java b/java/src/main/java/org/msgpack/util/annotation/MessagePackUnpackable.java index 473b5412..77f6e6de 100644 --- a/java/src/main/java/org/msgpack/util/annotation/MessagePackUnpackable.java +++ b/java/src/main/java/org/msgpack/util/annotation/MessagePackUnpackable.java @@ -6,6 +6,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) -@Retention(RetentionPolicy.CLASS) +@Retention(RetentionPolicy.RUNTIME) 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 index f92c51a0..52384448 100644 --- a/java/src/main/java/org/msgpack/util/annotation/PackUnpackUtil.java +++ b/java/src/main/java/org/msgpack/util/annotation/PackUnpackUtil.java @@ -3,9 +3,14 @@ package org.msgpack.util.annotation; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.lang.annotation.Annotation; +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.ConcurrentHashMap; @@ -14,7 +19,6 @@ import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; -import javassist.CtField; import javassist.CtMethod; import javassist.CtNewConstructor; import javassist.CtNewMethod; @@ -33,51 +37,16 @@ public class PackUnpackUtil { static final String KEYWORD_MODIFIER_PUBLIC = "public"; + static final String KEYWORD_FOR = "for"; + static final String KEYWORD_THROWS = "throws"; + static final String KEYWORD_NEW = "new"; + 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_BYTEARRAY = "byte[]"; - - 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(); @@ -111,6 +80,10 @@ public class PackUnpackUtil { static final String CHAR_NAME_EQUAL = "="; + static final String CHAR_NAME_PLUS = "+"; + + static final String CHAR_NAME_LESSTHAN = "<"; + static final String CHAR_NAME_RIGHT_PARENTHESIS = ")"; static final String CHAR_NAME_LEFT_PARENTHESIS = "("; @@ -127,8 +100,16 @@ public class PackUnpackUtil { static final String VARIABLE_NAME_OBJ = "obj"; + static final String VARIABLE_NAME_SIZE = "len"; + + static final String VARIABLE_NAME_I = "i"; + static final String METHOD_NAME_VALUEOF = "valueOf"; + static final String METHOD_NAME_ADD = "add"; + + static final String METHOD_NAME_PUT = "put"; + static final String METHOD_NAME_MSGPACK = "messagePack"; static final String METHOD_NAME_MSGUNPACK = "messageUnpack"; @@ -192,73 +173,68 @@ public class PackUnpackUtil { String origName = origClass.getName(); String enhName = origName + Constants.POSTFIX_TYPE_NAME_ENHANCER; CtClass origCtClass = pool.get(origName); - checkClassValidation(origCtClass); - checkDefaultConstructorValidation(origCtClass); + checkClassValidation(origClass); + checkDefaultConstructorValidation(origClass); CtClass enhCtClass = pool.makeClass(enhName); setSuperclass(enhCtClass, origCtClass); setInterfaces(enhCtClass); addConstructor(enhCtClass); - CtField[] fields = getDeclaredFields(origCtClass); + Field[] fields = getDeclaredFields(origClass); addMessagePackMethod(enhCtClass, origCtClass, fields); addMessageUnpackMethod(enhCtClass, origCtClass, fields); addMessageConvertMethod(enhCtClass, origCtClass, fields); return createClass(enhCtClass); } - private void checkClassValidation(CtClass origCtClass) { + private void checkClassValidation(Class origClass) { // not public, abstract, final - int mod = origCtClass.getModifiers(); - if ((!Modifier.isPublic(mod)) || Modifier.isAbstract(mod) - || Modifier.isFinal(mod)) { - throwClassValidationException(origCtClass); + int mod = origClass.getModifiers(); + if ((!(Modifier.isPublic(mod) || Modifier.isProtected(mod))) + || Modifier.isAbstract(mod) || Modifier.isFinal(mod)) { + throwClassValidationException(origClass); } // interface, enum - if (origCtClass.isInterface() || origCtClass.isEnum()) { - throwClassValidationException(origCtClass); + if (origClass.isInterface() || origClass.isEnum()) { + throwClassValidationException(origClass); } // annotation - checkPackUnpackAnnotation(origCtClass); + checkPackUnpackAnnotation(origClass); } - private static void throwClassValidationException(CtClass origCtClass) { + private static void throwClassValidationException(Class origClass) { throw new PackUnpackUtilException( "it must be a public class and have @" + MessagePackUnpackable.class.getName() + ": " - + origCtClass.getName()); + + origClass.getName()); } - private void checkPackUnpackAnnotation(CtClass origCtClass) { - try { - Object[] objs = origCtClass.getAnnotations(); - for (Object obj : objs) { - if (obj instanceof MessagePackUnpackable) { - return; - } - } - throwClassValidationException(origCtClass); - } catch (ClassNotFoundException e) { - throw new PackUnpackUtilException(e.getMessage(), e); + private void checkPackUnpackAnnotation(Class origClass) { + Annotation anno = origClass + .getAnnotation(MessagePackUnpackable.class); + if (anno == null) { + throwClassValidationException(origClass); } } - private void checkDefaultConstructorValidation(CtClass origCtClass) { - CtConstructor cons = null; + private void checkDefaultConstructorValidation(Class origClass) { + Constructor cons = null; try { - cons = origCtClass.getDeclaredConstructor(new CtClass[0]); - } catch (NotFoundException e) { - throwConstructoValidationException(origCtClass); + cons = origClass.getDeclaredConstructor(new Class[0]); + } catch (Exception e1) { + throwConstructoValidationException(origClass); } + int mod = cons.getModifiers(); if (!(Modifier.isPublic(mod) || Modifier.isProtected(mod))) { - throwConstructoValidationException(origCtClass); + throwConstructoValidationException(origClass); } } private static void throwConstructoValidationException( - CtClass origCtClass) { + Class origClass) { throw new PackUnpackUtilException( "it must have a public zero-argument constructor: " - + origCtClass.getName()); + + origClass.getName()); } private void setSuperclass(CtClass enhCtClass, CtClass origCtClass) @@ -282,301 +258,430 @@ public class PackUnpackUtil { enhCtClass.addConstructor(newCtCons); } - private CtField[] getDeclaredFields(CtClass origCtClass) { - ArrayList allFields = new ArrayList(); - try { - CtClass nextCtClass = origCtClass; - while (!nextCtClass - .equals(pool.get(Constants.TYPE_NAME_OBJECT))) { - CtField[] fields = nextCtClass.getDeclaredFields(); - for (CtField field : fields) { - try { - checkFieldValidation(field, allFields); - allFields.add(field); - } catch (PackUnpackUtilException e) { // ignore - } + private Field[] getDeclaredFields(Class origClass) { + ArrayList allFields = new ArrayList(); + Class nextClass = origClass; + while (nextClass != Object.class) { + Field[] fields = nextClass.getDeclaredFields(); + for (Field field : fields) { + try { + checkFieldValidation(field, allFields); + allFields.add(field); + } catch (PackUnpackUtilException e) { // ignore } - nextCtClass = nextCtClass.getSuperclass(); } - - } catch (NotFoundException e) { - throw new PackUnpackUtilException(e.getMessage(), e); + nextClass = nextClass.getSuperclass(); } - return allFields.toArray(new CtField[0]); + return allFields.toArray(new Field[0]); } - private void checkFieldValidation(CtField field, - ArrayList allFields) { + private void checkFieldValidation(Field field, List fields) { // check modifiers (public or protected) int mod = field.getModifiers(); if ((!(Modifier.isPublic(mod) || Modifier.isProtected(mod))) || Modifier.isStatic(mod) || Modifier.isFinal(mod) - || Modifier.isTransient(mod)) { + || Modifier.isTransient(mod) || field.isSynthetic()) { throwFieldValidationException(field); } // check same name - for (CtField f : allFields) { + for (Field f : fields) { if (f.getName().equals(field.getName())) { throwFieldValidationException(field); } } } - private static void throwFieldValidationException(CtField field) { + private static void throwFieldValidationException(Field field) { throw new PackUnpackUtilException("it must be a public field: " + field.getName()); } private void addMessagePackMethod(CtClass enhCtClass, - CtClass origCtClass, CtField[] fields) + CtClass origCtClass, Field[] fields) 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); - 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.KEYWORD_MODIFIER_PUBLIC); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.TYPE_NAME_VOID); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.METHOD_NAME_MSGPACK); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.TYPE_NAME_PACKER); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_PK); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.KEYWORD_THROWS); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.TYPE_NAME_IOEXCEPTION); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_LEFT_CURLY_BRACHET); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_PK); + sb.append(Constants.CHAR_NAME_DOT); + sb.append(Constants.METHOD_NAME_PACKARRAY); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(fields.length); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + for (Field field : fields) { + insertCodeOfMessagePack(sb, field); } sb.append(Constants.CHAR_NAME_RIGHT_CURLY_BRACHET); - System.out.println("messagePack method: " + sb.toString()); + //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 insertCodeOfMessagePack(StringBuilder sb, Field field) { + sb.append(Constants.VARIABLE_NAME_PK); + sb.append(Constants.CHAR_NAME_DOT); + sb.append(Constants.METHOD_NAME_PACK); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(field.getName()); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); } private void addMessageUnpackMethod(CtClass enhCtClass, - CtClass origCtClass, CtField[] fields) + CtClass origCtClass, Field[] fields) 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); - 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.KEYWORD_MODIFIER_PUBLIC); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.TYPE_NAME_VOID); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.METHOD_NAME_MSGUNPACK); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.TYPE_NAME_UNPACKER); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_PK); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.KEYWORD_THROWS); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.TYPE_NAME_MSGTYPEEXCEPTION); + sb.append(Constants.CHAR_NAME_COMMA); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.TYPE_NAME_IOEXCEPTION); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_LEFT_CURLY_BRACHET); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_PK); + sb.append(Constants.CHAR_NAME_DOT); + sb.append(Constants.METHOD_NAME_UNPACKARRAY); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + for (Field field : fields) { + insertCodeOfMessageUnpack(sb, field, field.getType()); } sb.append(Constants.CHAR_NAME_RIGHT_CURLY_BRACHET); - System.out.println("messageUnpack method: " + sb.toString()); + //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(); - insertRightVariable(sb, field, type); - insertValueOfMethodAndLeftParenthesis(sb, type); - sb.append(Constants.VARIABLE_NAME_PK).append( - Constants.CHAR_NAME_DOT); - insertUnpackMethod(sb, type); - sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); - insertUnpackMethodArgumenet(sb, field, type); - sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); - insertValueOfMethodAndRightParenthesis(sb, type); - sb.append(Constants.CHAR_NAME_SEMICOLON).append( - Constants.CHAR_NAME_SPACE); - - } - - private void insertRightVariable(StringBuilder sb, CtField field, - CtClass type) throws NotFoundException { - if (type.isPrimitive()) { // primitive type - sb.append(field.getName()).append(Constants.CHAR_NAME_SPACE) - .append(Constants.CHAR_NAME_EQUAL).append( - Constants.CHAR_NAME_SPACE); - } else { // reference type - if (type.equals(pool.get(Constants.TYPE_NAME_BOOLEAN2)) // Boolean - || type.equals(pool.get(Constants.TYPE_NAME_BYTE2)) // Byte - || type.equals(pool.get(Constants.TYPE_NAME_DOUBLE2)) // Double - || type.equals(pool.get(Constants.TYPE_NAME_FLOAT2)) // Float - || type.equals(pool.get(Constants.TYPE_NAME_INT2)) // Integer - || type.equals(pool.get(Constants.TYPE_NAME_LONG2)) // Long - || type.equals(pool.get(Constants.TYPE_NAME_SHORT2)) // Short - || type - .equals(pool - .get(Constants.TYPE_NAME_BIGINTEGER)) // BigInteger - || type.equals(pool.get(Constants.TYPE_NAME_STRING)) // String - || type.equals(pool.get(Constants.TYPE_NAME_BYTEARRAY)) // byte[] - || type.subtypeOf(pool.get(Constants.TYPE_NAME_LIST)) // List - || type.subtypeOf(pool.get(Constants.TYPE_NAME_MAP)) // Map - ) { - sb.append(field.getName()) - .append(Constants.CHAR_NAME_SPACE).append( - Constants.CHAR_NAME_EQUAL).append( - Constants.CHAR_NAME_SPACE); - } else { // MessageUnpackable - return; - } - } - - } - - private void insertValueOfMethodAndLeftParenthesis(StringBuilder sb, - CtClass type) throws NotFoundException { - if (type.isPrimitive()) { // primitive type - return; - } else { // reference type - if (type.equals(pool.get(Constants.TYPE_NAME_BOOLEAN2)) // Boolean - || type.equals(pool.get(Constants.TYPE_NAME_BYTE2)) // Byte - || type.equals(pool.get(Constants.TYPE_NAME_DOUBLE2)) // Double - || type.equals(pool.get(Constants.TYPE_NAME_FLOAT2)) // Float - || type.equals(pool.get(Constants.TYPE_NAME_INT2)) // Integer - || type.equals(pool.get(Constants.TYPE_NAME_LONG2)) // Long - || type.equals(pool.get(Constants.TYPE_NAME_SHORT2)) // Short - ) { - sb.append(type.getName()).append(Constants.CHAR_NAME_DOT) - .append(Constants.METHOD_NAME_VALUEOF).append( - Constants.CHAR_NAME_LEFT_PARENTHESIS); - } else { - return; - } + private void insertCodeOfMessageUnpack(StringBuilder sb, Field field, + Class type) throws NotFoundException { + if (type.isPrimitive()) { + // primitive type + insertCodeOfMessageUnpackForPrimitiveTypes(sb, field, type); + } else if (type.equals(Boolean.class) || // Boolean + type.equals(Byte.class) || // Byte + type.equals(Double.class) || // Double + type.equals(Float.class) || // Float + type.equals(Integer.class) || // Integer + type.equals(Long.class) || // Long + type.equals(Short.class)) { // Short + // reference type (wrapper type) + insertCodeOfMessageUnpackForWrapperTypes(sb, field, type); + } else if (type.equals(BigInteger.class) || // BigInteger + type.equals(String.class) || // String + type.equals(byte[].class)) { // byte[] + // reference type (other type) + insertCodeOfMessageUnpackForPrimitiveTypes(sb, field, type); + } else if (List.class.isAssignableFrom(type)) { + // List + insertCodeOfMessageUnpackForListType(sb, field, type); + } else if (Map.class.isAssignableFrom(type)) { + // Map + insertCodeOfMessageUnpackForMapType(sb, field, type); + } else if (MessageUnpackable.class.isAssignableFrom(type) + || (getCache(type.getName()) != null)) { + // MessageUnpackable + insertCodeOfMessageUnpackForMsgUnpackableType(sb, field, type); + } else { + throw new NotFoundException("unknown type: " + type.getName()); } } - private void insertUnpackMethod(StringBuilder sb, CtClass type) + private void insertCodeOfMessageUnpackForPrimitiveTypes( + StringBuilder sb, Field field, Class type) throws NotFoundException { - if (type.equals(CtClass.booleanType)) { // boolean + // insert a right variable + if (field != null) { + sb.append(field.getName()); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_EQUAL); + sb.append(Constants.CHAR_NAME_SPACE); + } + sb.append(Constants.VARIABLE_NAME_PK); + sb.append(Constants.CHAR_NAME_DOT); + // insert unpack method + if (type.equals(boolean.class)) { // boolean sb.append(Constants.METHOD_NAME_UNPACKBOOLEAN); - } else if (type.equals(CtClass.byteType)) { // byte + } else if (type.equals(byte.class)) { // byte sb.append(Constants.METHOD_NAME_UNPACKBYTE); - } else if (type.equals(CtClass.doubleType)) { // double + } else if (type.equals(double.class)) { // double sb.append(Constants.METHOD_NAME_UNPACKDOUBLE); - } else if (type.equals(CtClass.floatType)) { // float + } else if (type.equals(float.class)) { // float sb.append(Constants.METHOD_NAME_UNPACKFLOAT); - } else if (type.equals(CtClass.intType)) { // int + } else if (type.equals(int.class)) { // int sb.append(Constants.METHOD_NAME_UNPACKINT); - } else if (type.equals(CtClass.longType)) { // long + } else if (type.equals(long.class)) { // long sb.append(Constants.METHOD_NAME_UNPACKLONG); - } else if (type.equals(CtClass.shortType)) { // short + } else if (type.equals(short.class)) { // short sb.append(Constants.METHOD_NAME_UNPACKSHORT); } else { // reference type - Class c = null; - 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 + if (type.equals(BigInteger.class)) { // BigInteger sb.append(Constants.METHOD_NAME_UNPACKBIGINTEGER); - } else if (type.equals(pool.get(Constants.TYPE_NAME_STRING))) { // String + } else if (type.equals(String.class)) { // String sb.append(Constants.METHOD_NAME_UNPACKSTRING); - } else if (type.equals(pool.get(Constants.TYPE_NAME_BYTEARRAY))) { // byte[] + } else if (type.equals(byte[].class)) { // 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)) - || ((c = getCache(type.getName())) != null)) { // MessageUnpackable - sb.append(Constants.METHOD_NAME_UNPACK); } else { throw new NotFoundException("unknown type: " + type.getName()); } } - } - - private void insertUnpackMethodArgumenet(StringBuilder sb, - CtField field, CtClass type) throws NotFoundException { - if (type.isPrimitive()) { // primitive type - return; - } else { // reference type - Class c = null; - if (type.equals(pool.get(Constants.TYPE_NAME_MSGUNPACKABLE)) - || ((c = getCache(type.getName())) != null)) { - sb.append("(org.msgpack.MessageUnpackable)"); - sb.append(field.getName()); - } else { - return; - } + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + if (field != null) { + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); } } - private void insertValueOfMethodAndRightParenthesis(StringBuilder sb, - CtClass type) throws NotFoundException { - if (type.isPrimitive()) { // primitive type - return; - } else { // reference type - if (type.equals(pool.get(Constants.TYPE_NAME_BOOLEAN2)) // Boolean - || type.equals(pool.get(Constants.TYPE_NAME_BYTE2)) // Byte - || type.equals(pool.get(Constants.TYPE_NAME_DOUBLE2)) // Double - || type.equals(pool.get(Constants.TYPE_NAME_FLOAT2)) // Float - || type.equals(pool.get(Constants.TYPE_NAME_INT2)) // Integer - || type.equals(pool.get(Constants.TYPE_NAME_LONG2)) // Long - || type.equals(pool.get(Constants.TYPE_NAME_SHORT2)) // Short - ) { - sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); - } else { - return; - } + private void insertCodeOfMessageUnpackForWrapperTypes(StringBuilder sb, + Field field, Class type) throws NotFoundException { + // insert a right variable + if (field != null) { + sb.append(field.getName()); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_EQUAL); + sb.append(Constants.CHAR_NAME_SPACE); } + sb.append(type.getName()); + sb.append(Constants.CHAR_NAME_DOT); + sb.append(Constants.METHOD_NAME_VALUEOF); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.VARIABLE_NAME_PK); + sb.append(Constants.CHAR_NAME_DOT); + // insert the name of a unpack method + if (type.equals(Boolean.class)) { // Boolean + sb.append(Constants.METHOD_NAME_UNPACKBOOLEAN); + } else if (type.equals(Byte.class)) { // Byte + sb.append(Constants.METHOD_NAME_UNPACKBYTE); + } else if (type.equals(Double.class)) { // Double + sb.append(Constants.METHOD_NAME_UNPACKDOUBLE); + } else if (type.equals(Float.class)) { // Float + sb.append(Constants.METHOD_NAME_UNPACKFLOAT); + } else if (type.equals(Integer.class)) { // Integer + sb.append(Constants.METHOD_NAME_UNPACKINT); + } else if (type.equals(Long.class)) { // Long + sb.append(Constants.METHOD_NAME_UNPACKLONG); + } else if (type.equals(Short.class)) { // Short + sb.append(Constants.METHOD_NAME_UNPACKSHORT); + } else { + throw new NotFoundException("unknown type: " + type.getName()); + } + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + if (field != null) { + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + } + } + + private void insertCodeOfMessageUnpackForListType(StringBuilder sb, + Field field, Class type) throws NotFoundException { + ParameterizedType generic = (ParameterizedType) field + .getGenericType(); + Class genericType = (Class) generic.getActualTypeArguments()[0]; + + // len + sb.append(int.class.getName()); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_SIZE); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_EQUAL); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_PK); + sb.append(Constants.CHAR_NAME_DOT); + sb.append(Constants.METHOD_NAME_UNPACKARRAY); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + + // field initializer + sb.append(field.getName()); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_EQUAL); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.KEYWORD_NEW); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(ArrayList.class.getName()); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + + // for loop + sb.append(Constants.KEYWORD_FOR); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(int.class.getName()); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_I); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_EQUAL); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(0); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_I); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_LESSTHAN); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_SIZE); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_PLUS); + sb.append(Constants.CHAR_NAME_PLUS); + sb.append(Constants.VARIABLE_NAME_I); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_LEFT_CURLY_BRACHET); + sb.append(Constants.CHAR_NAME_SPACE); + + // block + sb.append(field.getName()); + sb.append(Constants.CHAR_NAME_DOT); + sb.append(Constants.METHOD_NAME_ADD); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + insertCodeOfMessageUnpack(sb, null, genericType); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + + sb.append(Constants.CHAR_NAME_RIGHT_CURLY_BRACHET); + sb.append(Constants.CHAR_NAME_SPACE); + } + + private void insertCodeOfMessageUnpackForMapType(StringBuilder sb, + Field field, Class type) throws NotFoundException { + 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(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_SIZE); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_EQUAL); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_PK); + sb.append(Constants.CHAR_NAME_DOT); + sb.append(Constants.METHOD_NAME_UNPACKMAP); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + + // field initializer + sb.append(field.getName()); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_EQUAL); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.KEYWORD_NEW); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(HashMap.class.getName()); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + + // for loop + sb.append(Constants.KEYWORD_FOR); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(int.class.getName()); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_I); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_EQUAL); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(0); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_I); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_LESSTHAN); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.VARIABLE_NAME_SIZE); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_PLUS); + sb.append(Constants.CHAR_NAME_PLUS); + sb.append(Constants.VARIABLE_NAME_I); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SPACE); + sb.append(Constants.CHAR_NAME_LEFT_CURLY_BRACHET); + sb.append(Constants.CHAR_NAME_SPACE); + + // block map. + sb.append(field.getName()); + sb.append(Constants.CHAR_NAME_DOT); + sb.append(Constants.METHOD_NAME_PUT); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + insertCodeOfMessageUnpack(sb, null, genericType0); + sb.append(Constants.CHAR_NAME_COMMA); + sb.append(Constants.CHAR_NAME_SPACE); + insertCodeOfMessageUnpack(sb, null, genericType1); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); + + sb.append(Constants.CHAR_NAME_RIGHT_CURLY_BRACHET); + sb.append(Constants.CHAR_NAME_SPACE); + } + + private void insertCodeOfMessageUnpackForMsgUnpackableType( + StringBuilder sb, Field field, Class type) { + // insert a right variable // ignore + sb.append(Constants.VARIABLE_NAME_PK); + sb.append(Constants.CHAR_NAME_DOT); + sb.append(Constants.METHOD_NAME_UNPACK); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_LEFT_PARENTHESIS); + sb.append(MessageUnpackable.class.getName()); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(field.getName()); + sb.append(Constants.CHAR_NAME_RIGHT_PARENTHESIS); + sb.append(Constants.CHAR_NAME_SEMICOLON); + sb.append(Constants.CHAR_NAME_SPACE); } private void addMessageConvertMethod(CtClass enhCtClass, - CtClass origCtClass, CtField[] fields) + CtClass origCtClass, Field[] fields) throws CannotCompileException { StringBuilder sb = new StringBuilder(); sb.append(Constants.KEYWORD_MODIFIER_PUBLIC).append( @@ -597,7 +702,7 @@ public class PackUnpackUtil { Constants.CHAR_NAME_SPACE); // TODO sb.append(Constants.CHAR_NAME_RIGHT_CURLY_BRACHET); - System.out.println("messageConvert method: " + sb.toString()); + //System.out.println("messageConvert method: " + sb.toString()); CtMethod newCtMethod = CtNewMethod.make(sb.toString(), enhCtClass); enhCtClass.addMethod(newCtMethod); } @@ -684,6 +789,6 @@ public class PackUnpackUtil { ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); Unpacker pac = new Unpacker(in); pac.unpack((MessageUnpackable) dst); - System.out.println(src.equals(dst)); + //System.out.println(src.equals(dst)); } } diff --git a/java/src/test/java/org/msgpack/util/annotation/TestMessagePackUnpackable.java b/java/src/test/java/org/msgpack/util/annotation/TestMessagePackUnpackable.java index 1cde65f2..dbea7cb2 100644 --- a/java/src/test/java/org/msgpack/util/annotation/TestMessagePackUnpackable.java +++ b/java/src/test/java/org/msgpack/util/annotation/TestMessagePackUnpackable.java @@ -3,6 +3,9 @@ package org.msgpack.util.annotation; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -16,9 +19,9 @@ import org.msgpack.Unpacker; public class TestMessagePackUnpackable extends TestCase { @Test - public void testGeneralPrimitiveTypeFields() throws Exception { - GeneralPrimitiveTypeFieldsClass src = (GeneralPrimitiveTypeFieldsClass) PackUnpackUtil - .newEnhancedInstance(GeneralPrimitiveTypeFieldsClass.class); + public void testPrimitiveTypeFields() throws Exception { + PrimitiveTypeFieldsClass src = (PrimitiveTypeFieldsClass) PackUnpackUtil + .newEnhancedInstance(PrimitiveTypeFieldsClass.class); src.f0 = (byte) 0; src.f1 = 1; src.f2 = 2; @@ -28,8 +31,8 @@ public class TestMessagePackUnpackable extends TestCase { src.f6 = false; ByteArrayOutputStream out = new ByteArrayOutputStream(); new Packer(out).pack(src); - GeneralPrimitiveTypeFieldsClass dst = (GeneralPrimitiveTypeFieldsClass) PackUnpackUtil - .newEnhancedInstance(GeneralPrimitiveTypeFieldsClass.class); + PrimitiveTypeFieldsClass dst = (PrimitiveTypeFieldsClass) PackUnpackUtil + .newEnhancedInstance(PrimitiveTypeFieldsClass.class); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); Unpacker pac = new Unpacker(in); pac.unpack((MessageUnpackable) dst); @@ -43,7 +46,7 @@ public class TestMessagePackUnpackable extends TestCase { } @MessagePackUnpackable - public static class GeneralPrimitiveTypeFieldsClass { + public static class PrimitiveTypeFieldsClass { public byte f0; public short f1; public int f2; @@ -52,7 +55,7 @@ public class TestMessagePackUnpackable extends TestCase { public double f5; public boolean f6; - public GeneralPrimitiveTypeFieldsClass() { + public PrimitiveTypeFieldsClass() { } } @@ -107,15 +110,93 @@ public class TestMessagePackUnpackable extends TestCase { } } - public void testListAndMap() throws Exception { + public void testListTypes() throws Exception { + SampleListTypes src = (SampleListTypes) PackUnpackUtil + .newEnhancedInstance(SampleListTypes.class); + src.f0 = new ArrayList(); + src.f1 = new ArrayList(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(src); + SampleListTypes dst = (SampleListTypes) PackUnpackUtil + .newEnhancedInstance(SampleListTypes.class); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + pac.unpack((MessageUnpackable) dst); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + for (int i = 0; i < src.f1.size(); ++i) { + assertEquals(src.f1.get(i), dst.f1.get(i)); + } + assertEquals(src.f2.size(), dst.f2.size()); + for (int i = 0; i < src.f2.size(); ++i) { + assertEquals(src.f2.get(i), dst.f2.get(i)); + } } @MessagePackUnpackable - public static class ListAndMapClass { - public List f0; - public Map f1; + public static class SampleListTypes { + public List f0; + public List f1; + public List f2; - public ListAndMapClass() { + public SampleListTypes() { + } + } + + public void testMapTypes() throws Exception { + SampleMapTypes src = (SampleMapTypes) PackUnpackUtil + .newEnhancedInstance(SampleMapTypes.class); + src.f0 = new HashMap(); + src.f1 = new HashMap(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + new Packer(out).pack(src); + SampleMapTypes dst = (SampleMapTypes) PackUnpackUtil + .newEnhancedInstance(SampleMapTypes.class); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + Unpacker pac = new Unpacker(in); + pac.unpack((MessageUnpackable) dst); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + Iterator srcf1 = src.f1.keySet().iterator(); + Iterator dstf1 = dst.f1.keySet().iterator(); + while (srcf1.hasNext()) { + Integer s1 = srcf1.next(); + Integer d1 = dstf1.next(); + assertEquals(s1, d1); + assertEquals(src.f1.get(s1), dst.f1.get(d1)); + } + assertEquals(src.f2.size(), dst.f2.size()); + Iterator srcf2 = src.f2.keySet().iterator(); + Iterator dstf2 = dst.f2.keySet().iterator(); + while (srcf2.hasNext()) { + String s2 = srcf2.next(); + String d2 = dstf2.next(); + assertEquals(s2, d2); + assertEquals(src.f2.get(s2), dst.f2.get(d2)); + } + } + + @MessagePackUnpackable + public static class SampleMapTypes { + public Map f0; + public Map f1; + public Map f2; + + public SampleMapTypes() { } }