Skip to content

Instantly share code, notes, and snippets.

@warmuuh
Last active December 22, 2015 09:28
Show Gist options
  • Save warmuuh/6451915 to your computer and use it in GitHub Desktop.
Save warmuuh/6451915 to your computer and use it in GitHub Desktop.
generate class and read json
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.PropertyUtils;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
public class GenNewClassTest implements Opcodes {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, JsonProcessingException, IOException {
Class<? extends DBStatusHolder> generatedClass = generateClass(MyTestCase.class, "myProperty");
ObjectMapper mapper = new ObjectMapper();
DBStatusHolder dbQuery = mapper.reader(generatedClass).readValue(
"{"
+ "\"statusId\": 1, "
+ "\"statusMsg\": \"hello\", "
+ "\"myProperty\":{"
+ "\"value\":\"Hello json world!\""
+ "}"
+ "}");
System.out.println("DB Query: " + dbQuery);
MyTestCase retrieved = (MyTestCase) PropertyUtils.getProperty(dbQuery, "myProperty");
System.out.println(retrieved.getValue());
}
private static Class<? extends DBStatusHolder> generateClass(Class propType, String propName) {
ClassWriter e = new ClassWriter(0);
e.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "MyFamousClass",null, "DBStatusHolder", null);
createCtor(e);
String internalName = "L" + propType.getName().replace('.', '/') + ";";
e.visitField(0, propName, internalName, null, null).visitEnd();
createSetter("MyFamousClass", propName, internalName, e);
createGetter("MyFamousClass", propName, internalName, e);
e.visitEnd();
byte[] byteArray = e.toByteArray();
Class loadedClass = loadClass("MyFamousClass", byteArray);
return loadedClass;
}
static void createCtor( ClassWriter e) {
MethodVisitor mv = e.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "DBStatusHolder", "<init>", "()V");
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
static void createSetter(String className, String propertyName, String type, ClassWriter e) {
String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
MethodVisitor mv = e.visitMethod(ACC_PUBLIC, methodName, "(" + type + ")V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(Type.getType(type).getOpcode(ILOAD), 1);
mv.visitFieldInsn(PUTFIELD, className, propertyName, type);
mv.visitInsn(RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
static void createGetter(String className, String propertyName, String returnType, ClassWriter e) {
String methodName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
MethodVisitor mv = e.visitMethod(ACC_PUBLIC, methodName, "()" + returnType, null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, className, propertyName, returnType);
mv.visitInsn(Type.getType(returnType).getOpcode(IRETURN));
mv.visitMaxs(1, 1);
mv.visitEnd();
}
private static Class loadClass(String className, byte[] b) {
//override classDefine (as it is protected) and define the class.
Class clazz = null;
try {
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class cls = Class.forName("java.lang.ClassLoader");
java.lang.reflect.Method method =
cls.getDeclaredMethod("defineClass", new Class[] { String.class, byte[].class, int.class, int.class });
// protected method invocaton
method.setAccessible(true);
try {
Object[] args = new Object[] { className, b, new Integer(0), new Integer(b.length)};
clazz = (Class) method.invoke(loader, args);
} finally {
method.setAccessible(false);
}
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
return clazz;
}
}
class MyTestCase {
String value;
public MyTestCase() {
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
class DBStatusHolder {
private int statusId;
private String statusMsg;
public int getStatusId() {
return statusId;
}
public void setStatusId(int statusId) {
this.statusId = statusId;
}
public String getStatusMsg() {
return statusMsg;
}
public void setStatusMsg(String statusMsg) {
this.statusMsg = statusMsg;
}
@Override
public String toString() {
return "DBStatusHolder [statusId=" + statusId + ", statusMsg=" + statusMsg + "]";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment