001: package org.terracotta.modules.lucene_2_0_0;
002:
003: import com.tc.asm.ClassAdapter;
004: import com.tc.asm.ClassVisitor;
005: import com.tc.asm.FieldVisitor;
006: import com.tc.asm.MethodVisitor;
007: import com.tc.asm.Opcodes;
008: import com.tc.asm.Type;
009: import com.tc.object.bytecode.ByteCodeUtil;
010: import com.tc.object.bytecode.ClassAdapterFactory;
011:
012: import java.lang.reflect.Method;
013: import java.lang.reflect.Modifier;
014: import java.util.HashMap;
015: import java.util.HashSet;
016: import java.util.Iterator;
017: import java.util.Map;
018: import java.util.Set;
019: import java.util.Vector;
020: import java.util.Map.Entry;
021:
022: public class RAMFileAdapter extends ClassAdapter implements
023: ClassAdapterFactory, Opcodes {
024:
025: public static final String BUFFERS_FIELD = "buffers";
026:
027: private final Set vectorDelegates = new HashSet();
028: private final Map fields = new HashMap();
029: private String className;
030:
031: public RAMFileAdapter(ClassVisitor cv) {
032: super (cv);
033:
034: // Only delegate the needed methods on the "buffers" vector
035: vectorDelegates.add("elementAt(I)Ljava/lang/Object;");
036: vectorDelegates.add("addElement(Ljava/lang/Object;)V");
037: vectorDelegates.add("size()I");
038: }
039:
040: public RAMFileAdapter() {
041: super (null);
042: }
043:
044: public ClassAdapter create(ClassVisitor visitor, ClassLoader loader) {
045: return new RAMFileAdapter(visitor);
046: }
047:
048: public void visit(int version, int access, String name,
049: String signature, String super Name, String[] interfaces) {
050: super .visit(version, access, name, signature, super Name,
051: interfaces);
052: this .className = name;
053: }
054:
055: public FieldVisitor visitField(int access, String name,
056: String desc, String signature, Object value) {
057: if (!name.startsWith(ByteCodeUtil.TC_FIELD_PREFIX)
058: && !Modifier.isStatic(access)) {
059: // make all fields private -- one of the purposes of this adapter is to make all field access go through methods.
060: // Making fields private will let us know if we missed an outside class
061: access &= ~ACC_PUBLIC;
062: access &= ~ACC_PROTECTED;
063: access |= ACC_PRIVATE;
064:
065: fields.put(name, desc);
066: }
067:
068: return super .visitField(access, name, desc, signature, value);
069: }
070:
071: public void visitEnd() {
072: addGetterSetter();
073: addBufferDelegates();
074: super .visitEnd();
075: }
076:
077: private void addBufferDelegates() {
078: String desc = (String) fields.get(BUFFERS_FIELD);
079:
080: if (desc != null & desc.equals("Ljava/util/Vector;")) {
081: Method[] vectorMetods = Vector.class.getMethods();
082: for (int i = 0; i < vectorMetods.length; i++) {
083: Method method = vectorMetods[i];
084: if (Modifier.isStatic(method.getModifiers())) {
085: continue;
086: }
087:
088: String methodName = method.getName();
089: String methodDesc = Type.getMethodDescriptor(method);
090:
091: if (methodName
092: .startsWith(ByteCodeUtil.TC_METHOD_PREFIX)) {
093: continue;
094: }
095:
096: if (!vectorDelegates.contains(methodName + methodDesc)) {
097: continue;
098: }
099:
100: MethodVisitor mv = super .visitMethod(ACC_PUBLIC,
101: BUFFERS_FIELD + methodName, methodDesc, null,
102: null);
103: mv.visitCode();
104: mv.visitVarInsn(ALOAD, 0);
105: mv.visitFieldInsn(GETFIELD, className, BUFFERS_FIELD,
106: desc);
107:
108: int index = 1;
109: Type[] args = Type.getArgumentTypes(methodDesc);
110: for (int j = 0; j < args.length; j++) {
111: mv.visitVarInsn(args[j].getOpcode(ILOAD), index);
112: index += args[j].getSize();
113: }
114:
115: mv.visitMethodInsn(INVOKEVIRTUAL, "java/util/Vector",
116: methodName, methodDesc);
117: mv.visitInsn(Type.getReturnType(method).getOpcode(
118: IRETURN));
119: mv.visitCode();
120: mv.visitMaxs(0, 0);
121: mv.visitEnd();
122: }
123: }
124: }
125:
126: private void addGetterSetter() {
127: for (Iterator i = fields.entrySet().iterator(); i.hasNext();) {
128: Map.Entry entry = (Entry) i.next();
129: String name = (String) entry.getKey();
130: String desc = (String) entry.getValue();
131:
132: Type type = Type.getType(desc);
133:
134: MethodVisitor mv = super .visitMethod(ACC_PUBLIC, "set"
135: + name, "(" + desc + ")V", null, null);
136: mv.visitCode();
137: mv.visitVarInsn(ALOAD, 0);
138: mv.visitVarInsn(type.getOpcode(ILOAD), 1);
139: mv.visitFieldInsn(PUTFIELD, className, name, desc);
140: mv.visitInsn(RETURN);
141: mv.visitCode();
142: mv.visitMaxs(0, 0);
143: mv.visitEnd();
144:
145: mv = super .visitMethod(ACC_PUBLIC, "get" + name, "()"
146: + desc, null, null);
147: mv.visitCode();
148: mv.visitVarInsn(ALOAD, 0);
149: mv.visitFieldInsn(GETFIELD, className, name, desc);
150: mv.visitInsn(type.getOpcode(IRETURN));
151: mv.visitCode();
152: mv.visitMaxs(0, 0);
153: mv.visitEnd();
154: }
155:
156: }
157:
158: }
|