001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.bytecode;
006:
007: import com.tc.asm.ClassAdapter;
008: import com.tc.asm.ClassVisitor;
009: import com.tc.asm.MethodVisitor;
010: import com.tc.asm.Opcodes;
011: import com.tc.asm.Type;
012:
013: import java.lang.reflect.Method;
014: import java.lang.reflect.Modifier;
015: import java.util.HashMap;
016: import java.util.Iterator;
017: import java.util.Map;
018:
019: /**
020: * Use me to make sure a class overrides all methods from a super class and delegates the call
021: */
022: public class DelegateMethodAdapter extends ClassAdapter implements
023: Opcodes, ClassAdapterFactory {
024:
025: private final Map overrideMethods;
026: private final String delegateField;
027: private final String delegateType;
028: private String this Classname;
029:
030: // This is the real constructor for the actual adapter
031: private DelegateMethodAdapter(ClassVisitor cv, Class super Class,
032: String delegateField) {
033: super (cv);
034: this .delegateField = delegateField;
035: this .overrideMethods = getOverrideMethods(super Class);
036: this .delegateType = super Class.getName().replace('.', '/');
037: }
038:
039: // This constructor is for creating the factory
040: public DelegateMethodAdapter(String delegateType,
041: String delegateField) {
042: super (null);
043: this .delegateField = delegateField;
044: this .delegateType = delegateType;
045: this .overrideMethods = null;
046: }
047:
048: public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) {
049: final Class c;
050: try {
051: c = Class.forName(delegateType, false, loader);
052: } catch (ClassNotFoundException e) {
053: throw new RuntimeException("Unable to load class "
054: + delegateType);
055: }
056:
057: return new DelegateMethodAdapter(visitor, c, delegateField);
058: }
059:
060: public void visit(int version, int access, String name,
061: String signature, String super Name, String[] interfaces) {
062: super .visit(version, access, name, signature, super Name,
063: interfaces);
064: this .this Classname = name;
065: }
066:
067: public MethodVisitor visitMethod(int access, String name,
068: String desc, String signature, String[] exceptions) {
069: String sig = name
070: + Type.getMethodDescriptor(Type.getReturnType(desc),
071: Type.getArgumentTypes(desc));
072: overrideMethods.remove(sig);
073: return super .visitMethod(access, name, desc, signature,
074: exceptions);
075: }
076:
077: public void visitEnd() {
078: for (Iterator iter = overrideMethods.values().iterator(); iter
079: .hasNext();) {
080: Method m = (Method) iter.next();
081:
082: Class[] exceptionTypes = m.getExceptionTypes();
083: String[] exceptions = new String[exceptionTypes.length];
084: for (int i = 0; i < exceptions.length; i++) {
085: exceptions[i] = exceptionTypes[i].getName().replace(
086: '.', '/');
087: }
088:
089: Type[] argumentTypes = Type.getArgumentTypes(m);
090:
091: MethodVisitor mv = super .visitMethod(m.getModifiers(), m
092: .getName(), Type.getMethodDescriptor(m), null,
093: exceptions);
094: mv.visitCode();
095:
096: mv.visitVarInsn(ALOAD, 0);
097: mv.visitFieldInsn(GETFIELD, this Classname, delegateField,
098: "L" + delegateType + ";");
099:
100: int slot = 1;
101: for (int i = 0; i < argumentTypes.length; i++) {
102: Type arg = argumentTypes[i];
103: mv.visitVarInsn(arg.getOpcode(ILOAD), slot);
104: slot += arg.getSize();
105: }
106:
107: mv.visitMethodInsn(INVOKEVIRTUAL, delegateType,
108: m.getName(), Type.getMethodDescriptor(m));
109:
110: Type returnType = Type.getReturnType(m);
111: if (returnType == Type.VOID_TYPE) {
112: mv.visitInsn(RETURN);
113: } else {
114: mv.visitInsn(returnType.getOpcode(IRETURN));
115: }
116:
117: mv.visitMaxs(0, 0);
118: mv.visitEnd();
119: }
120: super .visitEnd();
121: }
122:
123: private static Map getOverrideMethods(Class c) {
124: Map rv = new HashMap();
125: Method[] methods = c.getDeclaredMethods();
126: for (int i = 0; i < methods.length; i++) {
127: Method m = methods[i];
128:
129: int access = m.getModifiers();
130:
131: if (Modifier.isStatic(access) || Modifier.isPrivate(access)) {
132: continue;
133: }
134:
135: if (Modifier.isFinal(access)) {
136: throw new AssertionError(
137: "Final modifier found (must be be removed): "
138: + m.toString());
139: }
140:
141: String sig = m.getName() + Type.getMethodDescriptor(m);
142: Object prev = rv.put(sig, m);
143: if (prev != null) {
144: throw new AssertionError("replaced mapping for " + sig);
145: }
146: }
147: return rv;
148: }
149:
150: }
|