KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > object > bytecode > MergeTCToJavaClassAdapter


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
3  */

4 package com.tc.object.bytecode;
5
6 import com.tc.asm.ClassAdapter;
7 import com.tc.asm.ClassVisitor;
8 import com.tc.asm.FieldVisitor;
9 import com.tc.asm.MethodAdapter;
10 import com.tc.asm.MethodVisitor;
11 import com.tc.asm.Opcodes;
12 import com.tc.asm.tree.ClassNode;
13 import com.tc.asm.tree.FieldNode;
14 import com.tc.asm.tree.InnerClassNode;
15 import com.tc.asm.tree.MethodNode;
16
17 import java.lang.reflect.Modifier JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.HashSet JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.Set JavaDoc;
24
25 public class MergeTCToJavaClassAdapter extends ChangeClassNameHierarchyAdapter implements Opcodes {
26   private final ClassNode tcClassNode;
27   private final String JavaDoc jFullClassSlashes;
28   private final String JavaDoc tcFullClassSlashes;
29   private final Map JavaDoc instrumentedContext;
30   private final Set JavaDoc visitedMethods;
31   private String JavaDoc superName;
32   private TransparencyClassAdapter dsoAdapter;
33
34   public MergeTCToJavaClassAdapter(ClassVisitor cv, TransparencyClassAdapter dsoAdapter, String JavaDoc jFullClassDots, String JavaDoc tcFullClassDots,
35                                    ClassNode tcClassNode, Map JavaDoc instrumentedContext) {
36     super(cv);
37     this.tcClassNode = tcClassNode;
38     this.jFullClassSlashes = jFullClassDots.replace(DOT_DELIMITER, SLASH_DELIMITER);
39     this.tcFullClassSlashes = tcFullClassDots.replace(DOT_DELIMITER, SLASH_DELIMITER);
40
41     addNewContextIfNotExist(tcFullClassDots, jFullClassDots, instrumentedContext);
42     this.instrumentedContext = instrumentedContext;
43     this.visitedMethods = new HashSet JavaDoc();
44     this.dsoAdapter = dsoAdapter;
45   }
46
47   public void visit(int version, int access, String JavaDoc name, String JavaDoc signature, String JavaDoc superName, String JavaDoc[] interfaces) {
48     this.superName = superName;
49
50     List JavaDoc tcInterfaces = tcClassNode.interfaces;
51     List JavaDoc jInterfaces = new ArrayList JavaDoc();
52     for (int i = 0; i < interfaces.length; i++) {
53       if (!tcInterfaces.contains(interfaces[i])) {
54         jInterfaces.add(interfaces[i]);
55       }
56     }
57     for (Iterator JavaDoc i = tcInterfaces.iterator(); i.hasNext();) {
58       String JavaDoc intf = (String JavaDoc) i.next();
59       jInterfaces.add(intf);
60     }
61     interfaces = new String JavaDoc[jInterfaces.size()];
62     jInterfaces.toArray(interfaces);
63     //super.visit(version, access, name, signature, superName, interfaces);
64
dsoAdapter.visit(version, access, name, signature, superName, interfaces);
65   }
66
67   private String JavaDoc getNewName(String JavaDoc methodName) {
68     if (isInitMethod(methodName)) { return methodName; }
69     return ByteCodeUtil.TC_METHOD_PREFIX + methodName;
70   }
71
72   public MethodVisitor visitMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
73     String JavaDoc methodDesc = name + desc;
74     this.visitedMethods.add(methodDesc);
75
76     List JavaDoc tcMethods = tcClassNode.methods;
77     if (!isInitMethod(name)) {
78       for (Iterator JavaDoc i = tcMethods.iterator(); i.hasNext();) {
79         MethodNode mNode = (MethodNode) i.next();
80         if (mNode.name.equals(name) && mNode.desc.equals(desc)) { return super
81             .visitMethod(ACC_PRIVATE, getNewName(name), desc, signature, exceptions); }
82       }
83     }
84     if (LogicalClassSerializationAdapter.WRITE_OBJECT_SIGNATURE.equals(methodDesc)
85         || LogicalClassSerializationAdapter.READ_OBJECT_SIGNATURE.equals(methodDesc)) { return new LogicalClassSerializationAdapter.LogicalClassSerializationMethodAdapter(
86                                                                                                                                                                            super
87                                                                                                                                                                                .visitMethod(
88                                                                                                                                                                                             access,
89                                                                                                                                                                                             name,
90                                                                                                                                                                                             desc,
91                                                                                                                                                                                             signature,
92                                                                                                                                                                                             exceptions),
93                                                                                                                                                                            jFullClassSlashes); }
94
95     return super.visitMethod(access, name, desc, signature, exceptions);
96   }
97
98   public FieldVisitor visitField(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, Object JavaDoc value) {
99     List JavaDoc tcFields = tcClassNode.fields;
100     for (Iterator JavaDoc i = tcFields.iterator(); i.hasNext();) {
101       FieldNode fieldNode = (FieldNode) i.next();
102       if (access == fieldNode.access && name.equals(fieldNode.name) && desc.equals(fieldNode.desc)) {
103         i.remove();
104         break;
105       }
106     }
107
108     // hack for now
109
if ("java/util/LinkedHashMap".equals(jFullClassSlashes) && "accessOrder".equals(name)) {
110       access = ~Modifier.FINAL & access;
111     }
112     return super.visitField(access, name, desc, signature, value);
113   }
114
115   public void visitEnd() {
116     addTCFields();
117     addTCMethods();
118     addTCInnerClasses();
119     super.visitEnd();
120   }
121
122   private void addTCMethods() {
123     List JavaDoc tcMethods = tcClassNode.methods;
124     for (Iterator JavaDoc i = tcMethods.iterator(); i.hasNext();) {
125       MethodNode mNode = (MethodNode) i.next();
126       if (isInitMethod(mNode.name)) {
127         continue;
128       }
129       mNode.accept(new TCSuperClassAdapter(cv));
130     }
131     LogicalClassSerializationAdapter.addCheckSerializationOverrideMethod(cv, false);
132   }
133
134   private boolean isInitMethod(String JavaDoc methodName) {
135     return "<init>".equals(methodName);
136   }
137
138   private void addTCFields() {
139     List JavaDoc tcFields = tcClassNode.fields;
140     for (Iterator JavaDoc i = tcFields.iterator(); i.hasNext();) {
141       FieldNode fNode = (FieldNode) i.next();
142       fNode.accept(cv);
143     }
144   }
145
146   private void addTCInnerClasses() {
147     List JavaDoc tcInnerClasses = tcClassNode.innerClasses;
148     for (Iterator JavaDoc i = tcInnerClasses.iterator(); i.hasNext();) {
149       InnerClassNode innerClass = (InnerClassNode) i.next();
150       innerClass.accept(new TCSuperClassAdapter(cv));
151     }
152   }
153
154   private class TCSuperClassAdapter extends ClassAdapter implements Opcodes {
155     public TCSuperClassAdapter(ClassVisitor cv) {
156       super(cv);
157     }
158
159     public void visit(int version, int access, String JavaDoc name, String JavaDoc signature, String JavaDoc superName, String JavaDoc[] interfaces) {
160       name = replaceClassName(name);
161       superName = replaceClassName(superName);
162       super.visit(version, access & ~ACC_ABSTRACT, name, signature, superName, interfaces);
163     }
164
165     public MethodVisitor visitMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
166       desc = replaceClassName(desc);
167       signature = replaceClassName(signature);
168       //return new TCSuperMethodAdapter(super.visitMethod(access, name, desc, signature, exceptions));
169
return new TCSuperMethodAdapter(dsoAdapter.basicVisitMethod(access, name, desc, signature, exceptions));
170     }
171
172     private String JavaDoc replaceClassName(String JavaDoc classNameDots) {
173       return replaceClassName(classNameDots, tcFullClassSlashes, jFullClassSlashes);
174     }
175
176     private String JavaDoc replaceClassName(String JavaDoc classNameDots, String JavaDoc srcClassNameDots, String JavaDoc targetClassNameDots) {
177       if (classNameDots == null || classNameDots.length() == 0) { return classNameDots; }
178
179       classNameDots = classNameDots.replace(DOT_DELIMITER, SLASH_DELIMITER);
180       srcClassNameDots = srcClassNameDots.replace(DOT_DELIMITER, SLASH_DELIMITER);
181       targetClassNameDots = targetClassNameDots.replace(DOT_DELIMITER, SLASH_DELIMITER);
182
183       int index = classNameDots.indexOf(srcClassNameDots);
184       if (index == -1) { return classNameDots; }
185
186       StringBuffer JavaDoc newClassName = new StringBuffer JavaDoc();
187       while (index != -1) {
188         if (index > 0) {
189           newClassName.append(classNameDots.substring(0, index));
190         }
191         newClassName.append(targetClassNameDots);
192         classNameDots = classNameDots.substring(index + srcClassNameDots.length());
193         index = classNameDots.indexOf(srcClassNameDots);
194       }
195       newClassName.append(classNameDots);
196       return newClassName.toString();
197     }
198
199     private class TCSuperMethodAdapter extends MethodAdapter implements Opcodes {
200       public TCSuperMethodAdapter(MethodVisitor mv) {
201         super(mv);
202       }
203
204       public void visitMethodInsn(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
205         int index = owner.indexOf(tcFullClassSlashes);
206         if (opcode == INVOKESPECIAL && index == -1) {
207           if (!visitedMethods.contains(name + desc) && !isInitMethod(name)) {
208             owner = superName;
209           } else {
210             ChangeContext context = (ChangeContext) instrumentedContext.get(owner);
211             if (context != null) {
212               owner = context.convertedClassNameSlashes;
213             }
214             name = getNewName(name);
215           }
216           super.visitMethodInsn(opcode, owner, name, desc);
217         } else {
218           owner = replaceClassName(owner);
219           desc = replaceClassName(desc);
220           super.visitMethodInsn(opcode, owner, name, desc);
221         }
222       }
223
224       public void visitFieldInsn(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
225         owner = replaceClassName(owner);
226         desc = replaceClassName(desc);
227         super.visitFieldInsn(opcode, owner, name, desc);
228       }
229
230       public void visitTypeInsn(int opcode, String JavaDoc desc) {
231         ChangeContext context = (ChangeContext) instrumentedContext.get(desc);
232         if (context != null) {
233           desc = context.convertedClassNameSlashes;
234         } else {
235           desc = replaceClassName(desc);
236         }
237         super.visitTypeInsn(opcode, desc);
238       }
239
240     }
241   }
242 }
243
Popular Tags