Last active
December 22, 2015 09:28
-
-
Save warmuuh/6451915 to your computer and use it in GitHub Desktop.
generate class and read json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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