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  
14  import java.io.BufferedReader;
15  import java.io.FileNotFoundException;
16  import java.io.FileReader;
17  import java.io.IOException;
18  import java.util.ArrayList;
19  import java.util.List;
20  
21  import antlr.RecognitionException;
22  import antlr.TokenStreamException;
23  import antlr.collections.AST;
24  
25  import com.puppycrawl.tools.checkstyle.TreeWalker;
26  import com.puppycrawl.tools.checkstyle.api.DetailAST;
27  import com.puppycrawl.tools.checkstyle.api.FileContents;
28  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
29  
30  
31  /**
32   * This class provides some utility methods used to parse a java source file.
33   */
34  public class UtilJavaSourceParsing {
35  
36    /**
37     * Logger.
38     */
39    private static final Logger LOG
40      = LoggerFactory.getLogger(UtilJavaSourceParsing.class);
41    
42    /**
43     * Default constructor.
44     */
45    public UtilJavaSourceParsing () {
46    }
47    
48    /**
49     * This method extract the method's signature defined in the java source file.
50     *
51     * @param   absPath   The absolute path of the java source file.
52     *
53     * @return  The list of method's signature found.
54     *
55     * @throws  ClassGenerationException  The class generation exception
56     */
57    public List<MethodSignature> extractMethodSignature(String absPath, String fullQualifiedName)
58      throws ClassGenerationException {
59                          
60      List<String> listOfLines = null;
61      try {
62  
63        listOfLines = readFile(absPath);
64        
65      } catch (FileNotFoundException e) {
66  
67        Object[] args = new Object[] { absPath };
68        LOG.error("CRB000543_ExtractMethodSignatureError_FileNotFound", args, e);
69        throw new ClassGenerationException(
70          "CRB000543_ExtractMethodSignatureError_FileNotFound", args, e);
71  
72      } catch (IOException e) {
73  
74        Object[] args = new Object[] { absPath };
75        LOG.error("CRB000544_ExtractMethodSignatureError_IOException", args, e);
76        throw new ClassGenerationException(
77          "CRB000544_ExtractMethodSignatureError_IOException", args, e);
78      }
79      LOG.debug("Reading file ... done");
80  
81      String [] lines = listOfLines.toArray(new String[listOfLines.size()]);
82  
83      FileContents fc = new FileContents(absPath, lines);
84      DetailAST aRoot = null;
85      try {
86          aRoot = TreeWalker.parse(fc);
87  
88      } catch (RecognitionException e) {
89  
90        Object[] args = new Object[] { absPath };
91        LOG.error(
92          "CRB000545_ExtractMethodSignatureError_RecognitionException", args, e);
93        throw new ClassGenerationException(
94          "CRB000545_ExtractMethodSignatureError_RecognitionException", args, e);
95  
96      } catch (TokenStreamException e) {
97  
98        Object[] args = new Object[] { absPath };
99        LOG.error(
100         "CRB000546_ExtractMethodSignatureError_TokenStreamException", args, e);
101       throw new ClassGenerationException(
102         "CRB000546_ExtractMethodSignatureError_TokenStreamException", args, e);
103     }
104     LOG.debug("Parsing file ... done");
105 
106     List<DetailAST> nodeList = getTreeAsListOfNode(aRoot);
107 
108     List<MethodSignature> methodSignatureList
109       = extractMethodSignature(nodeList, fullQualifiedName);
110 
111     LOG.debug("Extractiong method's signature ... done");
112     return methodSignatureList;
113   }
114 
115   /**
116    * 
117    * @param nodeList  The node list
118    * @return          The return
119    */
120   private List<MethodSignature> extractMethodSignature(
121     List<DetailAST> nodeList, String fullQualifiedName) throws ClassGenerationException {
122 
123     List<MethodSignature> methodSignatureList
124       = new ArrayList<MethodSignature>();
125 
126     if (nodeList == null) {
127       LOG.debug("The list of node is null. nothing to do.");
128       return methodSignatureList;
129     }    
130 
131     // else
132 
133     for (DetailAST currentNode : nodeList) {
134 
135       if (currentNode != null
136             && currentNode.getType() == TokenTypes.METHOD_DEF) {
137 
138         String methodName = currentNode.getFirstChild().getNextSibling()
139                                        .getNextSibling().getText();
140         
141        
142         //String returnType = getTypeParameter(currentNode);
143         //*************************************************************
144         //Changed For Multimodule FIX
145         //Now The Return Type contain's also the package Information
146         String returnType =getParamFromNode(currentNode).getTypeName();
147         
148         
149         MethodSignature methodSignature = new MethodSignature();
150 
151         methodSignature.setClassName(fullQualifiedName);
152         methodSignature.setMethodName(methodName);
153         methodSignature.setReturnType(returnType);
154 
155         methodSignatureList.add(methodSignature);
156         LOG.debug("methodSignatureList.add:" + methodSignature);
157       }
158 
159       if (currentNode != null
160             && currentNode.getType() == TokenTypes.PARAMETER_DEF) {
161 
162         MethodSignature methodSignature
163           = methodSignatureList.get(methodSignatureList.size() - 1);
164                 
165         Param param = getParamFromNode(currentNode);
166         LOG.debug("CRB000571_Found_parameter", 
167         		new Object[]{param.getName(), param.getTypeName()});
168 
169         
170         // Adds the Holder Information
171         if (isHolderCorbaClass(param.getTypeName())) {
172             param.setHolder(true);
173             methodSignature.setContainsHolder(true);
174         }
175         methodSignature.getParameters().add(param);
176         LOG.debug("Found Param: "+param);
177         LOG.debug("CRB000572_methodSignature_update_Parameter_definition", 
178         		new Object[]{methodSignature, param.getName(), param.getTypeName()});
179       }
180 
181     }
182 
183     return methodSignatureList;
184   }
185 
186   /**
187    * Returns the tree (part of) as a List.
188    * @param aRoot  The aRoot
189    * @return       The return
190    */
191   private List<DetailAST> getTreeAsListOfNode(DetailAST aRoot) {
192 
193     List<DetailAST> nodeList = new ArrayList<DetailAST>();
194 
195     DetailAST curNode = aRoot;
196     while (curNode != null) {
197       DetailAST toVisit = (DetailAST) curNode.getFirstChild();
198       nodeList.add(toVisit);
199 
200       while ((curNode != null) && (toVisit == null)) {
201         toVisit = (DetailAST) curNode.getNextSibling();
202 
203         if (toVisit == null) {
204           curNode = curNode.getParent();
205         } else {
206           nodeList.add(toVisit);
207         }
208       }
209       curNode = toVisit;
210     }
211 
212     return nodeList;
213   }
214 
215 
216   /**
217    * This method is used to read a java sourse file.
218    *
219    * @param  filePath   The absolute path of the java source file.
220    *
221    * @return The file as a list of String. (a string for each text line).
222    *
223    * @throws IOException  The IO exception
224    */
225   private List<String> readFile(String filePath)
226     throws IOException {
227 
228     List<String> listOfLines = new ArrayList<String>();
229 
230     BufferedReader in = new BufferedReader(new FileReader(filePath));
231     String str = null;
232     while ((str = in.readLine()) != null) {
233         listOfLines.add(str);
234     }
235     in.close();
236 
237     return listOfLines;
238   }
239 
240   /**
241    * 
242    * @param tt  The tt
243    * @return    The return
244    */
245   private String tokenTypeToString(int tt) {
246     switch (tt) {
247     // 1. A
248     case TokenTypes.ABSTRACT:              return "ABSTRACT";
249     case TokenTypes.ANNOTATION:            return "ANNOTATION";
250     case TokenTypes.ANNOTATION_ARRAY_INIT: return "ANNOTATION_ARRAY_INIT";
251     case TokenTypes.ANNOTATION_DEF:        return "ANNOTATION_DEF";
252     case TokenTypes.ANNOTATION_FIELD_DEF:  return "ANNOTATION_FIELD_DEF";
253 
254     case TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR:
255       return "ANNOTATION_MEMBER_VALUE_PAIR";
256 
257     case TokenTypes.ANNOTATIONS:           return "ANNOTATIONS";
258     case TokenTypes.ARRAY_DECLARATOR:      return "ARRAY_DECLARATOR";
259     case TokenTypes.ARRAY_INIT:            return "ARRAY_INIT";
260     case TokenTypes.ASSIGN:                return "ASSIGN";
261     case TokenTypes.AT:                    return "AT";
262 
263     // 2. B
264     case TokenTypes.BAND:          return "BAND";
265     case TokenTypes.BAND_ASSIGN:   return "BAND_ASSIGN";
266     case TokenTypes.BNOT:          return "BNOT";
267     case TokenTypes.BOR:           return "BOR";
268     case TokenTypes.BOR_ASSIGN:    return "BOR_ASSIGN";
269     case TokenTypes.BSR:           return "BSR";
270     case TokenTypes.BSR_ASSIGN:    return "BSR_ASSIGN";
271     case TokenTypes.BXOR:          return "BXOR";
272     case TokenTypes.BXOR_ASSIGN:   return "BXOR_ASSIGN";
273 
274     // 3. C
275     case TokenTypes.CASE_GROUP:    return "CASE_GROUP";
276     case TokenTypes.CHAR_LITERAL:  return "CHAR_LITERAL";
277     case TokenTypes.CLASS_DEF:     return "CLASS_DEF";
278     case TokenTypes.COLON:         return "COLON";
279     case TokenTypes.COMMA:         return "COMMA";
280     case TokenTypes.CTOR_CALL:     return "CTOR_CALL";
281     case TokenTypes.CTOR_DEF:      return "CTOR_DEF";
282 
283     // 4. D
284     case TokenTypes.DEC:           return "DEC";
285     case TokenTypes.DIV:           return "DIV";
286     case TokenTypes.DIV_ASSIGN:    return "DIV_ASSIGN";
287     case TokenTypes.DO_WHILE:      return "DO_WHILE";
288     case TokenTypes.DOT:           return "DOT";
289 
290     // 5. E
291     case TokenTypes.ELIST:             return "ELIST";
292     case TokenTypes.ELLIPSIS:          return "ELLIPSIS";
293     case TokenTypes.EMPTY_STAT:        return "EMPTY_STAT";
294     case TokenTypes.ENUM:              return "ENUM";
295     case TokenTypes.ENUM_CONSTANT_DEF: return "ENUM_CONSTANT_DEF";
296     case TokenTypes.ENUM_DEF:          return "ENUM_DEF";
297     case TokenTypes.EOF:               return "EOF";
298     case TokenTypes.EQUAL:             return "EQUAL";
299     case TokenTypes.EXPR:              return "EXPR";
300     case TokenTypes.EXTENDS_CLAUSE:    return "EXTENDS_CLAUSE";
301 
302     // 6. F
303     case TokenTypes.FINAL:           return "FINAL";
304     case TokenTypes.FOR_CONDITION:   return "FOR_CONDITION";
305     case TokenTypes.FOR_EACH_CLAUSE: return "FOR_EACH_CLAUSE";
306     case TokenTypes.FOR_INIT:        return "FOR_INIT";
307     case TokenTypes.FOR_ITERATOR:    return "FOR_ITERATOR";
308 
309     // 7. G
310     case TokenTypes.GE:            return "GE";
311     case TokenTypes.GENERIC_END:   return "GENERIC_END";
312     case TokenTypes.GENERIC_START: return "GENERIC_START";
313     case TokenTypes.GT:            return "GT";
314 
315     // 8. H ...
316 
317     // 9. I
318     case TokenTypes.IDENT:             return "IDENT";
319     case TokenTypes.IMPLEMENTS_CLAUSE: return "IMPLEMENTS_CLAUSE";
320     case TokenTypes.IMPORT:            return "IMPORT";
321     case TokenTypes.INC:               return "INC";
322     case TokenTypes.INDEX_OP:          return "INDEX_OP";
323     case TokenTypes.INSTANCE_INIT:     return "INSTANCE_INIT";
324     case TokenTypes.INTERFACE_DEF:     return "INTERFACE_DEF";
325 
326     // 10. J ...
327     // 11. K ...
328 
329     // 12. L
330     case TokenTypes.LABELED_STAT: return "LABELED_STAT";
331     case TokenTypes.LAND:         return "LAND";
332     case TokenTypes.LCURLY:       return "LCURLY";
333     case TokenTypes.LE:           return "LE";
334     case TokenTypes.LNOT:         return "LNOT";
335     case TokenTypes.LPAREN:       return "LPAREN";
336     case TokenTypes.LT:           return "LT";
337 
338     // 13. M
339     case TokenTypes.METHOD_CALL:  return "METHOD_CALL";
340     case TokenTypes.METHOD_DEF:   return "METHOD_DEF";
341     case TokenTypes.MINUS:        return "MINUS";
342     case TokenTypes.MINUS_ASSIGN: return "MINUS_ASSIGN";
343     case TokenTypes.MOD:          return "MOD";
344     case TokenTypes.MOD_ASSIGN:   return "MOD_ASSIGN";
345     case TokenTypes.MODIFIERS:    return "MODIFIERS";
346 
347     // 14. N
348     case TokenTypes.NOT_EQUAL:  return "NOT_EQUAL";
349     case TokenTypes.NUM_DOUBLE: return "NUM_DOUBLE";
350     case TokenTypes.NUM_FLOAT:  return "NUM_FLOAT";
351     case TokenTypes.NUM_INT:    return "NUM_INT";
352     case TokenTypes.NUM_LONG:   return "NUM_LONG";
353 
354     // 15. O
355     case TokenTypes.OBJBLOCK: return "OBJBLOCK";
356 
357     // 16. P
358     case TokenTypes.PACKAGE_DEF:   return "PACKAGE_DEF";
359     case TokenTypes.PARAMETER_DEF: return "PARAMETER_DEF";
360     case TokenTypes.PARAMETERS:    return "PARAMETERS";
361     case TokenTypes.PLUS:          return "PLUS";
362     case TokenTypes.PLUS_ASSIGN:   return "PLUS_ASSIGN";
363     case TokenTypes.POST_DEC:      return "POST_DEC";
364     case TokenTypes.POST_INC:      return "POST_INC";
365 
366     // 17. Q
367     case TokenTypes.QUESTION: return "QUESTION";
368 
369     // 18. R
370     case TokenTypes.RBRACK: return "RBRACK";
371     case TokenTypes.RCURLY: return "RCURLY";
372     case TokenTypes.RPAREN: return "RPAREN";
373 
374     // 19. S
375     case TokenTypes.SEMI: return "SEMI";
376     case TokenTypes.SL: return "SL";
377     case TokenTypes.SL_ASSIGN: return "SL_ASSIGN";
378     case TokenTypes.SLIST: return "SLIST";
379     case TokenTypes.SR: return "SR";
380     case TokenTypes.SR_ASSIGN: return "SR_ASSIGN";
381     case TokenTypes.STAR: return "STAR";
382     case TokenTypes.STAR_ASSIGN: return "STAR_ASSIGN";
383     case TokenTypes.STATIC_IMPORT: return "STATIC_IMPORT";
384     case TokenTypes.STATIC_INIT: return "STATIC_INIT";
385     case TokenTypes.STRICTFP: return "STRICTFP";
386     case TokenTypes.STRING_LITERAL: return "STRING_LITERAL";
387     case TokenTypes.SUPER_CTOR_CALL: return "SUPER_CTOR_CALL";
388 
389     // 20. T
390     case TokenTypes.TYPE: return "TYPE";
391     case TokenTypes.TYPE_ARGUMENT: return "TYPE_ARGUMENT";
392     case TokenTypes.TYPE_ARGUMENTS: return "TYPE_ARGUMENTS";
393     case TokenTypes.TYPE_EXTENSION_AND: return "TYPE_EXTENSION_AND";
394     case TokenTypes.TYPE_LOWER_BOUNDS: return "TYPE_LOWER_BOUNDS";
395     case TokenTypes.TYPE_PARAMETER: return "TYPE_PARAMETER";
396     case TokenTypes.TYPE_PARAMETERS: return "TYPE_PARAMETERS";
397     case TokenTypes.TYPE_UPPER_BOUNDS: return "TYPE_UPPER_BOUNDS";
398     case TokenTypes.TYPECAST: return "TYPECAST";
399 
400     // 21. U
401     case TokenTypes.UNARY_MINUS: return "UNARY_MINUS";
402     case TokenTypes.UNARY_PLUS: return "UNARY_PLUS";
403 
404     // 22. V
405     case TokenTypes.VARIABLE_DEF: return "VARIABLE_DEF";
406 
407     // 23. W
408     case TokenTypes.WILDCARD_TYPE: return "SEMI";
409 
410     // 24. X ...
411     // 25. Y ...
412     // 26. Z ...
413     }
414 
415     // FIXME java keyworld
416 
417     return "TokenTypeUnknown";
418   }
419   
420   /**
421    * Return true if the class is a holder Type class.
422    * In the first implementation, the method check only if the type 
423    * ends with <code>Holder</code>.
424    * Note that there is no Holder interface or superclass.
425    * @param typeName
426    * @return
427    */
428   public static boolean isHolderCorbaClass(String typeName) {
429       boolean ret = false;
430       if (typeName != null) {
431           if (typeName.endsWith("Holder")) {
432               ret = true;
433           }
434       }
435    return ret;
436   }
437  
438   /**
439      * Gets the type string from the current node. Populate also the array
440      * informations (if it's an array and the array dimension).
441      * 
442      * @param currentNode the AST node
443      * 
444      * @return the parame populated with type nad name.
445      */
446   private Param getParamFromNode(DetailAST currentNode) {
447       // If the token is a "." (TokenTypes.DOT) the type is in the form "xx.dd.xxx".:  Lets collect the type.
448       String type = "";
449       int arrayDimension = 0; 
450       boolean isArray = false;
451       
452       // Gets the parameter name
453       String pName = currentNode.getFirstChild().getNextSibling()
454       .getNextSibling().getText();
455       
456       // Test if the parameter is an array
457       if (currentNode.getFirstChild().getNextSibling()
458       .getFirstChild().getType() == TokenTypes.ARRAY_DECLARATOR) {
459           isArray = true;
460       }
461       
462       if ((currentNode.getFirstChild().getNextSibling()
463           .getFirstChild().getType() == TokenTypes.DOT)  || (currentNode.getFirstChild().getNextSibling()
464               .getFirstChild().getType() == TokenTypes.ARRAY_DECLARATOR)) {
465    
466           // get name type of parameter
467           String typeParam = getTypeParameter(currentNode);
468           
469           AST typeNode = currentNode.getFirstChild().getNextSibling().getFirstChild();            
470           List<DetailAST> typeDetails = getTreeAsListOfNode((DetailAST)typeNode);
471           // Gets all the token, until the pName is found;   
472           boolean paramNotFound = true;
473           for (int i = 0; i < typeDetails.size() && paramNotFound; i++) {
474               DetailAST node = (DetailAST)typeDetails.get(i);
475               if (node != null) {       
476                   if (node.getText().equals(pName)) {
477                       // Parameter name found: break!
478                       paramNotFound = false;                                      
479                   } else if ((node.getType() != TokenTypes.DOT) && (node.getType() != TokenTypes.ARRAY_DECLARATOR) 
480                           && (node.getType() != TokenTypes.RBRACK)) {
481                       // Adds the type string, excludes all the "DOT"and "[" chars
482                       type = type + node.getText();     
483                       // Adds the dot if the  token is not the final class part
484                       if (i != typeDetails.size()) {   
485                           //LOG.debug("Adds the dot if the token is not the final class part");
486                           DetailAST nextNode = (DetailAST)node.getParent().getNextSibling();
487                           
488                           // For the types with package with a single DOT
489                           if (nextNode == null) {
490                               nextNode = (DetailAST)node.getNextSibling();
491                           }
492                            
493                           // Adds a "dot" if there is a parent token of type DOT 
494                           // and the node is a package. 
495                           if ((nextNode != null) && (node.getParent().getType() == TokenTypes.DOT)
496                                   && (!node.getText().equals(typeParam))) {
497                               type = type + ".";
498                               LOG.debug("Adds the dot");
499                           } 
500                            
501                       }
502                   } else if ((node.getType() == TokenTypes.RBRACK)) {
503                       // Arry declaration closed
504                       arrayDimension++;
505                   }
506               }                                                              
507           } 
508           
509       } else {
510           type = currentNode.getFirstChild().getNextSibling()
511           .getFirstChild().getText();              
512       }      
513       Param param = new Param();
514       param.setName(pName);
515       param.setTypeName(type);
516       param.setArray(isArray);
517       param.setArrayDimension(arrayDimension);
518       return param;
519   }
520   
521   /**
522    * Gets the type name of the parameter into currentNode.
523    * 
524    * @param currentNode
525    * @return type Parameter's Name
526    */
527   private String getTypeParameter(DetailAST currentNode){
528     
529     LOG.debug(">>>>> getTypeParameter - begin");
530        
531     String result ="";
532     DetailAST node = (DetailAST)currentNode.getFirstChild().getNextSibling()
533                                 .getFirstChild();
534 
535     // Explore Array...
536     while ((node.getType() == TokenTypes.ARRAY_DECLARATOR)){
537       LOG.debug("Explore Array...");
538       node = (DetailAST) node.getFirstChild();
539       
540     }
541     
542     // Explore package
543     if ((node.getType() == TokenTypes.DOT)){
544       LOG.debug("Explore package");
545       node = (DetailAST) node.getFirstChild().getNextSibling();
546     
547     }
548     
549     
550     
551     result = node.getText();
552     
553     LOG.debug("Parameter's Name: " + result);
554     LOG.debug(">>>>> getTypeParameter - end");
555     return result;
556   }
557 }