mirror of https://github.com/apache/openjpa.git
OPENJPA-2909 generate CalendarProxy via ASM
This commit is contained in:
parent
94a2bf97be
commit
87458c708b
|
@ -98,6 +98,7 @@ public class ProxyManagerImpl
|
||||||
|
|
||||||
private static final Localizer _loc = Localizer.forPackage
|
private static final Localizer _loc = Localizer.forPackage
|
||||||
(ProxyManagerImpl.class);
|
(ProxyManagerImpl.class);
|
||||||
|
public static final Type TYPE_OBJECT = Type.getType(Object.class);
|
||||||
|
|
||||||
private static long _proxyId = 0L;
|
private static long _proxyId = 0L;
|
||||||
private static final Map _stdCollections = new HashMap();
|
private static final Map _stdCollections = new HashMap();
|
||||||
|
@ -469,8 +470,7 @@ public class ProxyManagerImpl
|
||||||
ProxyCalendar.class);
|
ProxyCalendar.class);
|
||||||
Class pcls = loadBuildTimeProxy(type, l);
|
Class pcls = loadBuildTimeProxy(type, l);
|
||||||
if (pcls == null)
|
if (pcls == null)
|
||||||
pcls = GeneratedClasses.loadBCClass(
|
pcls = generateAndLoadProxyCalendar(type, true, l);
|
||||||
generateProxyCalendarBytecode(type, true), l);
|
|
||||||
proxy = (ProxyCalendar) instantiateProxy(pcls, null, null);
|
proxy = (ProxyCalendar) instantiateProxy(pcls, null, null);
|
||||||
_proxies.put(type, proxy);
|
_proxies.put(type, proxy);
|
||||||
}
|
}
|
||||||
|
@ -676,15 +676,20 @@ public class ProxyManagerImpl
|
||||||
return GeneratedClasses.loadAsmClass(proxyClassName, classBytes, ProxyDate.class, l);
|
return GeneratedClasses.loadAsmClass(proxyClassName, classBytes, ProxyDate.class, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Class generateAndLoadProxyCalendar(Class type, boolean runtime, ClassLoader l) {
|
||||||
|
final String proxyClassName = getProxyClassName(type, runtime);
|
||||||
|
final byte[] classBytes = generateProxyCalendarBytecode(type, runtime, proxyClassName);
|
||||||
|
|
||||||
|
return GeneratedClasses.loadAsmClass(proxyClassName, classBytes, ProxyDate.class, l);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the bytecode for a date proxy for the given type.
|
* Generate the bytecode for a date proxy for the given type.
|
||||||
*/
|
*/
|
||||||
protected byte[] generateProxyDateBytecode(Class type, boolean runtime, String proxyClassName) {
|
protected byte[] generateProxyDateBytecode(Class type, boolean runtime, String proxyClassName) {
|
||||||
assertNotFinal(type);
|
assertNotFinal(type);
|
||||||
String proxyClassDef = proxyClassName.replace('.', '/');
|
String proxyClassDef = proxyClassName.replace('.', '/');
|
||||||
|
String superClassFileNname = Type.getInternalName(type);
|
||||||
String superClassFileNname = type.getName().replace('.', '/');
|
|
||||||
|
|
||||||
String[] interfaceNames = new String[]{Type.getInternalName(ProxyDate.class)};
|
String[] interfaceNames = new String[]{Type.getInternalName(ProxyDate.class)};
|
||||||
|
|
||||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||||
|
@ -704,6 +709,34 @@ public class ProxyManagerImpl
|
||||||
return cw.toByteArray();
|
return cw.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the bytecode for a calendar proxy for the given type.
|
||||||
|
*/
|
||||||
|
protected byte[] generateProxyCalendarBytecode(Class type, boolean runtime, String proxyClassName) {
|
||||||
|
assertNotFinal(type);
|
||||||
|
String proxyClassDef = proxyClassName.replace('.', '/');
|
||||||
|
String superClassFileNname = Type.getInternalName(type);
|
||||||
|
String[] interfaceNames = new String[]{Type.getInternalName(ProxyCalendar.class)};
|
||||||
|
|
||||||
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||||
|
cw.visit(Opcodes.V11, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, proxyClassDef,
|
||||||
|
null, superClassFileNname, interfaceNames);
|
||||||
|
|
||||||
|
String classFileName = runtime ? type.getName() : proxyClassDef;
|
||||||
|
cw.visitSource(classFileName + ".java", null);
|
||||||
|
|
||||||
|
delegateConstructors(cw, type, superClassFileNname);
|
||||||
|
addInstanceVariables(cw);
|
||||||
|
addProxyMethods(cw, true, proxyClassDef, type);
|
||||||
|
addProxyCalendarMethods(cw, proxyClassDef, type);
|
||||||
|
proxySetters(cw, proxyClassDef, type);
|
||||||
|
addWriteReplaceMethod(cw, proxyClassDef, runtime);
|
||||||
|
|
||||||
|
return cw.toByteArray();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add the instance variables to the class to be generated
|
* add the instance variables to the class to be generated
|
||||||
*/
|
*/
|
||||||
|
@ -808,13 +841,13 @@ public class ProxyManagerImpl
|
||||||
* provide a detached proxy object (null out the StateManager).
|
* provide a detached proxy object (null out the StateManager).
|
||||||
*/
|
*/
|
||||||
MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "clone",
|
MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "clone",
|
||||||
Type.getMethodDescriptor(Type.getType(Object.class))
|
Type.getMethodDescriptor(TYPE_OBJECT)
|
||||||
, null, null);
|
, null, null);
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(parentClass), "clone",
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(parentClass), "clone",
|
||||||
Type.getMethodDescriptor(Type.getType(Object.class)), false);
|
Type.getMethodDescriptor(TYPE_OBJECT), false);
|
||||||
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(Proxy.class));
|
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(Proxy.class));
|
||||||
mv.visitVarInsn(Opcodes.ASTORE, 1);
|
mv.visitVarInsn(Opcodes.ASTORE, 1);
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||||
|
@ -886,8 +919,9 @@ public class ProxyManagerImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "copy",
|
MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "copy",
|
||||||
Type.getMethodDescriptor(Type.getType(Object.class), Type.getType(Object.class))
|
Type.getMethodDescriptor(TYPE_OBJECT, TYPE_OBJECT)
|
||||||
, null, null);
|
, null, null);
|
||||||
|
mv.visitCode();
|
||||||
mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(type));
|
mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(type));
|
||||||
mv.visitInsn(Opcodes.DUP);
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
|
||||||
|
@ -939,6 +973,7 @@ public class ProxyManagerImpl
|
||||||
MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "newInstance",
|
MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "newInstance",
|
||||||
Type.getMethodDescriptor(Type.getType(ProxyDate.class))
|
Type.getMethodDescriptor(Type.getType(ProxyDate.class))
|
||||||
, null, null);
|
, null, null);
|
||||||
|
mv.visitCode();
|
||||||
mv.visitTypeInsn(Opcodes.NEW, proxyClassDef);
|
mv.visitTypeInsn(Opcodes.NEW, proxyClassDef);
|
||||||
mv.visitInsn(Opcodes.DUP);
|
mv.visitInsn(Opcodes.DUP);
|
||||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, proxyClassDef, "<init>",
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, proxyClassDef, "<init>",
|
||||||
|
@ -950,6 +985,130 @@ public class ProxyManagerImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addProxyCalendarMethods(ClassWriter cw, String proxyClassDef, Class type) {
|
||||||
|
// calendar copy
|
||||||
|
{
|
||||||
|
Constructor cons = findCopyConstructor(type);
|
||||||
|
Class[] params = (cons == null) ? new Class[0] : cons.getParameterTypes();
|
||||||
|
|
||||||
|
MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "copy",
|
||||||
|
Type.getMethodDescriptor(TYPE_OBJECT, TYPE_OBJECT)
|
||||||
|
, null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(type));
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(type), "<init>",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE, getParamTypes(params)), false);
|
||||||
|
|
||||||
|
// timeInMillis
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||||
|
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(Calendar.class));
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Calendar.class), "getTimeInMillis",
|
||||||
|
Type.getMethodDescriptor(Type.LONG_TYPE), false);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(type), "setTimeInMillis",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE, Type.LONG_TYPE), false);
|
||||||
|
|
||||||
|
// lenient
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||||
|
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(Calendar.class));
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Calendar.class), "isLenient",
|
||||||
|
Type.getMethodDescriptor(Type.BOOLEAN_TYPE), false);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(type), "setLenient",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE, Type.BOOLEAN_TYPE), false);
|
||||||
|
|
||||||
|
// firstDayOfWeek
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||||
|
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(Calendar.class));
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Calendar.class), "getFirstDayOfWeek",
|
||||||
|
Type.getMethodDescriptor(Type.INT_TYPE), false);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(type), "setFirstDayOfWeek",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE), false);
|
||||||
|
|
||||||
|
// minimalDaysInFirstWeek
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||||
|
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(Calendar.class));
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Calendar.class), "getMinimalDaysInFirstWeek",
|
||||||
|
Type.getMethodDescriptor(Type.INT_TYPE), false);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(type), "setMinimalDaysInFirstWeek",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE), false);
|
||||||
|
|
||||||
|
// timeZone
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||||
|
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(Calendar.class));
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(Calendar.class), "getTimeZone",
|
||||||
|
Type.getMethodDescriptor(Type.getType(TimeZone.class)), false);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(type), "setTimeZone",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(TimeZone.class)), false);
|
||||||
|
|
||||||
|
mv.visitInsn(Opcodes.ARETURN);
|
||||||
|
mv.visitMaxs(-1, -1);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// newInstance factory
|
||||||
|
{
|
||||||
|
MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "newInstance",
|
||||||
|
Type.getMethodDescriptor(Type.getType(ProxyCalendar.class))
|
||||||
|
, null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
mv.visitTypeInsn(Opcodes.NEW, proxyClassDef);
|
||||||
|
mv.visitInsn(Opcodes.DUP);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, proxyClassDef, "<init>",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE), false);
|
||||||
|
|
||||||
|
mv.visitInsn(Opcodes.ARETURN);
|
||||||
|
mv.visitMaxs(-1, -1);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// proxy the protected computeFields method b/c it is called on
|
||||||
|
// mutate, and some setters are final and therefore not proxyable
|
||||||
|
{
|
||||||
|
MethodVisitor mv = cw.visitMethod(Modifier.PROTECTED, "computeFields",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE)
|
||||||
|
, null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
mv.visitInsn(Opcodes.ICONST_1);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(Proxies.class), "dirty",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Proxy.class), Type.BOOLEAN_TYPE), false);
|
||||||
|
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(type), "computeFields",
|
||||||
|
Type.getMethodDescriptor(Type.VOID_TYPE), false);
|
||||||
|
|
||||||
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
mv.visitMaxs(-1, -1);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
// proxy the protected computeFields method b/c it is called on
|
||||||
|
// mutate, and some setters are final and therefore not proxyable
|
||||||
|
m = bc.declareMethod("computeFields", void.class, null);
|
||||||
|
m.makeProtected();
|
||||||
|
code = m.getCode(true);
|
||||||
|
code.aload().setThis();
|
||||||
|
code.constant().setValue(true);
|
||||||
|
code.invokestatic().setMethod(Proxies.class, "dirty", void.class,
|
||||||
|
new Class[] { Proxy.class, boolean.class });
|
||||||
|
code.aload().setThis();
|
||||||
|
code.invokespecial().setMethod(type, "computeFields", void.class, null);
|
||||||
|
code.vreturn();
|
||||||
|
code.calculateMaxStack();
|
||||||
|
code.calculateMaxLocals();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Proxy setter methods of the given type.
|
* Proxy setter methods of the given type.
|
||||||
*
|
*
|
||||||
|
@ -1006,13 +1165,13 @@ public class ProxyManagerImpl
|
||||||
*/
|
*/
|
||||||
private void addWriteReplaceMethod(ClassWriter cw, String proxyClassDef, boolean runtime) {
|
private void addWriteReplaceMethod(ClassWriter cw, String proxyClassDef, boolean runtime) {
|
||||||
MethodVisitor mv = cw.visitMethod(Modifier.PROTECTED, "writeReplace",
|
MethodVisitor mv = cw.visitMethod(Modifier.PROTECTED, "writeReplace",
|
||||||
Type.getMethodDescriptor(Type.getType(Object.class))
|
Type.getMethodDescriptor(TYPE_OBJECT)
|
||||||
, null, new String[]{Type.getInternalName(ObjectStreamException.class)});
|
, null, new String[]{Type.getInternalName(ObjectStreamException.class)});
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
mv.visitInsn(runtime ? Opcodes.ICONST_0 : Opcodes.ICONST_1); // !runtime
|
mv.visitInsn(runtime ? Opcodes.ICONST_0 : Opcodes.ICONST_1); // !runtime
|
||||||
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(Proxies.class), "writeReplace",
|
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(Proxies.class), "writeReplace",
|
||||||
Type.getMethodDescriptor(Type.getType(Object.class), Type.getType(Proxy.class), Type.BOOLEAN_TYPE), false);
|
Type.getMethodDescriptor(TYPE_OBJECT, Type.getType(Proxy.class), Type.BOOLEAN_TYPE), false);
|
||||||
|
|
||||||
mv.visitInsn(Opcodes.ARETURN);
|
mv.visitInsn(Opcodes.ARETURN);
|
||||||
mv.visitMaxs(-1, -1);
|
mv.visitMaxs(-1, -1);
|
||||||
|
@ -1120,25 +1279,6 @@ public class ProxyManagerImpl
|
||||||
|
|
||||||
/* ASM end */
|
/* ASM end */
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate the bytecode for a calendar proxy for the given type.
|
|
||||||
*/
|
|
||||||
protected BCClass generateProxyCalendarBytecode(Class type,
|
|
||||||
boolean runtime) {
|
|
||||||
assertNotFinal(type);
|
|
||||||
Project project = new Project();
|
|
||||||
BCClass bc = AccessController.doPrivileged(J2DoPrivHelper
|
|
||||||
.loadProjectClassAction(project, getProxyClassName(type, runtime)));
|
|
||||||
bc.setSuperclass(type);
|
|
||||||
bc.declareInterface(ProxyCalendar.class);
|
|
||||||
|
|
||||||
delegateConstructors(bc, type);
|
|
||||||
addProxyMethods(bc, true);
|
|
||||||
addProxyCalendarMethods(bc, type);
|
|
||||||
proxySetters(bc, type);
|
|
||||||
addWriteReplaceMethod(bc, runtime);
|
|
||||||
return bc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the bytecode for a bean proxy for the given type.
|
* Generate the bytecode for a bean proxy for the given type.
|
||||||
|
@ -1523,100 +1663,7 @@ public class ProxyManagerImpl
|
||||||
code.calculateMaxStack();
|
code.calculateMaxStack();
|
||||||
code.calculateMaxLocals();
|
code.calculateMaxLocals();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Implement the methods in the {@link ProxyCalendar} interface.
|
|
||||||
*/
|
|
||||||
private void addProxyCalendarMethods(BCClass bc, Class type) {
|
|
||||||
// calendar copy
|
|
||||||
Constructor cons = findCopyConstructor(type);
|
|
||||||
Class[] params = (cons == null) ? new Class[0]
|
|
||||||
: cons.getParameterTypes();
|
|
||||||
|
|
||||||
BCMethod m = bc.declareMethod("copy", Object.class,
|
|
||||||
new Class[] {Object.class});
|
|
||||||
m.makePublic();
|
|
||||||
Code code = m.getCode(true);
|
|
||||||
|
|
||||||
code.anew().setType(type);
|
|
||||||
code.dup();
|
|
||||||
if (params.length == 1) {
|
|
||||||
code.aload().setParam(0);
|
|
||||||
code.checkcast().setType(params[0]);
|
|
||||||
}
|
|
||||||
code.invokespecial().setMethod(type, "<init>", void.class, params);
|
|
||||||
if (params.length == 0) {
|
|
||||||
code.dup();
|
|
||||||
code.aload().setParam(0);
|
|
||||||
code.checkcast().setType(Calendar.class);
|
|
||||||
code.invokevirtual().setMethod(Calendar.class, "getTimeInMillis",
|
|
||||||
long.class, null);
|
|
||||||
code.invokevirtual().setMethod(type, "setTimeInMillis", void.class,
|
|
||||||
new Class[] { long.class });
|
|
||||||
|
|
||||||
code.dup();
|
|
||||||
code.aload().setParam(0);
|
|
||||||
code.checkcast().setType(Calendar.class);
|
|
||||||
code.invokevirtual().setMethod(Calendar.class, "isLenient",
|
|
||||||
boolean.class, null);
|
|
||||||
code.invokevirtual().setMethod(type, "setLenient", void.class,
|
|
||||||
new Class[] { boolean.class });
|
|
||||||
|
|
||||||
code.dup();
|
|
||||||
code.aload().setParam(0);
|
|
||||||
code.checkcast().setType(Calendar.class);
|
|
||||||
code.invokevirtual().setMethod(Calendar.class, "getFirstDayOfWeek",
|
|
||||||
int.class, null);
|
|
||||||
code.invokevirtual().setMethod(type, "setFirstDayOfWeek",
|
|
||||||
void.class, new Class[] { int.class });
|
|
||||||
|
|
||||||
code.dup();
|
|
||||||
code.aload().setParam(0);
|
|
||||||
code.checkcast().setType(Calendar.class);
|
|
||||||
code.invokevirtual().setMethod(Calendar.class,
|
|
||||||
"getMinimalDaysInFirstWeek", int.class, null);
|
|
||||||
code.invokevirtual().setMethod(type, "setMinimalDaysInFirstWeek",
|
|
||||||
void.class, new Class[] { int.class });
|
|
||||||
|
|
||||||
code.dup();
|
|
||||||
code.aload().setParam(0);
|
|
||||||
code.checkcast().setType(Calendar.class);
|
|
||||||
code.invokevirtual().setMethod(Calendar.class, "getTimeZone",
|
|
||||||
TimeZone.class, null);
|
|
||||||
code.invokevirtual().setMethod(type, "setTimeZone", void.class,
|
|
||||||
new Class[] { TimeZone.class });
|
|
||||||
}
|
|
||||||
code.areturn();
|
|
||||||
code.calculateMaxStack();
|
|
||||||
code.calculateMaxLocals();
|
|
||||||
|
|
||||||
// new instance factory
|
|
||||||
m = bc.declareMethod("newInstance", ProxyCalendar.class, null);
|
|
||||||
m.makePublic();
|
|
||||||
code = m.getCode(true);
|
|
||||||
code.anew().setType(bc);
|
|
||||||
code.dup();
|
|
||||||
code.invokespecial().setMethod("<init>", void.class, null);
|
|
||||||
code.areturn();
|
|
||||||
code.calculateMaxStack();
|
|
||||||
code.calculateMaxLocals();
|
|
||||||
|
|
||||||
// proxy the protected computeFields method b/c it is called on
|
|
||||||
// mutate, and some setters are final and therefore not proxyable
|
|
||||||
m = bc.declareMethod("computeFields", void.class, null);
|
|
||||||
m.makeProtected();
|
|
||||||
code = m.getCode(true);
|
|
||||||
code.aload().setThis();
|
|
||||||
code.constant().setValue(true);
|
|
||||||
code.invokestatic().setMethod(Proxies.class, "dirty", void.class,
|
|
||||||
new Class[] { Proxy.class, boolean.class });
|
|
||||||
code.aload().setThis();
|
|
||||||
code.invokespecial().setMethod(type, "computeFields", void.class, null);
|
|
||||||
code.vreturn();
|
|
||||||
code.calculateMaxStack();
|
|
||||||
code.calculateMaxLocals();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement the methods in the {@link ProxyBean} interface.
|
* Implement the methods in the {@link ProxyBean} interface.
|
||||||
*/
|
*/
|
||||||
|
@ -2094,13 +2141,17 @@ public class ProxyManagerImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
// ASM generated proxies
|
// ASM generated proxies
|
||||||
if (Date.class.isAssignableFrom(cls)) {
|
if (Date.class.isAssignableFrom(cls) ||
|
||||||
|
Calendar.class.isAssignableFrom(cls)) {
|
||||||
final String proxyClassName = getProxyClassName(cls, false);
|
final String proxyClassName = getProxyClassName(cls, false);
|
||||||
|
|
||||||
byte[] bytes = null;
|
byte[] bytes = null;
|
||||||
if (Date.class.isAssignableFrom(cls)) {
|
if (Date.class.isAssignableFrom(cls)) {
|
||||||
bytes = mgr.generateProxyDateBytecode(cls, false, proxyClassName);
|
bytes = mgr.generateProxyDateBytecode(cls, false, proxyClassName);
|
||||||
}
|
}
|
||||||
|
else if (Calendar.class.isAssignableFrom(cls)) {
|
||||||
|
bytes = mgr.generateProxyCalendarBytecode(cls, false, proxyClassName);
|
||||||
|
}
|
||||||
if (bytes != null) {
|
if (bytes != null) {
|
||||||
final String fileName = cls.getName().replace('.', '$') + PROXY_SUFFIX + ".class";
|
final String fileName = cls.getName().replace('.', '$') + PROXY_SUFFIX + ".class";
|
||||||
java.nio.file.Files.write(new File(dir, fileName).toPath(), bytes);
|
java.nio.file.Files.write(new File(dir, fileName).toPath(), bytes);
|
||||||
|
@ -2112,8 +2163,6 @@ public class ProxyManagerImpl
|
||||||
bc = mgr.generateProxyCollectionBytecode(cls, false);
|
bc = mgr.generateProxyCollectionBytecode(cls, false);
|
||||||
else if (Map.class.isAssignableFrom(cls))
|
else if (Map.class.isAssignableFrom(cls))
|
||||||
bc = mgr.generateProxyMapBytecode(cls, false);
|
bc = mgr.generateProxyMapBytecode(cls, false);
|
||||||
else if (Calendar.class.isAssignableFrom(cls))
|
|
||||||
bc = mgr.generateProxyCalendarBytecode(cls, false);
|
|
||||||
else {
|
else {
|
||||||
final Class fCls = cls;
|
final Class fCls = cls;
|
||||||
// TODO Move this to J2DOPrivHelper
|
// TODO Move this to J2DOPrivHelper
|
||||||
|
|
Loading…
Reference in New Issue