mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-24 17:49:45 +01:00
edit Packer and Unpacker classes, and move org.msgpack.util.annotation.*.java to org.msgpack.util.codegen.*.java
This commit is contained in:
parent
ee1ba5c0f2
commit
2736b88dd5
@ -17,23 +17,22 @@
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
// FIXME package private?
|
||||
public class CustomConverter {
|
||||
public static void register(Class target, MessageConverter converter) {
|
||||
map.put(target, converter);
|
||||
private static ConcurrentHashMap<Class<?>, MessageConverter> map = new ConcurrentHashMap<Class<?>, MessageConverter>();
|
||||
|
||||
public static void register(Class<?> target, MessageConverter converter) {
|
||||
map.putIfAbsent(target, converter);
|
||||
}
|
||||
|
||||
public static MessageConverter get(Class target) {
|
||||
public static MessageConverter get(Class<?> target) {
|
||||
return map.get(target);
|
||||
}
|
||||
|
||||
public static boolean isRegistered(Class target) {
|
||||
public static boolean isRegistered(Class<?> target) {
|
||||
return map.containsKey(target);
|
||||
}
|
||||
|
||||
private static Map<Class, MessageConverter> map = new HashMap<Class, MessageConverter>();
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,19 @@
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
public class CustomMessage {
|
||||
public static void registerPacker(Class target, MessagePacker packer) {
|
||||
public static void registerPacker(Class<?> target, MessagePacker packer) {
|
||||
CustomPacker.register(target, packer);
|
||||
}
|
||||
|
||||
public static void registerTemplate(Class target, Template tmpl) {
|
||||
public static void registerTemplate(Class<?> target, Template tmpl) {
|
||||
CustomUnpacker.register(target, tmpl);
|
||||
CustomConverter.register(target, tmpl);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isAnnotated(Class<?> target, Class<? extends Annotation> with) {
|
||||
return target.getAnnotation(with) != null;
|
||||
}
|
||||
}
|
||||
|
@ -17,23 +17,21 @@
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
// FIXME package private?
|
||||
public class CustomUnpacker {
|
||||
public static void register(Class target, MessageUnpacker converter) {
|
||||
map.put(target, converter);
|
||||
private static ConcurrentHashMap<Class<?>, MessageUnpacker> map = new ConcurrentHashMap<Class<?>, MessageUnpacker>();
|
||||
|
||||
public static void register(Class<?> target, MessageUnpacker converter) {
|
||||
map.putIfAbsent(target, converter);
|
||||
}
|
||||
|
||||
public static MessageUnpacker get(Class target) {
|
||||
public static MessageUnpacker get(Class<?> target) {
|
||||
return map.get(target);
|
||||
}
|
||||
|
||||
public static boolean isRegistered(Class target) {
|
||||
public static boolean isRegistered(Class<?> target) {
|
||||
return map.containsKey(target);
|
||||
}
|
||||
|
||||
private static Map<Class, MessageUnpacker> map = new HashMap<Class, MessageUnpacker>();
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,7 @@
|
||||
//
|
||||
package org.msgpack;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface MessageConverter {
|
||||
public Object convert(MessagePackObject from) throws MessageTypeException;
|
||||
Object convert(MessagePackObject from) throws MessageTypeException;
|
||||
}
|
||||
|
||||
|
@ -485,22 +485,21 @@ public class Packer {
|
||||
if(packer != null) {
|
||||
packer.pack(this, o);
|
||||
return this;
|
||||
} else if (isAnnotated(klass, MessagePackMessage.class)) {
|
||||
} else if (CustomMessage.isAnnotated(klass, MessagePackMessage.class)) {
|
||||
packer = ReflectionPacker.create(klass);
|
||||
packer.pack(this, o);
|
||||
return this;
|
||||
} else if (isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
} else if (CustomMessage.isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
// FIXME DelegatePacker
|
||||
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
||||
} else if (isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
||||
} else if (CustomMessage.isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
||||
// FIXME OrdinalEnumPacker
|
||||
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
||||
}
|
||||
CustomPacker.register(klass, packer);
|
||||
// FIXME check annotations -> code generation -> CustomMessage.registerPacker
|
||||
|
||||
if (packer != null) {
|
||||
CustomMessage.registerPacker(klass, packer);
|
||||
}
|
||||
throw new MessageTypeException("unknown object "+o+" ("+o.getClass()+")");
|
||||
}
|
||||
|
||||
static boolean isAnnotated(Class<?> target, Class<? extends Annotation> with) {
|
||||
return target.getAnnotation(with) != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,12 +18,17 @@
|
||||
package org.msgpack;
|
||||
|
||||
import java.lang.Iterable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.msgpack.annotation.MessagePackDelegate;
|
||||
import org.msgpack.annotation.MessagePackMessage;
|
||||
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
||||
|
||||
/**
|
||||
* Unpacker enables you to deserialize objects from stream.
|
||||
*
|
||||
@ -573,7 +578,7 @@ public class Unpacker implements Iterable<MessagePackObject> {
|
||||
obj.messageUnpack(this);
|
||||
}
|
||||
|
||||
final public Object unpack(Class klass) throws IOException, MessageTypeException, InstantiationException, IllegalAccessException {
|
||||
final public Object unpack(Class<?> klass) throws IOException, MessageTypeException, InstantiationException, IllegalAccessException {
|
||||
if(MessageUnpackable.class.isAssignableFrom(klass)) {
|
||||
Object obj = klass.newInstance();
|
||||
((MessageUnpackable)obj).messageUnpack(this);
|
||||
@ -584,14 +589,25 @@ public class Unpacker implements Iterable<MessagePackObject> {
|
||||
if(unpacker != null) {
|
||||
return unpacker.unpack(this);
|
||||
}
|
||||
|
||||
// FIXME check annotations -> code generation -> CustomMessage.registerTemplate
|
||||
|
||||
|
||||
Template tmpl = null;
|
||||
if (CustomMessage.isAnnotated(klass, MessagePackMessage.class)) {
|
||||
tmpl = ReflectionTemplate.create(klass);
|
||||
return tmpl.unpack(this);
|
||||
} else if (CustomMessage.isAnnotated(klass, MessagePackDelegate.class)) {
|
||||
// FIXME DelegateTemplate
|
||||
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
||||
} else if (CustomMessage.isAnnotated(klass, MessagePackOrdinalEnum.class)) {
|
||||
// FIXME OrdinalEnumTemplate
|
||||
throw new UnsupportedOperationException("not supported yet. : " + klass.getName());
|
||||
}
|
||||
if (tmpl != null) {
|
||||
CustomMessage.registerTemplate(klass, tmpl);
|
||||
}
|
||||
MessageConverter converter = CustomConverter.get(klass);
|
||||
if(converter != null) {
|
||||
return converter.convert(unpackObject());
|
||||
}
|
||||
|
||||
throw new MessageTypeException();
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
160
java/src/main/java/org/msgpack/util/codegen/BasicConstants.java
Normal file
160
java/src/main/java/org/msgpack/util/codegen/BasicConstants.java
Normal file
@ -0,0 +1,160 @@
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
public interface BasicConstants {
|
||||
|
||||
String KEYWORD_MODIFIER_PUBLIC = "public";
|
||||
|
||||
String KEYWORD_CATCH = "catch";
|
||||
|
||||
String KEYWORD_ELSE = "else";
|
||||
|
||||
String KEYWORD_ELSEIF = "else if";
|
||||
|
||||
String KEYWORD_FOR = "for";
|
||||
|
||||
String KEYWORD_IF = "if";
|
||||
|
||||
String KEYWORD_INSTANCEOF = "instanceof";
|
||||
|
||||
String KEYWORD_NEW = "new";
|
||||
|
||||
String KEYWORD_NULL = "null";
|
||||
|
||||
String KEYWORD_THROW = "throw";
|
||||
|
||||
String KEYWORD_THROWS = "throws";
|
||||
|
||||
String KEYWORD_TRY = "try";
|
||||
|
||||
String CHAR_NAME_SPACE = " ";
|
||||
|
||||
String CHAR_NAME_COMMA = ",";
|
||||
|
||||
String CHAR_NAME_EQUAL = "=";
|
||||
|
||||
String CHAR_NAME_PLUS = "+";
|
||||
|
||||
String CHAR_NAME_LESSTHAN = "<";
|
||||
|
||||
String CHAR_NAME_RIGHT_PARENTHESIS = ")";
|
||||
|
||||
String CHAR_NAME_LEFT_PARENTHESIS = "(";
|
||||
|
||||
String CHAR_NAME_RIGHT_CURLY_BRACKET = "}";
|
||||
|
||||
String CHAR_NAME_LEFT_CURLY_BRACKET = "{";
|
||||
|
||||
String CHAR_NAME_RIGHT_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_TARGET = "_$$_target";
|
||||
|
||||
String VARIABLE_NAME_SIZE = "_$$_len";
|
||||
|
||||
String VARIABLE_NAME_ARRAY = "_$$_ary";
|
||||
|
||||
String VARIABLE_NAME_LIST = "_$$_list";
|
||||
|
||||
String VARIABLE_NAME_MAP = "_$$_map";
|
||||
|
||||
String VARIABLE_NAME_KEY = "_$$_key";
|
||||
|
||||
String VARIABLE_NAME_VAL = "_$$_val";
|
||||
|
||||
String VARIABLE_NAME_ITER = "_$$_iter";
|
||||
|
||||
String VARIABLE_NAME_MPO = "_$$_mpo";
|
||||
|
||||
String VARIABLE_NAME_I = "i";
|
||||
|
||||
String METHOD_NAME_VALUEOF = "valueOf";
|
||||
|
||||
String METHOD_NAME_ADD = "add";
|
||||
|
||||
String METHOD_NAME_PUT = "put";
|
||||
|
||||
String METHOD_NAME_GET = "get";
|
||||
|
||||
String METHOD_NAME_SIZE = "size";
|
||||
|
||||
String METHOD_NAME_KEYSET = "keySet";
|
||||
|
||||
String METHOD_NAME_ITERATOR = "iterator";
|
||||
|
||||
String METHOD_NAME_HASNEXT = "hasNext";
|
||||
|
||||
String METHOD_NAME_NEXT = "next";
|
||||
|
||||
String METHOD_NAME_MSGPACK = "messagePack";
|
||||
|
||||
String METHOD_NAME_MSGUNPACK = "messageUnpack";
|
||||
|
||||
String METHOD_NAME_MSGCONVERT = "messageConvert";
|
||||
|
||||
String METHOD_NAME_PACK = "pack";
|
||||
|
||||
String METHOD_NAME_PACKARRAY = "packArray";
|
||||
|
||||
String METHOD_NAME_UNPACK = "unpack";
|
||||
|
||||
String METHOD_NAME_UNPACKBOOLEAN = "unpackBoolean";
|
||||
|
||||
String METHOD_NAME_UNPACKBYTE = "unpackByte";
|
||||
|
||||
String METHOD_NAME_UNPACKDOUBLE = "unpackDouble";
|
||||
|
||||
String METHOD_NAME_UNPACKFLOAT = "unpackFloat";
|
||||
|
||||
String METHOD_NAME_UNPACKINT = "unpackInt";
|
||||
|
||||
String METHOD_NAME_UNPACKLONG = "unpackLong";
|
||||
|
||||
String METHOD_NAME_UNPACKSHORT = "unpackShort";
|
||||
|
||||
String METHOD_NAME_UNPACKSTRING = "unpackString";
|
||||
|
||||
String METHOD_NAME_UNPACKBIGINTEGER = "unpackBigInteger";
|
||||
|
||||
String METHOD_NAME_UNPACKOBJECT = "unpackObject";
|
||||
|
||||
String METHOD_NAME_UNPACKBYTEARRAY = "unpackByteArray";
|
||||
|
||||
String METHOD_NAME_UNPACKARRAY = "unpackArray";
|
||||
|
||||
String METHOD_NAME_UNPACKMAP = "unpackMap";
|
||||
|
||||
String METHOD_NAME_ASARRAY = "asArray";
|
||||
|
||||
String METHOD_NAME_ASBOOLEAN = "asBoolean";
|
||||
|
||||
String METHOD_NAME_ASBYTE = "asByte";
|
||||
|
||||
String METHOD_NAME_ASSHORT = "asShort";
|
||||
|
||||
String METHOD_NAME_ASINT = "asInt";
|
||||
|
||||
String METHOD_NAME_ASFLOAT = "asFloat";
|
||||
|
||||
String METHOD_NAME_ASLONG = "asLong";
|
||||
|
||||
String METHOD_NAME_ASDOUBLE = "asDouble";
|
||||
|
||||
String METHOD_NAME_ASSTRING = "asString";
|
||||
|
||||
String METHOD_NAME_ASBYTEARRAY = "asByteArray";
|
||||
|
||||
String METHOD_NAME_ASBIGINTEGER = "asBigInteger";
|
||||
|
||||
String METHOD_NAME_ASLIST = "asList";
|
||||
|
||||
String METHOD_NAME_ASMAP = "asMap";
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
public interface Constants extends BasicConstants {
|
||||
String POSTFIX_TYPE_NAME_PACKER = "_$$_Packer";
|
||||
|
||||
String POSTFIX_TYPE_NAME_ENHANCER = "_$$_Enhanced";
|
||||
}
|
232
java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java
Normal file
232
java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java
Normal file
@ -0,0 +1,232 @@
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javassist.CannotCompileException;
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtConstructor;
|
||||
import javassist.CtMethod;
|
||||
import javassist.CtNewConstructor;
|
||||
import javassist.CtNewMethod;
|
||||
import javassist.NotFoundException;
|
||||
|
||||
import org.msgpack.MessagePacker;
|
||||
import org.msgpack.Packer;
|
||||
import org.msgpack.Template;
|
||||
|
||||
public class DynamicCodeGen extends DynamicCodeGenBase implements Constants {
|
||||
|
||||
private static DynamicCodeGen INSTANCE;
|
||||
|
||||
private static AtomicInteger COUNTER;
|
||||
|
||||
public static DynamicCodeGen getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new DynamicCodeGen();
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private ClassPool pool;
|
||||
|
||||
private DynamicCodeGen() {
|
||||
this.pool = ClassPool.getDefault();
|
||||
}
|
||||
|
||||
public Class<?> generateMessagePackerClass(Class<?> origClass) {
|
||||
try {
|
||||
String origName = origClass.getName();
|
||||
String packerName = origName + POSTFIX_TYPE_NAME_PACKER;
|
||||
checkClassValidation(origClass);
|
||||
checkDefaultConstructorValidation(origClass);
|
||||
CtClass packerCtClass = pool.makeClass(packerName);
|
||||
setInterface(packerCtClass, MessagePacker.class);
|
||||
addDefaultConstructor(packerCtClass);
|
||||
Field[] fields = getDeclaredFields(origClass);
|
||||
addPackMethod(packerCtClass, origClass, fields);
|
||||
return createClass(packerCtClass);
|
||||
} 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;
|
||||
checkClassValidation(origClass);
|
||||
checkDefaultConstructorValidation(origClass);
|
||||
CtClass packerCtClass = pool.makeClass(packerName);
|
||||
setInterface(packerCtClass, Template.class);
|
||||
addDefaultConstructor(packerCtClass);
|
||||
Field[] fields = getDeclaredFields(origClass);
|
||||
addPackMethod(packerCtClass, origClass, fields);
|
||||
return createClass(packerCtClass);
|
||||
} catch (NotFoundException e) {
|
||||
throw new DynamicCodeGenException(e.getMessage(), e);
|
||||
} catch (CannotCompileException e) {
|
||||
throw new DynamicCodeGenException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkClassValidation(Class<?> origClass) {
|
||||
// not public, abstract, final
|
||||
int mod = origClass.getModifiers();
|
||||
if ((!(Modifier.isPublic(mod) || Modifier.isProtected(mod)))
|
||||
|| Modifier.isAbstract(mod) || Modifier.isFinal(mod)) {
|
||||
throwClassValidationException(origClass,
|
||||
"it must be a public class");
|
||||
}
|
||||
// interface, enum
|
||||
if (origClass.isInterface() || origClass.isEnum()) {
|
||||
throwClassValidationException(origClass,
|
||||
"it must not be an interface or enum");
|
||||
}
|
||||
}
|
||||
|
||||
private static void throwClassValidationException(Class<?> origClass,
|
||||
String msg) {
|
||||
throw new DynamicCodeGenException(msg + ": " + origClass.getName());
|
||||
}
|
||||
|
||||
private void checkDefaultConstructorValidation(Class<?> origClass) {
|
||||
Constructor<?> cons = null;
|
||||
try {
|
||||
cons = origClass.getDeclaredConstructor(new Class[0]);
|
||||
} catch (Exception e1) {
|
||||
throwConstructoValidationException(origClass);
|
||||
}
|
||||
|
||||
int mod = cons.getModifiers();
|
||||
if (!(Modifier.isPublic(mod) || Modifier.isProtected(mod))) {
|
||||
throwConstructoValidationException(origClass);
|
||||
}
|
||||
}
|
||||
|
||||
private static void throwConstructoValidationException(Class<?> origClass) {
|
||||
throw new DynamicCodeGenException(
|
||||
"it must have a public zero-argument constructor: "
|
||||
+ origClass.getName());
|
||||
}
|
||||
|
||||
private void setInterface(CtClass packerCtClass, Class<?> infClass)
|
||||
throws NotFoundException {
|
||||
CtClass infCtClass = pool.get(infClass.getName());
|
||||
packerCtClass.addInterface(infCtClass);
|
||||
}
|
||||
|
||||
private void addDefaultConstructor(CtClass enhCtClass)
|
||||
throws CannotCompileException {
|
||||
CtConstructor newCtCons = CtNewConstructor
|
||||
.defaultConstructor(enhCtClass);
|
||||
enhCtClass.addConstructor(newCtCons);
|
||||
}
|
||||
|
||||
private Field[] getDeclaredFields(Class<?> origClass) {
|
||||
ArrayList<Field> allFields = new ArrayList<Field>();
|
||||
Class<?> nextClass = origClass;
|
||||
while (nextClass != Object.class) {
|
||||
Field[] fields = nextClass.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
try {
|
||||
checkFieldValidation(field, allFields);
|
||||
allFields.add(field);
|
||||
} catch (DynamicCodeGenException e) { // ignore
|
||||
}
|
||||
}
|
||||
nextClass = nextClass.getSuperclass();
|
||||
}
|
||||
return allFields.toArray(new Field[0]);
|
||||
}
|
||||
|
||||
private void checkFieldValidation(Field field, List<Field> 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) || field.isSynthetic()) {
|
||||
throwFieldValidationException(field);
|
||||
}
|
||||
// check same name
|
||||
for (Field f : fields) {
|
||||
if (f.getName().equals(field.getName())) {
|
||||
throwFieldValidationException(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void throwFieldValidationException(Field field) {
|
||||
throw new DynamicCodeGenException("it must be a public field: "
|
||||
+ field.getName());
|
||||
}
|
||||
|
||||
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());
|
||||
CtMethod newCtMethod = CtNewMethod.make(sb.toString(), packerCtClass);
|
||||
packerCtClass.addMethod(newCtMethod);
|
||||
}
|
||||
|
||||
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);
|
||||
insertValueInsertion(sb, mc.toString());
|
||||
insertSemicolon(sb);
|
||||
insertMethodCall(sb, VARIABLE_NAME_PK, METHOD_NAME_PACKARRAY,
|
||||
new String[] { new Integer(fs.length).toString() });
|
||||
insertSemicolon(sb);
|
||||
for (Field f : fs) {
|
||||
insertCodeOfPackCall(sb, f);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertCodeOfPackCall(StringBuilder sb, Field field) {
|
||||
StringBuilder aname = new StringBuilder();
|
||||
aname.append(VARIABLE_NAME_TARGET);
|
||||
aname.append(CHAR_NAME_DOT);
|
||||
aname.append(field.getName());
|
||||
insertMethodCall(sb, VARIABLE_NAME_PK, METHOD_NAME_PACK,
|
||||
new String[] { aname.toString() });
|
||||
insertSemicolon(sb);
|
||||
}
|
||||
|
||||
private Class<?> createClass(CtClass packerCtClass)
|
||||
throws CannotCompileException {
|
||||
return packerCtClass.toClass(null, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DynamicCodeGenBase implements BasicConstants {
|
||||
public DynamicCodeGenBase() {
|
||||
}
|
||||
|
||||
public void insertSemicolon(StringBuilder sb) {
|
||||
sb.append(CHAR_NAME_SEMICOLON);
|
||||
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 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 insertDefaultConsCall(StringBuilder sb, Class<?> type) {
|
||||
// new tname()
|
||||
insertConsCall(sb, type, null);
|
||||
}
|
||||
|
||||
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 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 insertTryCatchBlocks(StringBuilder sb, String tryBody,
|
||||
List<Class<?>> types, List<String> names, List<String> 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 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());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
public class DynamicCodeGenException extends RuntimeException {
|
||||
|
||||
public DynamicCodeGenException(String reason) {
|
||||
super(reason);
|
||||
}
|
||||
|
||||
public DynamicCodeGenException(String reason, Throwable t) {
|
||||
super(reason, t);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
import org.msgpack.MessagePacker;
|
||||
|
||||
public class DynamicCodeGenPacker {
|
||||
|
||||
public static MessagePacker create(Class<?> c) {
|
||||
try {
|
||||
DynamicCodeGen gen = DynamicCodeGen.getInstance();
|
||||
Class<?> packerClass = gen.generateMessagePackerClass(c);
|
||||
return (MessagePacker)packerClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new DynamicCodeGenException(e.getMessage(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new DynamicCodeGenException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
import org.msgpack.Template;
|
||||
|
||||
public class DynamicCodeGenTemplate {
|
||||
public static Template create(Class<?> c) {
|
||||
try {
|
||||
DynamicCodeGen gen = DynamicCodeGen.getInstance();
|
||||
Class<?> tmplClass = gen.generateTemplateClass(c);
|
||||
return (Template) tmplClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new DynamicCodeGenException(e.getMessage(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new DynamicCodeGenException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.msgpack.util.annotation;
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
@ -1,4 +1,4 @@
|
||||
package org.msgpack.util.annotation;
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
@ -1,4 +1,4 @@
|
||||
package org.msgpack.util.annotation;
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
@ -1,4 +1,4 @@
|
||||
package org.msgpack.util.annotation;
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@ -230,7 +230,7 @@ public class PackUnpackUtil {
|
||||
}
|
||||
|
||||
private static void throwClassValidationException(Class<?> origClass) {
|
||||
throw new PackUnpackUtilException(
|
||||
throw new DynamicCodeGenException(
|
||||
"it must be a public class and have @"
|
||||
+ MessagePackUnpackable.class.getName() + ": "
|
||||
+ origClass.getName());
|
||||
@ -260,7 +260,7 @@ public class PackUnpackUtil {
|
||||
|
||||
private static void throwConstructoValidationException(
|
||||
Class<?> origClass) {
|
||||
throw new PackUnpackUtilException(
|
||||
throw new DynamicCodeGenException(
|
||||
"it must have a public zero-argument constructor: "
|
||||
+ origClass.getName());
|
||||
}
|
||||
@ -295,7 +295,7 @@ public class PackUnpackUtil {
|
||||
try {
|
||||
checkFieldValidation(field, allFields);
|
||||
allFields.add(field);
|
||||
} catch (PackUnpackUtilException e) { // ignore
|
||||
} catch (DynamicCodeGenException e) { // ignore
|
||||
}
|
||||
}
|
||||
nextClass = nextClass.getSuperclass();
|
||||
@ -320,7 +320,7 @@ public class PackUnpackUtil {
|
||||
}
|
||||
|
||||
private static void throwFieldValidationException(Field field) {
|
||||
throw new PackUnpackUtilException("it must be a public field: "
|
||||
throw new DynamicCodeGenException("it must be a public field: "
|
||||
+ field.getName());
|
||||
}
|
||||
|
||||
@ -1267,9 +1267,9 @@ public class PackUnpackUtil {
|
||||
try {
|
||||
enhClass = enhancer.generate(origClass, packUnpackable);
|
||||
} catch (NotFoundException e) {
|
||||
throw new PackUnpackUtilException(e.getMessage(), e);
|
||||
throw new DynamicCodeGenException(e.getMessage(), e);
|
||||
} catch (CannotCompileException e) {
|
||||
throw new PackUnpackUtilException(e.getMessage(), e);
|
||||
throw new DynamicCodeGenException(e.getMessage(), e);
|
||||
}
|
||||
// set the generated class to the cache
|
||||
enhancer.setCache(origName, enhClass);
|
||||
@ -1306,9 +1306,9 @@ public class PackUnpackUtil {
|
||||
// create a new object of the generated class
|
||||
return enhClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new PackUnpackUtilException(e.getMessage(), e);
|
||||
throw new DynamicCodeGenException(e.getMessage(), e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new PackUnpackUtilException(e.getMessage(), e);
|
||||
throw new DynamicCodeGenException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
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.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() { }
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackConvert() throws Exception {
|
||||
tString(); // FIXME link StringTemplate
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
MessagePacker packer = DynamicCodeGenPacker.create(StringFieldClass.class);
|
||||
|
||||
StringFieldClass src = new StringFieldClass();
|
||||
|
||||
src.s1 = "kumofs";
|
||||
src.s2 = "frsyuki";
|
||||
|
||||
packer.pack(new Packer(out), src);
|
||||
|
||||
Template tmpl = ReflectionTemplate.create(StringFieldClass.class);
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
|
||||
Object obj = tmpl.unpack(new Unpacker(in));
|
||||
assertEquals(obj.getClass(), StringFieldClass.class);
|
||||
|
||||
StringFieldClass dst = (StringFieldClass)obj;
|
||||
assertEquals(src.s1, dst.s1);
|
||||
assertEquals(src.s2, dst.s2);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.msgpack.util.annotation;
|
||||
package org.msgpack.util.codegen;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@ -16,6 +16,9 @@ import org.msgpack.MessagePackObject;
|
||||
import org.msgpack.MessageUnpackable;
|
||||
import org.msgpack.Packer;
|
||||
import org.msgpack.Unpacker;
|
||||
import org.msgpack.util.codegen.MessagePackUnpackable;
|
||||
import org.msgpack.util.codegen.PackUnpackUtil;
|
||||
import org.msgpack.util.codegen.DynamicCodeGenException;
|
||||
|
||||
public class TestMessagePackUnpackable extends TestCase {
|
||||
|
||||
@ -350,7 +353,7 @@ public class TestMessagePackUnpackable extends TestCase {
|
||||
try {
|
||||
PackUnpackUtil.newEnhancedInstance(NoDefaultConstructorClass.class);
|
||||
fail();
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
assertTrue(true);
|
||||
@ -358,7 +361,7 @@ public class TestMessagePackUnpackable extends TestCase {
|
||||
PackUnpackUtil
|
||||
.newEnhancedInstance(PrivateDefaultConstructorClass.class);
|
||||
fail();
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
assertTrue(true);
|
||||
@ -366,7 +369,7 @@ public class TestMessagePackUnpackable extends TestCase {
|
||||
PackUnpackUtil
|
||||
.newEnhancedInstance(ProtectedDefaultConstructorClass.class);
|
||||
assertTrue(true);
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
fail();
|
||||
}
|
||||
assertTrue(true);
|
||||
@ -374,7 +377,7 @@ public class TestMessagePackUnpackable extends TestCase {
|
||||
PackUnpackUtil
|
||||
.newEnhancedInstance(PackageDefaultConstructorClass.class);
|
||||
fail();
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
assertTrue(true);
|
||||
@ -409,21 +412,21 @@ public class TestMessagePackUnpackable extends TestCase {
|
||||
try {
|
||||
PackUnpackUtil.newEnhancedInstance(PrivateModifierClass.class);
|
||||
fail();
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
assertTrue(true);
|
||||
try {
|
||||
PackUnpackUtil.newEnhancedInstance(ProtectedModifierClass.class);
|
||||
assertTrue(true);
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
fail();
|
||||
}
|
||||
assertTrue(true);
|
||||
try {
|
||||
PackUnpackUtil.newEnhancedInstance(PackageModifierClass.class);
|
||||
fail();
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
assertTrue(true);
|
||||
@ -448,14 +451,14 @@ public class TestMessagePackUnpackable extends TestCase {
|
||||
try {
|
||||
PackUnpackUtil.newEnhancedInstance(FinalModifierClass.class);
|
||||
fail();
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
assertTrue(true);
|
||||
try {
|
||||
PackUnpackUtil.newEnhancedInstance(AbstractModifierClass.class);
|
||||
fail();
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
assertTrue(true);
|
||||
@ -474,14 +477,14 @@ public class TestMessagePackUnpackable extends TestCase {
|
||||
try {
|
||||
PackUnpackUtil.newEnhancedInstance(SampleInterface.class);
|
||||
fail();
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
assertTrue(true);
|
||||
try {
|
||||
PackUnpackUtil.newEnhancedInstance(SampleEnum.class);
|
||||
fail();
|
||||
} catch (PackUnpackUtilException e) {
|
||||
} catch (DynamicCodeGenException e) {
|
||||
assertTrue(true);
|
||||
}
|
||||
assertTrue(true);
|
Loading…
x
Reference in New Issue
Block a user