KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > jdo > tools > enhancer > FieldRefEnhancer


1
2 /*
3  * Copyright (c) 1998 - 2005 Versant Corporation
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  * Versant Corporation - initial API and implementation
11  */

12 package com.versant.core.jdo.tools.enhancer;
13
14 import com.versant.core.jdo.tools.enhancer.utils.*;
15
16 import java.util.*;
17 import java.io.*;
18 import java.net.URL JavaDoc;
19
20 import com.versant.lib.bcel.classfile.*;
21 import com.versant.lib.bcel.generic.*;
22 import com.versant.lib.bcel.Constants;
23 import com.versant.lib.bcel.*;
24 /**
25  * The FieldRefEnhancer catches all the Persistent aware classes
26  */

27 public class FieldRefEnhancer {
28     private ClassLoader JavaDoc loader;
29     private HashMap fieldToEnhanceMap;
30     private ClassGen classGen;
31     private ConstantPoolGen constantPoolGen;
32     private InstructionFactory instructionFactory;
33     private File outputDir;
34     private ArrayList pcList = new ArrayList();
35     private boolean hasChanges;
36     private static final String JavaDoc GET_FIELD = com.versant.lib.bcel.generic.GETFIELD.class.getName();
37     private static final String JavaDoc PUT_FIELD = com.versant.lib.bcel.generic.PUTFIELD.class.getName();
38     private static final String JavaDoc A_LOAD = com.versant.lib.bcel.generic.ALOAD.class.getName();
39     private static final String JavaDoc D_U_P = com.versant.lib.bcel.generic.DUP.class.getName();
40     private int aware;
41     private String JavaDoc fileSeparator;
42     private char charfileSeparator;
43     private File currentOutputFile;
44
45
46     public FieldRefEnhancer(File outputDir,ClassLoader JavaDoc loader) {
47         this.outputDir = outputDir;
48         this.loader = loader;
49         fileSeparator = System.getProperty("file.separator");
50         charfileSeparator = fileSeparator.charAt(0);
51     }
52
53     public void setFieldsToEnhanceMap(HashMap map){
54         fieldToEnhanceMap = map;
55     }
56
57     public int getAwareNum(){
58         return aware;
59     }
60     public void setPersistentCapable(String JavaDoc pcClassName){
61         pcList.add(pcClassName);
62     }
63
64     public void enhance(Set scopeFiles){
65         if (fieldToEnhanceMap.isEmpty())return;
66         Iterator iter = scopeFiles.iterator();
67         while (iter.hasNext()){
68             String JavaDoc fileName = (String JavaDoc)iter.next();
69             try {
70                 hasChanges = false;
71                 JavaClass javaClass = getJavaClass(fileName);
72                 classGen = new ClassGen(javaClass);
73                 if (!pcList.contains(classGen.getClassName())) {
74                     // ConstantPoolGen is used to represent the constant pool of a Classfile
75
constantPoolGen = classGen.getConstantPool();
76                     // used to create objects representing VM instructions
77
instructionFactory = new InstructionFactory(constantPoolGen);
78                     swapGetterAndSetter();
79                     if (hasChanges){
80                         dumpClass();
81                         aware++;
82                         System.out.println("Persistent Aware = " + classGen.getClassName());
83                     }
84                 }
85             } catch (Exception JavaDoc e){
86                 e.printStackTrace(); // TODO fix this
87
}
88         }
89     }
90
91
92     private JavaClass getJavaClass(String JavaDoc className) throws IOException {
93         InputStream inputStream = loader.getResourceAsStream(className);
94         if (inputStream == null) {
95             if (inputStream == null) {
96                 throw new javax.jdo.JDOFatalUserException("Class not found: " + className);
97             }
98         }
99         ClassParser parser = new ClassParser(inputStream, className);
100         return parser.parse();
101     }
102
103     private void dumpClass() throws VerifyException {
104         String JavaDoc fileName = classGen.getClassName().replace('.', charfileSeparator) + ".class";
105         File dumpFile;
106         if (outputDir != null) {
107             dumpFile = new File(outputDir, fileName);
108         } else {
109             URL JavaDoc currentFileURL = loader.getResource(fileName);
110             if (currentFileURL.toString().startsWith("jar:")) {
111                 throw new javax.jdo.JDOFatalUserException("Can not write file " + fileName + " into a jar. Please specify a output directory.");
112             }
113             currentOutputFile = new File(currentFileURL.getFile());
114             dumpFile = currentOutputFile;
115         }
116         try {
117             classGen.getJavaClass().dump(dumpFile);
118         } catch (IOException e) {
119             throw new VerifyException(e);
120         }
121
122     }
123
124
125     private void swapGetterAndSetter() {
126
127         // representation of methods in the class
128
Method[] methods = classGen.getMethods();
129         for (int i = 0; i < methods.length; i++) {
130             Method m = methods[i];
131
132             // native and abstract methods don't have any code
133
// so continue with next method
134
if (m.isNative() || m.isAbstract()) {
135                 continue;
136             }
137             //we do not want to enhance our enhanced methods
138
if (m.getName().startsWith("jdo") || m.getName().startsWith("<c")) {
139                 continue;
140             }
141
142             boolean changed = false;
143
144             MethodGen mg = new MethodGen(m, classGen.getClassName(), constantPoolGen);
145
146             // get the code in form of an InstructionList object
147
InstructionList il = mg.getInstructionList();
148
149             // get the first instruction
150
InstructionHandle ih = il.getStart();
151             while (ih != null) {
152                 Instruction ins = ih.getInstruction();
153                 if (ins.getClass().getName().equals(GET_FIELD)) {//if (ins instanceof GETFIELD)
154
GETFIELD is = (GETFIELD) ins;
155                     if (!is.getFieldName(constantPoolGen).startsWith("jdo")) {
156                         String JavaDoc key = is.getClassName(constantPoolGen) + "|" + is.getFieldName(constantPoolGen);
157                         if (fieldToEnhanceMap.containsKey(key)) {
158                             SwapFieldHelper helper = (SwapFieldHelper) fieldToEnhanceMap.get(key);
159                             // replace it with our static replacement method
160
ih.setInstruction(instructionFactory.createInvoke(
161                                     helper.className,
162                                     helper.jdoGetName,
163                                     helper.type,
164                                     new Type[]{
165                                         new ObjectType(helper.className)
166                                     },
167                                     Constants.INVOKESTATIC));
168                             il.setPositions();
169                             il.update();
170
171                             changed = true;
172                             InstructionHandle prevIhDUP = ih.getPrev();
173                             Instruction iffyDup = prevIhDUP.getInstruction();
174                             if (iffyDup.getClass().getName().equals(D_U_P)) { // The previos ist was a DUP
175
ih = ih.getPrev();
176                                 InstructionHandle prevIhALOAD = ih.getPrev();
177                                 Instruction iffyAload = prevIhALOAD.getInstruction();
178                                 if (iffyAload.getClass().getName().equals(A_LOAD)) { // The inst before that was a ALOAD
179
ALOAD aLoad = (ALOAD) iffyAload;
180                                     ih.setInstruction(aLoad); // Swap ref out
181
il.setPositions();
182                                     il.update();
183                                 } else {
184                                     ih = ih.getNext();
185                                 }
186                             }
187                         }
188                     }
189                 } else if (ins.getClass().getName().equals(PUT_FIELD)) {
190                     PUTFIELD is = (PUTFIELD) ins;
191                     if (!is.getFieldName(constantPoolGen).startsWith("jdo")) {
192                         String JavaDoc key = is.getClassName(constantPoolGen) + "|" + is.getFieldName(constantPoolGen);
193                         if (fieldToEnhanceMap.containsKey(key)) {
194                             SwapFieldHelper helper = (SwapFieldHelper) fieldToEnhanceMap.get(key);
195                             // replace it with our static replacement method
196
ih.setInstruction(instructionFactory.createInvoke(
197                                     helper.className,
198                                     helper.jdoSetName,
199                                     Type.VOID,
200                                     new Type[]{
201                                         new ObjectType(helper.className),
202                                         helper.type
203                                     },
204                                     Constants.INVOKESTATIC));
205                             il.setPositions();
206                             il.update();
207                             changed = true;
208                         }
209                     }
210                 }
211                 // next instruction
212
ih = ih.getNext();
213             }
214             if (changed) {
215                 hasChanges = true;
216                 il.setPositions();
217                 il.update();
218                 mg.setMaxLocals();
219                 mg.setMaxStack();
220                 Method method = mg.getMethod();
221                 classGen.replaceMethod(m, method);
222             }
223         }
224     }
225 }
226
Popular Tags