View Javadoc

1    /****************************************************************************
2    * Copyright (c) 2005, 2006, 2007, 2008, 2009 Imola Informatica.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the LGPL License v2.1
5    * which accompanies this distribution, and is available at
6    * http://www.gnu.org/licenses/lgpl.html
7    ****************************************************************************/
8   
9   package it.imolinfo.jbi4corba.webservice.generator.bcm;
10  
11  import it.imolinfo.jbi4corba.Logger;
12  import it.imolinfo.jbi4corba.LoggerFactory;
13  import it.imolinfo.jbi4corba.jbi.Messages;
14  
15  import org.objectweb.asm.AnnotationVisitor;
16  import org.objectweb.asm.ClassWriter;
17  import org.objectweb.asm.Label;
18  import org.objectweb.asm.MethodVisitor;
19  import org.objectweb.asm.Opcodes;
20  import org.objectweb.asm.Type;
21  
22  
23  
24  /**
25   * This class is used to supply all the utility methods for the bytecode
26   * manipulation.
27   */
28  public class ByteCodeManipulationUtil {
29  
30      /**
31       * Logger.
32       */
33      private static final Logger LOG
34              = LoggerFactory.getLogger(ByteCodeManipulationUtil.class);
35  
36      /**
37       * The responsible to translate localized messages.
38       */
39      private static final Messages MESSAGES
40              = Messages.getMessages(ByteCodeManipulationUtil.class);
41      
42      /**
43       * XmlAttribute annotation.
44       */
45      public static final String JAXB_XML_ATTRIBUTE = "Ljavax/xml/bind/annotation/XmlAttribute;";    
46  
47      /**
48       * Default constructor.
49       */
50      public ByteCodeManipulationUtil (){
51      }
52      
53      /**
54      * This method remove the '.class' suffix.
55      *
56      * @param    cn    The class name to modify.
57      *
58      * @return    The class name modified.
59      */
60      String bytecodeClassName(String cn) {
61          final String suffix = ".class";
62  
63          if (cn == null) {
64              LOG.error("CRB000601_Class_name_is_null");
65              throw new NullPointerException(
66                      MESSAGES.getString("CRB000601_Class_name_is_null"));
67          }
68  
69          // If .class is not present, do not remove it.
70          int suffixLengthToRemove = 0;
71          if (cn.indexOf(suffix) != -1) {
72          	suffixLengthToRemove = suffix.length();
73          }
74          String bcn = cn.substring(0, cn.length() - suffixLengthToRemove);
75  
76          bcn = bcn.replace(".", "/");
77  
78          LOG.debug("bytecodeClassName:" + bcn);
79          return bcn;
80      }
81  
82      /**
83       * This method add a setter method.
84       *
85       * @param    classWriter        The object used to create the setter.
86       * @param    className          The name of the class.
87       * @param    propertyName       The name of the property of the setter.
88       * @param    type               The type of the property of the setter.
89       *
90       */
91      public void createSetter(ClassWriter classWriter,
92                        String className,
93                        String propertyName,
94                        String type) {
95  
96      LOG.debug(">>>>> createSetter - begin");
97  
98      LOG.debug("createSetter.propertyName=" + propertyName + "; type=" + type);
99  
100     String methodName = "set"
101                         + propertyName.substring(0, 1).toUpperCase()
102                         + propertyName.substring(1);
103 
104     MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC,
105                                                 methodName,
106                                                 "(" + type + ")V",
107                                                 null,
108                                                 null);
109     mv.visitVarInsn(Opcodes.ALOAD, 0);
110     mv.visitVarInsn(Type.getType(type).getOpcode(Opcodes.ILOAD), 1);
111 
112     mv.visitFieldInsn(Opcodes.PUTFIELD,
113                       bytecodeClassName(className),
114                       propertyName,
115                       type);
116 
117     mv.visitInsn(Opcodes.RETURN);
118     mv.visitMaxs(0, 0);
119     mv.visitEnd();
120     LOG.debug("<<<<< createSetter - end");
121     }
122 
123     /**
124      * This method add a getter method.
125      *
126      * @param    classWriter     The object used to create the setter.
127      * @param    className       The name of the class.
128      * @param    propertyName    The name of the property of the getter.
129      * @param    returnType      The type of the property of the getter.
130      * @param    isXmlAttribute  if True, adds the XmlAttribute annotation to the method (useful for exception mapping)
131      *
132      */
133     public void createGetter(ClassWriter classWriter,
134                       String className,
135                       String propertyName,
136                       String returnType, 
137                       boolean isXmlAttribute) {
138 
139         LOG.debug(">>>>> createGetter - begin");
140 
141         LOG.debug("createGetter.propertyName=" + propertyName
142                   + "; returnType=" + returnType);
143 
144         String methodName = "get"
145             + propertyName.substring(0, 1).toUpperCase()
146             + propertyName.substring(1);
147 
148         MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC,
149                                                    methodName,
150                                                    "()" + returnType,
151                                                    null,
152                                                    null);
153         
154         // If isXmlAttribute, adds the XmlAttribute to getter methods
155         if (isXmlAttribute) {
156             LOG.debug("Adding XMLAttribute to getter for the property: " + propertyName);
157             AnnotationVisitor av = null;
158             // We annotate the classes with property access type
159             av = mv.visitAnnotation(JAXB_XML_ATTRIBUTE, true);
160             av.visitEnd();
161         }
162         
163         mv.visitVarInsn(Opcodes.ALOAD, 0);
164 
165         mv.visitFieldInsn(Opcodes.GETFIELD,
166                           bytecodeClassName(className),
167                           propertyName,
168                           returnType);
169 
170         mv.visitInsn(Type.getType(returnType).getOpcode(Opcodes.IRETURN));
171         mv.visitMaxs(0, 0);
172                 
173         mv.visitEnd();
174         
175         
176         LOG.debug("<<<<< createGetter - end");
177     }
178 
179     /**
180     * This method create a method toString().
181     *
182     * <code>
183     *     public String toString() {
184     *         return ReflectionToStringBuilder.toString(this);
185     *     }
186     * </code>
187     *
188     * @param    classWriter        The object used to create the method.
189     */
190     void createToString(ClassWriter classWriter) {
191         MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC,
192                                                 "toString",
193                                                 "()Ljava/lang/String;",
194                                                 null,
195                                                 null);
196         mv.visitCode();
197         Label start = new Label();
198         mv.visitLabel(start);
199         mv.visitLineNumber(53, start);
200         mv.visitVarInsn(Opcodes.ALOAD, 0);
201 
202         mv.visitMethodInsn(
203                 Opcodes.INVOKESTATIC,
204                 "org/apache/commons/lang/builder/ReflectionToStringBuilder",
205                 "toString",
206                 "(Ljava/lang/Object;)Ljava/lang/String;");
207 
208         mv.visitInsn(Opcodes.ARETURN);
209         Label stop = new Label();
210         mv.visitLabel(stop);
211         mv.visitMaxs(1, 1);
212         mv.visitEnd();
213     }
214 
215     /**
216     * This method create a method equals(Object).
217     *
218     * <code>
219     * public boolean equals(Object obj) {
220     *     return EqualsBuilder.reflectionEquals(this, obj);
221     * }
222     * </code>
223     *
224     * @param    classWriter        The object used to create the method.
225     */
226     void createEquals(ClassWriter classWriter) {
227         MethodVisitor mv = classWriter.visitMethod(Opcodes.ACC_PUBLIC,
228                                                 "equals",
229                                                 "(Ljava/lang/Object;)Z",
230                                                 null,
231                                                 null);
232         mv.visitCode();
233         Label start = new Label();
234         mv.visitLabel(start);
235         mv.visitLineNumber(53, start);
236         mv.visitVarInsn(Opcodes.ALOAD, 0);
237         mv.visitVarInsn(Opcodes.ALOAD, 1);
238 
239         mv.visitMethodInsn(
240                 Opcodes.INVOKESTATIC,
241                 "org/apache/commons/lang/builder/EqualsBuilder",
242                 "reflectionEquals",
243                 "(Ljava/lang/Object;Ljava/lang/Object;)Z");
244 
245         mv.visitInsn(Opcodes.IRETURN);
246         Label stop = new Label();
247         mv.visitLabel(stop);
248         mv.visitMaxs(2, 2);
249         mv.visitEnd();
250     }
251 
252 
253 }