in openjpa-kernel/src/main/java/org/apache/openjpa/util/ProxyManagerImpl.java [920:1049]
private void addProxyCollectionMethods(ClassWriterTracker ct, String proxyClassDef, Class type) {
// change tracker
{
ct.getCw().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_TRANSIENT,
"changeTracker", Type.getDescriptor(CollectionChangeTracker.class), null, null).visitEnd();
MethodVisitor mv = ct.visitMethod(Modifier.PUBLIC, "getChangeTracker",
Type.getMethodDescriptor(Type.getType(ChangeTracker.class))
, null, null);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassDef, "changeTracker", Type.getDescriptor(CollectionChangeTracker.class));
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(-1, -1);
mv.visitEnd();
}
// collection copy
{
Constructor cons = findCopyConstructor(type);
if (cons == null && SortedSet.class.isAssignableFrom(type)) {
cons = findComparatorConstructor(type);
}
Class[] params = (cons == null) ? new Class[0]
: cons.getParameterTypes();
MethodVisitor mv = ct.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);
if (params.length == 1) {
mv.visitVarInsn(Opcodes.ALOAD, 1);
if (params[0] == Comparator.class) {
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(SortedSet.class));
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.getInternalName(SortedSet.class), "comparator",
Type.getMethodDescriptor(Type.getType(Comparator.class)), true);
}
else {
// otherwise just pass the parameter
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(params[0]));
}
}
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(type), "<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, AsmHelper.getParamTypes(params)), false);
if (params.length == 0 || params[0] == Comparator.class) {
mv.visitInsn(Opcodes.DUP);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitTypeInsn(Opcodes.CHECKCAST, Type.getInternalName(Collection.class));
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(type), "addAll",
Type.getMethodDescriptor(Type.BOOLEAN_TYPE, Type.getType(Collection.class)), false);
mv.visitInsn(Opcodes.POP);
}
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(-1, -1);
mv.visitEnd();
}
// element type
{
ct.getCw().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_TRANSIENT,
"elementType", Type.getDescriptor(Class.class), null, null).visitEnd();
MethodVisitor mv = ct.visitMethod(Modifier.PUBLIC, "getElementType",
Type.getMethodDescriptor(Type.getType(Class.class))
, null, null);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassDef, "elementType", Type.getDescriptor(Class.class));
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(-1, -1);
mv.visitEnd();
}
// new instance factory
{
MethodVisitor mv = ct.visitMethod(Modifier.PUBLIC, "newInstance",
Type.getMethodDescriptor(Type.getType(ProxyCollection.class),
Type.getType(Class.class), Type.getType(Comparator.class), Type.BOOLEAN_TYPE, Type.BOOLEAN_TYPE)
, null, null);
mv.visitCode();
mv.visitTypeInsn(Opcodes.NEW, proxyClassDef);
mv.visitInsn(Opcodes.DUP);
Constructor cons = findComparatorConstructor(type);
Class[] params = (cons == null) ? new Class[0] : cons.getParameterTypes();
if (params.length == 1) {
mv.visitVarInsn(Opcodes.ALOAD, 2);
}
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, proxyClassDef, "<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, AsmHelper.getParamTypes(params)), false);
mv.visitVarInsn(Opcodes.ASTORE, 5);
mv.visitVarInsn(Opcodes.ALOAD, 5);
mv.visitVarInsn(Opcodes.ALOAD, 1);
mv.visitFieldInsn(Opcodes.PUTFIELD, proxyClassDef, "elementType", Type.getDescriptor(Class.class));
mv.visitVarInsn(Opcodes.ILOAD, 3);
Label lNotTrack = new Label();
mv.visitJumpInsn(Opcodes.IFEQ, lNotTrack);
mv.visitVarInsn(Opcodes.ALOAD, 5);
mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(CollectionChangeTrackerImpl.class));
mv.visitInsn(Opcodes.DUP);
mv.visitVarInsn(Opcodes.ALOAD, 5);
mv.visitInsn(allowsDuplicates(type) ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
mv.visitInsn(isOrdered(type) ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
mv.visitVarInsn(Opcodes.ILOAD, 4);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(CollectionChangeTrackerImpl.class), "<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Collection.class),
Type.BOOLEAN_TYPE, Type.BOOLEAN_TYPE, Type.BOOLEAN_TYPE),
false);
mv.visitFieldInsn(Opcodes.PUTFIELD, proxyClassDef, "changeTracker", Type.getDescriptor(CollectionChangeTracker.class));
mv.visitLabel(lNotTrack);
mv.visitVarInsn(Opcodes.ALOAD, 5);
mv.visitInsn(Opcodes.ARETURN);
mv.visitMaxs(-1, -1);
mv.visitEnd();
}
}