KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > enhancer > EnhancementHelper


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19 package org.apache.cayenne.enhancer;
20
21 import org.objectweb.asm.ClassVisitor;
22 import org.objectweb.asm.FieldVisitor;
23 import org.objectweb.asm.Label;
24 import org.objectweb.asm.MethodVisitor;
25 import org.objectweb.asm.Opcodes;
26 import org.objectweb.asm.Type;
27
28 /**
29  * A helper for the ASM ClassVisitor that encapsulates common class enhancement
30  * operations.
31  *
32  * @since 3.0
33  * @author Andrus Adamchik
34  */

35 public class EnhancementHelper {
36
37     /**
38      * Returns whether the field name matches the naming pattern of fields generated by
39      * Cayenne enhancer.
40      */

41     public static boolean isGeneratedField(String JavaDoc name) {
42         return name != null && name.startsWith(fieldPrefix);
43     }
44
45     private static String JavaDoc fieldPrefix = "$cay_";
46     private ClassVisitor classVisitor;
47     private Type currentClass;
48
49     public EnhancementHelper(ClassVisitor classVisitor) {
50         this.classVisitor = classVisitor;
51     }
52
53     public Type getCurrentClass() {
54         return currentClass;
55     }
56
57     public String JavaDoc getPropertyField(String JavaDoc propertyName) {
58         return fieldPrefix + propertyName;
59     }
60
61     public void reset(String JavaDoc className) {
62         // assuming no primitives or arrays
63
this.currentClass = Type.getType("L" + className + ";");
64     }
65
66     public String JavaDoc[] addInterface(String JavaDoc[] interfaces, Class JavaDoc newInterface) {
67
68         String JavaDoc name = Type.getInternalName(newInterface);
69         if (interfaces == null || interfaces.length == 0) {
70             return new String JavaDoc[] {
71                 name
72             };
73         }
74
75         String JavaDoc[] expandedInterfaces = new String JavaDoc[interfaces.length + 1];
76         expandedInterfaces[0] = name;
77         System.arraycopy(interfaces, 0, expandedInterfaces, 1, interfaces.length);
78
79         return expandedInterfaces;
80     }
81
82     /**
83      * Creates a new protected field in the current class. Field name will be
84      * automatically prefixed by "$cay_".
85      */

86     public void createField(Class JavaDoc fieldType, String JavaDoc name) {
87         createField(fieldType, name, false);
88     }
89
90     /**
91      * Creates a new protected field in the current class. Field name will be
92      * automatically prefixed by "$cay_".
93      */

94     public void createField(Class JavaDoc fieldType, String JavaDoc name, boolean isTransient) {
95         Type asmType = Type.getType(fieldType);
96         int access = Opcodes.ACC_PROTECTED;
97         if (isTransient) {
98             access += Opcodes.ACC_TRANSIENT;
99         }
100
101         createField(name, asmType, access);
102     }
103
104     public void createProperty(Class JavaDoc propertyType, String JavaDoc name) {
105         createProperty(propertyType, name, false);
106     }
107
108     public void createProperty(Class JavaDoc propertyType, String JavaDoc name, boolean isTransient) {
109         Type asmType = Type.getType(propertyType);
110
111         int access = Opcodes.ACC_PROTECTED;
112         if (isTransient) {
113             access += Opcodes.ACC_TRANSIENT;
114         }
115
116         createField(name, asmType, access);
117         createGetter(name, asmType);
118         createSetter(name, asmType);
119     }
120
121     private void createSetter(String JavaDoc propertyName, Type asmType) {
122
123         String JavaDoc methodName = "set" + Character.toUpperCase(propertyName.charAt(0));
124         if (propertyName.length() > 1) {
125             methodName += propertyName.substring(1);
126         }
127
128         MethodVisitor mv = classVisitor.visitMethod(Opcodes.ACC_PUBLIC, methodName, "("
129                 + asmType.getDescriptor()
130                 + ")V", null, null);
131         mv.visitCode();
132         Label l0 = new Label();
133         mv.visitLabel(l0);
134         mv.visitVarInsn(Opcodes.ALOAD, 0);
135
136         // TODO: andrus, 10/9/2006 other opcodes
137
if ("I".equals(asmType.getDescriptor())) {
138             mv.visitVarInsn(Opcodes.ILOAD, 1);
139         }
140         else {
141             mv.visitVarInsn(Opcodes.ALOAD, 1);
142         }
143
144         mv.visitFieldInsn(
145                 Opcodes.PUTFIELD,
146                 currentClass.getInternalName(),
147                 getPropertyField(propertyName),
148                 asmType.getDescriptor());
149         mv.visitInsn(Opcodes.RETURN);
150         Label l1 = new Label();
151         mv.visitLabel(l1);
152         mv.visitLocalVariable("this", currentClass.getDescriptor(), null, l0, l1, 0);
153         mv.visitLocalVariable(propertyName, asmType.getDescriptor(), null, l0, l1, 1);
154         mv.visitMaxs(2, 2);
155         mv.visitEnd();
156     }
157
158     private void createGetter(String JavaDoc propertyName, Type asmType) {
159
160         String JavaDoc prefix = "boolean".equals(asmType.getClassName()) ? "is" : "get";
161         String JavaDoc methodName = prefix + Character.toUpperCase(propertyName.charAt(0));
162         if (propertyName.length() > 1) {
163             methodName += propertyName.substring(1);
164         }
165
166         MethodVisitor mv = classVisitor.visitMethod(Opcodes.ACC_PUBLIC, methodName, "()"
167                 + asmType.getDescriptor(), null, null);
168         mv.visitCode();
169         Label l0 = new Label();
170         mv.visitLabel(l0);
171         mv.visitVarInsn(Opcodes.ALOAD, 0);
172         mv.visitFieldInsn(
173                 Opcodes.GETFIELD,
174                 currentClass.getInternalName(),
175                 getPropertyField(propertyName),
176                 asmType.getDescriptor());
177
178         // TODO: andrus, 10/9/2006 other return opcodes
179
if ("I".equals(asmType.getDescriptor())) {
180             mv.visitInsn(Opcodes.IRETURN);
181         }
182         else {
183             mv.visitInsn(Opcodes.ARETURN);
184         }
185
186         Label l1 = new Label();
187         mv.visitLabel(l1);
188         mv.visitLocalVariable("this", currentClass.getDescriptor(), null, l0, l1, 0);
189         mv.visitMaxs(1, 1);
190         mv.visitEnd();
191     }
192
193     private void createField(String JavaDoc propertyName, Type asmType, int access) {
194         FieldVisitor fv = classVisitor.visitField(
195                 access,
196                 getPropertyField(propertyName),
197                 asmType.getDescriptor(),
198                 null,
199                 null);
200         fv.visitEnd();
201     }
202 }
203
Popular Tags