KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > weaving > TopLinkMethodWeaver


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 2005, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.weaving;
23
24 //ASM imports
25
import oracle.toplink.libraries.asm.*;
26
27 import java.util.Iterator JavaDoc;
28
29 /**
30  * INTERNAL:
31  *
32  * Used by TopLink's weaving feature to adjust methods to make use of ValueHolders that
33  * have been inserted by TopLinkClassWeaver.
34  *
35  * For FIELD access, changes references to GETFIELD and PUTFIELD to call newly added
36  * convenience methods.
37  *
38  * For Property access, modifies the getters and setters to make use of new ValueHolders
39  *
40  * Also adds initialization of newly added ValueHolders to constructor.
41  *
42  */

43
44 public class TopLinkMethodWeaver extends CodeAdapter implements Constants {
45
46     protected TopLinkClassWeaver tcw;
47     protected String JavaDoc methodName;
48     private String JavaDoc methodDescriptor = null;
49     
50     // used to determine if we are at the first line of a method
51
private boolean methodStarted = false;
52     
53     // Used to control initialization of valueholders in constructor
54
private boolean constructorInitializationDone = false;
55     
56     public TopLinkMethodWeaver(TopLinkClassWeaver tcw, String JavaDoc methodName, String JavaDoc methodEscriptor,
57         CodeVisitor cv) {
58         
59         super(cv);
60         this.tcw = tcw;
61         this.methodName = methodName;
62         this.methodDescriptor = methodDescriptor;
63     }
64
65     /**
66      * INTERNAL:
67      * Change GETFIELD and PUTFIELD for fields that use attribute access to make use of new convenience methods
68      *
69      * A GETFIELD for an attribute named 'variableName' will be replaced by a call to:
70      *
71      * _toplink_getvariableName()
72      *
73      * A PUTFIELD for an attribute named 'variableName' will be replaced by a call to:
74      *
75      * toplink_setvariableName(variableName)
76      */

77     public void weaveAttributesIfRequired(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc){
78         AttributeDetails attributeDetails = (AttributeDetails)tcw.classDetails.getAttributeDetailsFromClassOrSuperClass(name);
79         if (attributeDetails == null || !attributeDetails.isMappedWithAttributeAccess()){
80             super.visitFieldInsn(opcode, owner, name, desc);
81             return;
82         }
83         if (opcode == GETFIELD) {
84             if (attributeDetails != null) {
85                 cv.visitMethodInsn(INVOKEVIRTUAL, tcw.classDetails.getClassName(), "_toplink_get" + name, "()L" + attributeDetails.getReferenceClass().replace('.','/') + ";");
86             } else {
87                 super.visitFieldInsn(opcode, owner, name, desc);
88             }
89         } else if (opcode == PUTFIELD) {
90             if (attributeDetails != null) {
91                 cv.visitMethodInsn(INVOKEVIRTUAL, tcw.classDetails.getClassName(), "_toplink_set" + name, "(L" + attributeDetails.getReferenceClass().replace('.','/') + ";)V");
92             } else {
93                 super.visitFieldInsn(opcode, owner, name, desc);
94             }
95         } else {
96             super.visitFieldInsn(opcode, owner, name, desc);
97         }
98     }
99
100     /**
101      * INTERNAL:
102      * Add initialization of new ValueHolders to constuctors. If a ValueHolder called 'variableName'
103      * has been added, the following line will be added to the constructor.
104      *
105      * _toplink_variableName_vh = new ValueHolder();
106      */

107     public void weaveConstructorIfRequired(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc){
108         if (!constructorInitializationDone && ("<init>".equals(methodName)||"<cinit>".equals(methodName))) {
109                 // look for the superclass initializer and insert the valueholder
110
// initialization after it
111
if (opcode == INVOKESPECIAL && name.startsWith("<init>")) {
112                 ClassDetails details = tcw.classDetails;
113                 Iterator JavaDoc attributes = details.getAttributesMap().keySet().iterator();
114                 while (attributes.hasNext()){
115                     String JavaDoc key = (String JavaDoc)attributes.next();
116                         
117                     AttributeDetails attribute = (AttributeDetails)details.getAttributesMap().get(key);
118                     if (attribute.weaveValueHolders() && !attribute.isCollectionMapping() && !attribute.isAttributeOnSuperClass()){
119                         super.visitVarInsn(ALOAD, 0);
120                         super.visitTypeInsn(NEW, "oracle/toplink/essentials/indirection/ValueHolder");
121                         super.visitInsn(DUP);
122                         super.visitMethodInsn(INVOKESPECIAL, "oracle/toplink/essentials/indirection/ValueHolder", "<init>", "()V");
123                         super.visitFieldInsn(PUTFIELD, details.className, "_toplink_" + attribute.attributeName + "_vh", "Loracle/toplink/essentials/indirection/ValueHolderInterface;");
124                     }
125                 }
126             }
127             constructorInitializationDone = true;
128         }
129     }
130
131     /**
132      * INTERNAL:
133      * Modifies getter and setter methods for attributes using property access
134      *
135      * In a getter method for 'attributeName', the following line is added at the beginning of the method
136      *
137      * setAttributeName((&lt;AttributeClass&gt;)_toplink_attributeName_vh.getValue());
138      *
139      * In a setter method, for 'attributeName', the following line is added at the beginning of the method
140      *
141      * _toplink_attributeName_vh.setValue(methodArgument);
142      *
143      * TODO: In the end, the call to setValue() should be modified to somehow make use of the result of
144      * the getter method. This behavior has not yet been implemented.
145      */

146     public void addValueHolderReferencesIfRequired(){
147         if (methodStarted){
148             return;
149         }
150         AttributeDetails attributeDetails = (AttributeDetails)tcw.classDetails.getGetterMethodToAttributeDetails().get(methodName);
151         if (attributeDetails != null && !attributeDetails.isAttributeOnSuperClass()){
152             cv.visitVarInsn(ALOAD, 0);
153             cv.visitVarInsn(ALOAD, 0);
154             cv.visitFieldInsn(GETFIELD, tcw.classDetails.getClassName(), "_toplink_" + attributeDetails.getAttributeName() + "_vh", TopLinkClassWeaver.VHI_SIGNATURE);
155             cv.visitMethodInsn(INVOKEINTERFACE, TopLinkClassWeaver.VHI_SHORT_SIGNATURE, "getValue", "()Ljava/lang/Object;");
156             cv.visitTypeInsn(CHECKCAST, attributeDetails.getReferenceClass().replace('.','/'));
157             cv.visitMethodInsn(INVOKEVIRTUAL, tcw.classDetails.getClassName(), attributeDetails.getSetterMethodName(), "(L" + attributeDetails.getReferenceClass().replace('.','/') + ";)V");
158         } else {
159             attributeDetails = (AttributeDetails)tcw.classDetails.getSetterMethodToAttributeDetails().get(methodName);
160             if (attributeDetails != null){
161                 cv.visitVarInsn(ALOAD, 0);
162                 cv.visitFieldInsn(GETFIELD, tcw.classDetails.getClassName(), "_toplink_" + attributeDetails.getAttributeName() + "_vh", "Loracle/toplink/essentials/indirection/ValueHolderInterface;");
163                 cv.visitVarInsn(ALOAD, 1);
164                 cv.visitMethodInsn(INVOKEINTERFACE, TopLinkClassWeaver.VHI_SHORT_SIGNATURE, "setValue", "(Ljava/lang/Object;)V");
165             }
166         }
167     }
168
169     public void visitInsn (final int opcode) {
170         addValueHolderReferencesIfRequired();
171         methodStarted = true;
172         super.visitInsn(opcode);
173     }
174
175     public void visitIntInsn (final int opcode, final int operand) {
176         addValueHolderReferencesIfRequired();
177         methodStarted = true;
178         cv.visitIntInsn(opcode, operand);
179     }
180
181     public void visitVarInsn (final int opcode, final int var) {
182         addValueHolderReferencesIfRequired();
183         methodStarted = true;
184         cv.visitVarInsn(opcode, var);
185     }
186
187     public void visitTypeInsn (final int opcode, final String JavaDoc desc) {
188         addValueHolderReferencesIfRequired();
189         methodStarted = true;
190         cv.visitTypeInsn(opcode, desc);
191     }
192
193     public void visitFieldInsn (final int opcode, final String JavaDoc owner, final String JavaDoc name, final String JavaDoc desc){
194         addValueHolderReferencesIfRequired();
195         methodStarted = true;
196         weaveAttributesIfRequired(opcode, owner, name, desc);
197     }
198
199     public void visitMethodInsn (final int opcode, final String JavaDoc owner, final String JavaDoc name, final String JavaDoc desc){
200         addValueHolderReferencesIfRequired();
201         methodStarted = true;
202         super.visitMethodInsn(opcode, owner, name, desc);
203         weaveConstructorIfRequired(opcode, owner, name, desc);
204     }
205
206     public void visitJumpInsn (final int opcode, final Label label) {
207         addValueHolderReferencesIfRequired();
208         methodStarted = true;
209         cv.visitJumpInsn(opcode, label);
210     }
211
212     public void visitLabel (final Label label) {
213         cv.visitLabel(label);
214     }
215
216     public void visitLdcInsn (final Object JavaDoc cst) {
217         addValueHolderReferencesIfRequired();
218         methodStarted = true;
219         cv.visitLdcInsn(cst);
220     }
221
222     public void visitIincInsn (final int var, final int increment) {
223         addValueHolderReferencesIfRequired();
224         methodStarted = true;
225         cv.visitIincInsn(var, increment);
226     }
227
228     public void visitTableSwitchInsn (final int min, final int max, final Label dflt, final Label labels[]){
229         addValueHolderReferencesIfRequired();
230         methodStarted = true;
231         cv.visitTableSwitchInsn(min, max, dflt, labels);
232     }
233
234     public void visitLookupSwitchInsn (final Label dflt, final int keys[], final Label labels[]){
235         addValueHolderReferencesIfRequired();
236         methodStarted = true;
237         cv.visitLookupSwitchInsn(dflt, keys, labels);
238     }
239
240     public void visitMultiANewArrayInsn (final String JavaDoc desc, final int dims) {
241         addValueHolderReferencesIfRequired();
242         methodStarted = true;
243         cv.visitMultiANewArrayInsn(desc, dims);
244     }
245
246     public void visitTryCatchBlock (final Label start, final Label end,final Label handler, final String JavaDoc type){
247         addValueHolderReferencesIfRequired();
248         methodStarted = true;
249         cv.visitTryCatchBlock(start, end, handler, type);
250     }
251
252     public void visitMaxs (final int maxStack, final int maxLocals) {
253         addValueHolderReferencesIfRequired();
254         methodStarted = true;
255         cv.visitMaxs(0, 0);
256     }
257
258     public void visitLocalVariable (final String JavaDoc name, final String JavaDoc desc, final Label start, final Label end, final int index){
259         addValueHolderReferencesIfRequired();
260         methodStarted = true;
261         cv.visitLocalVariable(name, desc, start, end, index);
262     }
263
264     public void visitLineNumber (final int line, final Label start) {
265         cv.visitLineNumber(line, start);
266     }
267
268     public void visitAttribute (final Attribute attr) {
269         addValueHolderReferencesIfRequired();
270         methodStarted = true;
271         cv.visitAttribute(attr);
272     }
273
274
275     // helper methods
276
protected AttributeDetails weaveValueHolders(ClassDetails startingDetails,
277         String JavaDoc fieldName) {
278         
279         if (startingDetails == null) {
280             return null;
281         } else {
282             AttributeDetails attributeDetails = (AttributeDetails)startingDetails.getAttributesMap().get(fieldName);
283             if (attributeDetails != null && attributeDetails.weaveValueHolders()) {
284                 return attributeDetails;
285             } else {
286                 return weaveValueHolders(startingDetails.getSuperClassDetails(),
287                     fieldName);
288             }
289         }
290     }
291 }
292
Popular Tags