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.exception.Jbi4CorbaRuntimeException;
14  
15  
16  import java.util.HashMap;
17  import java.util.Iterator;
18  import java.util.Map;
19  
20  import org.objectweb.asm.Label;
21  import org.objectweb.asm.MethodVisitor;
22  import org.objectweb.asm.Opcodes;
23  import org.objectweb.asm.Type;
24  import org.objectweb.asm.util.TraceMethodVisitor;
25  
26  /**
27   * This class is used to append (at the default constructor)
28   * the code to initialize some fields.
29   */
30  public class AppenderMethodVisitor extends TraceMethodVisitor {
31  
32    /**
33     * Logger.
34     */
35    private static final Logger LOG
36            = LoggerFactory.getLogger(AppenderMethodVisitor.class);
37  
38   /**
39    * The fields to initialize. (key = fieldName; value = fieldType)
40    */
41    private Map<String, String> mapOfFields = new HashMap<String, String>();
42  
43   /**
44    * The name of the class.
45    */
46    private String className = null;
47  
48    // Utility Object
49    private ByteCodeManipulationUtil bcmUtil = new ByteCodeManipulationUtil();
50    
51  //  private Map<String, InterfaceType> allIntTypes;
52  
53   /**
54    * Constructor.
55    *
56    * @param    mv                 The method visitor.
57    * @param    mapOfFields        The fields to initialize.
58    * @param    className          The name of the class.
59    * @param    allInterfaceTypes  All the Interface type
60    */
61    public AppenderMethodVisitor(MethodVisitor mv,
62                                Map<String, String> mapOfFields,
63                                String className) {
64      super(mv);
65  
66      this.mapOfFields = mapOfFields;
67      this.className = className;
68      
69    }
70  
71    /**
72     * This method appends (before Opcodes.RETURN) the initialization code of
73     * every fields.
74     *
75     * @param    opcode    @see org.objectweb.asm.Opcodes
76     */
77    @Override
78    public void visitInsn(int opcode) {
79      LOG.debug(">>>>> AppenderMethodVisitor.visitInsn - begin");
80      
81      if (Opcodes.RETURN == opcode) {
82        Iterator<String> i = mapOfFields.keySet().iterator();
83        while (i.hasNext()) {
84          String k = i.next();
85          String v = mapOfFields.get(k);
86  
87          LOG.debug("mapOfFields[" + k + "]=" + v);
88  
89          initField(k, v, this);
90        }
91      }
92      LOG.debug("<<<<< AppenderMethodVisitor.visitInsn - end");
93      super.visitInsn(opcode);
94    }
95  
96   
97  	
98    
99    /**
100    * @param fieldName  The field name
101    * @param fieldType  The field type
102    * @param mv         The method visitor
103    */
104   private void initField(String fieldName, String fieldType, MethodVisitor mv) {
105     LOG.debug(">>>>> initField - begin");
106 
107     LOG.debug("fieldName=" + fieldName + "; fieldType=" + fieldType
108             + "; Type.getType(fieldType)=" + Type.getType(fieldType));
109 
110     String jtype = Type.getType(fieldType).getClassName();
111    
112     if (! jtype.endsWith("[]")) {
113         LOG.debug(jtype + " is NOT an array ... "
114                 + "the variable will not be initialized.");
115         return;
116     }
117     // else
118     LOG.debug(jtype + " is an ARRAY.");
119 
120     Label label = new Label();
121    
122     mv.visitLabel(label);
123     mv.visitLineNumber(5, label);
124     mv.visitVarInsn(Opcodes.ALOAD, 0);
125   
126     //mv.visitInsn(Opcodes.ICONST_2);
127     if(fieldType.lastIndexOf("[")>0){
128 
129       for(int i=0;i<fieldType.lastIndexOf("[")+1;i++){
130         mv.visitInsn(Opcodes.ICONST_0);
131       }
132       
133       mv.visitMultiANewArrayInsn(fieldType, fieldType.lastIndexOf("[")+1);
134     }else {
135         mv.visitInsn(Opcodes.ICONST_0);
136         String obj = jtype.substring(0, jtype.length() - 2);
137 
138         if (isAnObject(jtype)) {
139             mv.visitTypeInsn(Opcodes.ANEWARRAY, replaceDotWithSlash(obj));
140         } else {
141             mv.visitIntInsn(Opcodes.NEWARRAY, getOpcode(obj));
142         }
143     }
144     // x = y
145    
146     mv.visitFieldInsn(Opcodes.PUTFIELD,
147                       bcmUtil.bytecodeClassName(className),
148                       fieldName,
149                       fieldType);
150 
151     LOG.debug("<<<<< initField - end");
152   }
153 
154   /**
155    * @param    jtype    The data type to inspect.
156    *
157    * @return    The Opcodes of the java primitive associated to jtype.
158    *
159    * @see        org.objectweb.asm.Opcodes
160    */
161   private int getOpcode(String jtype) {
162     if (boolean.class.getCanonicalName().equals(jtype)) {
163       return Opcodes.T_BOOLEAN;
164     } else if (byte.class.getCanonicalName().equals(jtype)) {
165       return Opcodes.T_BYTE;
166     } else if (char.class.getCanonicalName().equals(jtype)) {
167       return Opcodes.T_CHAR;
168     } else if (double.class.getCanonicalName().equals(jtype)) {
169       return Opcodes.T_DOUBLE;
170     } else if (float.class.getCanonicalName().equals(jtype)) {
171       return Opcodes.T_FLOAT;
172     } else if (int.class.getCanonicalName().equals(jtype)) {
173       return Opcodes.T_INT;
174     } else if (long.class.getCanonicalName().equals(jtype)) {
175       return Opcodes.T_LONG;
176     } else if (short.class.getCanonicalName().equals(jtype)) {
177       return Opcodes.T_SHORT;
178     }
179 
180     LOG.error("CRB000600_Dont_match_any_primitive_java_types", jtype);
181     throw new Jbi4CorbaRuntimeException(
182             "CRB000600_Dont_match_any_primitive_java_types",
183             new Object[] { jtype }, null);
184   }
185 
186   /**
187    * This method replaces the dot with a '/'.
188    *
189    * @param    s    The working path.
190    *
191    * @return    The new string.
192    */
193   private String replaceDotWithSlash(String s) {
194     LOG.debug("replaceDotWithSlash. the input is " + s);
195     if (s == null) {
196       LOG.debug("replaceDotWithSlash. "
197               + "the input is null. returning empty String");
198       return "";
199     }
200     // else
201     if ("".equals(s)) {
202       LOG.debug("replaceDotWithSlash. "
203               + "the input is an empty String. returning empty String");
204       return "";
205     }
206     // else
207     String res = s.replaceAll("\\.", "/");
208     LOG.debug("replaceDotWithSlash.The input is " + s + " returning " + res);
209     return res;
210   }
211 
212 
213  /**
214   * @param    jtype    The data type to inspect.
215   * @return    false, if jtype doesn't contain any dots;
216   *             true, if jtype contains at least a dot.
217   */
218   private boolean isAnObject(String jtype) {
219     if (jtype.indexOf('.') == -1) {
220       LOG.debug(jtype + " is a PRIMITIVE");
221       return false;
222     }
223     // else
224     LOG.debug(jtype + " is an OBJECT.");
225     return true;
226   }
227 
228 }