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   package it.imolinfo.jbi4corba.webservice.generator;
9   
10  import it.imolinfo.jbi4corba.Logger;
11  import it.imolinfo.jbi4corba.LoggerFactory;
12  import it.imolinfo.jbi4corba.exception.ClassGenerationException;
13  import it.imolinfo.jbi4corba.jbi.Messages;
14  
15  import java.lang.reflect.Field;
16  import java.lang.reflect.Method;
17  import java.lang.reflect.Type;
18  import java.util.HashMap;
19  import java.util.List;
20  import java.util.Map;
21  import java.util.Set;
22  
23  /**
24   * Utility class for holder parameters management.
25   * @author marco
26   *
27   */
28  public class HolderUtils {
29      
30      /** Primitive type name -> class map. */
31      private static final Map<String,Class> PRIMITIVE_NAME_TYPE_MAP = new HashMap<String,Class>();
32  
33      /** Setup the primitives map. */
34      
35      static
36      {
37         PRIMITIVE_NAME_TYPE_MAP.put("boolean", Boolean.TYPE);
38         PRIMITIVE_NAME_TYPE_MAP.put("byte", Byte.TYPE);
39         PRIMITIVE_NAME_TYPE_MAP.put("char", Character.TYPE);
40         PRIMITIVE_NAME_TYPE_MAP.put("short", Short.TYPE);
41         PRIMITIVE_NAME_TYPE_MAP.put("int", Integer.TYPE);
42         PRIMITIVE_NAME_TYPE_MAP.put("long", Long.TYPE);
43         PRIMITIVE_NAME_TYPE_MAP.put("float", Float.TYPE);
44         PRIMITIVE_NAME_TYPE_MAP.put("double", Double.TYPE);
45      }
46      
47      private static final Map<String,Class> PRIMITIVE_NAME_CLASS_MAP = new HashMap<String,Class>();
48  
49      /** Setup the primitives map. */
50      /**FIX for the correct generation of the wsdl the primitive are replaced with Class**/
51      static
52      {
53      	PRIMITIVE_NAME_CLASS_MAP.put("boolean", Boolean.class);
54      	PRIMITIVE_NAME_CLASS_MAP.put("byte", Byte.class);
55      	PRIMITIVE_NAME_CLASS_MAP.put("char", Character.class);
56      	PRIMITIVE_NAME_CLASS_MAP.put("short", Short.class);
57      	PRIMITIVE_NAME_CLASS_MAP.put("int", Integer.class);
58      	PRIMITIVE_NAME_CLASS_MAP.put("long", Long.class);
59      	PRIMITIVE_NAME_CLASS_MAP.put("float", Float.class);
60      	PRIMITIVE_NAME_CLASS_MAP.put("double", Double.class);
61      }
62      
63      // interface replacement descriptor type 
64      // private static final String W3CEPR = org.objectweb.asm.Type.getDescriptor(javax.xml.ws.wsaddressing.W3CEndpointReference.class);
65      private static final String W3CEPR = "javax.xml.ws.wsaddressing.W3CEndpointReference";
66      
67      /**
68       * Logger.
69       */
70      private static final Logger LOG
71        = LoggerFactory.getLogger(HolderUtils.class);
72      private static final Messages MESSAGES = 
73      	Messages.getMessages(HolderUtils.class);
74  
75      
76      /**
77       * Calculate the Corba Holder value type class and set it in the Param of the <code>MethodSignature</code>.
78       * Gets also the interface class type.
79       * @param classesDir
80       * @param methodSignatures
81       * @param interfaceTypes 
82       * @param unionTypes 
83       * @throws ClassGenerationException
84       */
85      public static void populateCorbaHolderValueType(String classesDir, List<MethodSignature> methodSignatures, Set<String> unionTypes, Set<String> interfaceTypes) 
86          throws ClassGenerationException {      
87              	
88          for (MethodSignature methodSignature: methodSignatures) {
89              String interfaceClassTypeName = methodSignature.getClassName();
90              Class interfaceClassType = Util.classLoad(classesDir, interfaceClassTypeName, true);
91              methodSignature.setClassType(interfaceClassType);
92                                  	
93              for (Param param: methodSignature.getParameters()) {              
94                  try {
95                      Class typeClass = getTypeClass(param.getTypeName(), classesDir, interfaceClassType, param.isArray());
96                      param.setType(typeClass);
97                      param.setTypeName(typeClass.getName());
98                      // if the class is an holder, gets the value
99                      if (param.isHolder()) {                        
100                         // Gets the class value
101                         Field value = typeClass.getField("value");                        
102                         // sets the holder data in the object 
103                         param.setHolderType(typeClass);     
104                         
105                         if(isPrimitive(value.getType().getName())){
106                         	param.setPrimitive(true);
107                         	param.setHolderValueType((Class)PRIMITIVE_NAME_CLASS_MAP.get(value.getType().getName()));
108                         	
109                         }else{
110                         	
111                         	param.setHolderValueType(value.getType());
112                         }
113                           
114                       
115                     }                                       
116                     
117                 } catch (SecurityException e) {
118                 	String msg=MESSAGES.getString("CRB000558_Error_in_holder_inspection");
119                     LOG.error(msg,e);
120                     throw new ClassGenerationException(msg,e);
121 
122                 } catch (NoSuchFieldException e) {
123                 	String msg=MESSAGES.getString("CRB000558_Error_in_holder_inspection");
124                     LOG.error(msg,e);
125                     throw new ClassGenerationException(msg,e);
126                 }catch (IllegalArgumentException e) {
127                 	String msg=MESSAGES.getString("CRB000558_Error_in_holder_inspection");
128                     LOG.error(msg,e);
129                     throw new ClassGenerationException(msg,e);
130                 }                    
131             }
132             
133             // Gets the interface methods
134             Method[] methods = interfaceClassType.getMethods();
135             
136             // look for the method
137             for(int i = 0; i < methods.length; i++) {
138                 if (findMethod(methods[i], methodSignature, true, unionTypes, interfaceTypes)) {
139                     methodSignature.setMethod(methods[i]);
140                 }
141             }           
142         }
143     }
144     
145     /**
146      * True if the <code>MethodSignature</code> is the same as the
147      * <code>Method</code>. If the parameter is an Holder, two beahviour are implemented: <br/>
148      * <li/> if <code>compareHolderTypes == true the comparison is with the <code>Param</code> holderType class name.
149      * <li/> if <code>compareHolderTypes == false </code> the comparison is with the <code>Param</code>type class name. 
150      *  
151      * @param method
152      * @param methodSignature
153      * @param compareHolderTypes
154      * @param setOfInterfaces 
155      * @param setOfUnions 
156      * 
157      * @return
158      */
159     private static boolean findMethod(Method method, MethodSignature methodSignature, boolean compareHolderTypes, Set<String> setOfUnions, Set<String> setOfInterfaces) {
160       
161         if(!method.getName().equals(methodSignature.getMethodName())) {
162             // False if the name is different
163             return false;
164         } else if (!(method.getParameterTypes().length == methodSignature.getParameters().size())) {
165             // False if the length param is different 
166             return false;
167         }             		    		
168         for (int i = 0; i < method.getParameterTypes().length; i++) {
169            
170         	        	
171             Type parameterType = (Type)method.getGenericParameterTypes()[i];                        
172             	
173             String paramTypeFromMethodAsString = "";
174             if (parameterType instanceof Class) {
175                 paramTypeFromMethodAsString = getTypeName((Class)parameterType);    
176             } else {            		          
177               	paramTypeFromMethodAsString = parameterType.toString();		            	           	
178             }       
179             Param param = methodSignature.getParameters().get(i);
180             
181             // If is not an holder or i do not care about holder comparison... 
182             if (!param.isHolder() || !compareHolderTypes) {
183                 // Normal parameter                
184 
185                 String paramTypeStr = param.getTypeName();
186                 
187                 // union type
188                 boolean isSearchedType = false;
189                 String paramTypeModified = null;               
190                 if (setOfUnions.contains(paramTypeStr) && !compareHolderTypes)
191                 {
192                 	isSearchedType = true;
193                 	paramTypeModified = param.getTypeName() + "Wrapper";               	
194                 }
195                               
196                 if (setOfInterfaces.contains(paramTypeStr)  && !compareHolderTypes)
197                 {
198                 	isSearchedType = true;
199                 	paramTypeModified =  W3CEPR;              	
200                 }
201 
202                 if (paramTypeStr.equals(AnyType.CORBA_ANY_TYPE)  && !compareHolderTypes)
203                 {
204                 	isSearchedType = true;
205                 	paramTypeModified = "java.lang.Object";               	
206                 }
207 
208                 // If an array, the [] must be added
209                 if (param.isArray()) {
210                     // Adds the array "[]"
211                     for (int j = 0; j < param.getArrayDimension(); j++) {
212                         paramTypeStr = paramTypeStr + "[]";
213                         if (!compareHolderTypes)
214                         	paramTypeModified = paramTypeModified + "[]";
215 
216                     }
217                 }
218                 if (!paramTypeStr.equals(paramTypeFromMethodAsString) && !isSearchedType && !param.isHolder()) {
219                 
220                     return false;
221                }
222                 
223                 
224                 if(paramTypeModified!=null){
225                 
226                     if (!paramTypeModified.equals(paramTypeFromMethodAsString) && isSearchedType) {
227                 	
228                         return false;
229                     }
230                 }
231                 // for SearchedTypes we should look also at holders
232                 if (param.isHolder())
233                 {
234                 	String holderType =TypeUtils.getTypeNameWithoutBrackets(param.getHolderValueType());
235                 	StringBuffer holderWithSearchedType = new StringBuffer("javax.xml.ws.Holder<");
236                 	isSearchedType = false;
237                 	if (setOfUnions.contains(holderType))
238                     {
239                 		isSearchedType = true;
240                 		holderWithSearchedType.append(holderType);
241                 		holderWithSearchedType.append("Wrapper");
242                 		
243                     }
244                	if (setOfInterfaces.contains(holderType))
245                    {
246                		isSearchedType = true;
247                		holderWithSearchedType.append(W3CEPR);
248                		
249                    }
250                	if (holderType.equals(AnyType.CORBA_ANY_TYPE))
251                 {
252                 	isSearchedType = true;
253                 	holderWithSearchedType.append("java.lang.Object");
254                 }
255                 	holderWithSearchedType.append(">");
256                 	
257                 	if (!holderWithSearchedType.toString().equals(paramTypeFromMethodAsString) && isSearchedType) {
258                     	
259                         return false;
260                    }
261                 }
262                 
263 
264             } else {                              
265                 // Holder       
266             	
267                 if (!param.getHolderType().getCanonicalName().equals(paramTypeFromMethodAsString)) {
268                     return false;
269                 }
270             }
271         }   
272         return true;
273     }
274     
275     /**
276      * If the method contains holder parameters, the signature can be changed, so try
277      * to conect the <MethodSignature> with the  <code>Method</code> object.
278      * @param method
279      * @param methodSignature
280      * @param classesDir
281      * @param interfaceTypes 
282      * @param unionTypes 
283      * @return
284      * @throws ClassGenerationException 
285      */
286     public static void populateChangedMethod(MethodSignature methodSignature, String classesDir, Set<String> unionTypes, Set<String> interfaceTypes) throws ClassGenerationException {
287 
288         String className = methodSignature.getClassName();
289         Class interfaceClassType = Util.classLoad(classesDir, className);
290 
291         // Gets the interface methods
292         Method[] methods = interfaceClassType.getMethods();
293 
294         // look for the method
295             
296         for(int i = 0; i < methods.length; i++) {
297         	        		        	
298             if (findMethod(methods[i], methodSignature, false, unionTypes, interfaceTypes)) {            	
299                 methodSignature.setChangedMethod(methods[i]);             
300                 // TODO: add break when the method was found....
301             }
302         }
303     }
304     
305    
306     /**
307      * Try to load the class from the className.
308      * First of all, try to load the class direclty. If no class is found, try to add the 
309      * interface package name. If no class is further found, try to add the "java.lang" default package 
310      * @param className
311      * @param classesDir
312      * @param interfaceClassType
313      * @return
314      * @throws ClassGenerationException 
315      */
316     private static Class getTypeClass(String className, String classesDir, Class interfaceClassType, boolean isArray) throws ClassGenerationException {
317         Class typeClass = null;
318 
319         // Catch the primitive types:
320         if (isPrimitive(className)) {
321             typeClass = (Class) PRIMITIVE_NAME_TYPE_MAP.get(className); 
322         } else {
323             // otherwise, try to load th class directly
324             typeClass = Util.classLoadQuiet(classesDir, className);
325         }
326 
327         // Try adding the interface package to the type.
328         if (typeClass == null) {
329             LOG.debug("No type class found. Let's try adding the interface class package");
330              String classWithInterfacePackage=null;
331              if(interfaceClassType.getPackage()!=null){
332             	 classWithInterfacePackage = interfaceClassType.getPackage().getName() + "." + className;
333             }else{
334             	 classWithInterfacePackage = interfaceClassType.getName() + "." + className;
335             }
336             typeClass = Util.classLoadQuiet(classesDir, classWithInterfacePackage);            
337         }
338 
339         // Try adding the java.lang package to the type.
340         if (typeClass == null) {
341             LOG.debug("No type class found. Let's try adding the the java.lang package");
342             String classWithJavaLangPackage = "java.lang." +  className;    
343             typeClass = Util.classLoadQuiet(classesDir, classWithJavaLangPackage);
344             typeClass = Util.classLoadQuiet(classesDir, classWithJavaLangPackage);
345         }
346 
347         // If no class is found, throws an exception
348         if (typeClass == null) {
349         	String msg=MESSAGES.getString("CRB000559_Error_in_getting_the_parameter_class", 
350         			new Object[] {className});
351             LOG.error(msg);
352             throw new ClassGenerationException(msg);
353 
354 
355         }
356         return typeClass;
357     }
358     
359     /**
360        * True if the type is a primitive type.
361        * @param type
362        * @return
363        */
364       public static boolean isPrimitive(final String type)
365       {
366           return PRIMITIVE_NAME_TYPE_MAP.containsKey(type);
367       }
368 
369       /**
370        * Return the class type name as string if the type is an array.
371        * @param type
372        * @return
373        */
374       static String getTypeName(Class type) {
375           if (type.isArray()) {
376 
377               Class cl = type;
378               int dimensions = 0;
379               while (cl.isArray()) {
380                   dimensions++;
381                   cl = cl.getComponentType();
382               }
383               StringBuffer sb = new StringBuffer();
384               sb.append(cl.getName());
385               for (int i = 0; i < dimensions; i++) {
386                   sb.append("[]");
387               }
388               return sb.toString();
389 
390           }
391           return type.getName();
392       }
393 
394 }