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.bcm;
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.webservice.generator.AnyType;
14 import it.imolinfo.jbi4corba.webservice.generator.InterfaceType;
15 import it.imolinfo.jbi4corba.webservice.generator.MethodSignature;
16 import it.imolinfo.jbi4corba.webservice.generator.Param;
17 import it.imolinfo.jbi4corba.webservice.generator.TypeUtils;
18 import it.imolinfo.jbi4corba.webservice.generator.UnionType;
19 import it.imolinfo.jbi4corba.webservice.generator.UnionTypeUtils;
20 import it.imolinfo.jbi4corba.webservice.generator.Util;
21
22 import java.util.ArrayList;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27
28 import org.objectweb.asm.AnnotationVisitor;
29 import org.objectweb.asm.ClassAdapter;
30 import org.objectweb.asm.ClassVisitor;
31 import org.objectweb.asm.ClassWriter;
32 import org.objectweb.asm.MethodVisitor;
33 import org.objectweb.asm.Type;
34
35 /**
36 * This class is used to add the annotations for the WebService.
37 * Also collect the exceptions classes name thrown by the operation methods.
38 *
39 * FIXME with method overloading the behavior is undefined.
40 */
41 public class WebServiceAnnotationAdapter extends ClassAdapter {
42
43 /**
44 * A JSR181 annotation internal class name.
45 * <pre>
46 * ==========================================================================
47 * member | mean | default
48 * ==========================================================================
49 * name | the name of the WS. | Simple name of the
50 * | Used as the name of | java class or
51 * | the wsdl:portType | interface.
52 * --------------------------------------------------------------------------
53 * targetNamespace | used for wsdl:portType | see JaxWs 2.0
54 * | or wsdl:service or both |
55 * --------------------------------------------------------------------------
56 * serviceName | wsdl:service (not allowed | simple name of the
57 * | on endpoint interface) | java class
58 * | | + Service
59 * --------------------------------------------------------------------------
60 * portName | wsdl:port (not allowed on | WS name + Port
61 * | endpoint interface) |
62 * --------------------------------------------------------------------------
63 * wsdlLocation | | none
64 * --------------------------------------------------------------------------
65 * endpointInterface | (not allowed on | none
66 * | endpoint interface) |
67 * ==========================================================================
68 * </pre>
69 */
70 public static final String JSR181_WEB_SERVICE = "Ljavax/jws/WebService;";
71 private static final String W3CEPR = Type.getDescriptor(javax.xml.ws.wsaddressing.W3CEndpointReference.class);
72 /**
73 * A JSR181 annotation internal class name.
74 * <pre>
75 * ==========================================================================
76 * member | mean | default
77 * ==========================================================================
78 * operationName | wsdl:operation name | name of the java
79 * | | method
80 * --------------------------------------------------------------------------
81 * action | the soap action | ""
82 * --------------------------------------------------------------------------
83 * exclude | a method not exposed (not allowed | false
84 * | on endpoint interface) |
85 * ==========================================================================
86 * </pre>
87 */
88 public static final String JSR181_WEB_METHOD = "Ljavax/jws/WebMethod;";
89 /**
90 * <pre>
91 * ==========================================================================
92 * member | mean | default
93 * ==========================================================================
94 * name | name of the parameter. | WebMethod.operation
95 * | | name if the
96 * | If RPC and WebParam.partName has | operation is
97 * | not been specified, this is the | DOCUMENT style and
98 * | name of the wsdl:part | the parameter style
99 * | | is BARE.
100 * | If DOCUMENT or the parameter maps |
101 * | to a header, this is the local | Otherwise:
102 * | name of the XML element | arg0,arg1,...
103 * | representing the parameter. |
104 * | |
105 * | A name MUST be specified if the |
106 * | operation is DOCUMENT style, the |
107 * | parameter style is BARE, and the |
108 * | mode is OUT or INOUT. |
109 * --------------------------------------------------------------------------
110 * partName | the wsdl:part name. | WebParam.name
111 * | Used only if the operation is RPC |
112 * | or the operation is DOCUMENT and |
113 * | parameter style is BARE |
114 * --------------------------------------------------------------------------
115 * mode | the direction of the parameter | INOUT if Holder
116 * | on endpoint interface) | type otherwise IN
117 * | | (see JaxWs 2.0)
118 * --------------------------------------------------------------------------
119 * header | If true the parameter is pulled | false
120 * | from a message header rather then |
121 * | the message body |
122 * ==========================================================================
123 * </pre>
124 */
125 public static final String JSR181_WEB_PARAM = "Ljavax/jws/WebParam;";
126 public static final String JSR181_WEB_PARAM_MODE = "Ljavax/jws/WebParam$Mode;";
127 public static final String JSR181_WEB_PARAM_MODE_INOUT = "INOUT";
128 public static final String JSR181_WEB_RESULT = "Ljavax/jws/WebResult;";
129 public static final String JAVAX_XML_WS_HOLDER_TYPE = "Ljavax/xml/ws/Holder;";
130 public static final String JAVAX_XML_WS_HOLDER_TYPE_CANONICAL_NAME = "javax.xml.ws.Holder";
131 public static final String JAVAX_XML_WS_HOLDER_TYPE_NO_SEMICOLON = "Ljavax/xml/ws/Holder";
132 public static final String JSR181_SOAP_BINDING = "Ljavax/jws/soap/SOAPBinding;";
133 public static final String JAXB_XML_SEE_ALSO_ANNOTATOIN = "Ljavax/xml/bind/annotation/XmlSeeAlso;";
134 public static final String JSR181_SOAP_BINDING_USE = "Ljavax/jws/soap/SOAPBinding$Use;";
135 public static final String JSR181_SOAP_BINDING_STYLE = "Ljavax/jws/soap/SOAPBinding$ParameterStyle;";
136 public static final String JSR181_LITERAL = "LITERAL";
137 public static final String JSR181_WRAPPED = "WRAPPED";
138 public static final String JSR181_BARE = "BARE";
139 private Map<String, UnionType> allUnionTypes;
140 private Map<String, InterfaceType> allInterfaceTypes;
141 private String workingDirClasses;
142 /* Exceptions list */
143 public Set<String> exceptionsThrown = new HashSet<String>();
144 /**
145 * Used to mark an asynchronous WebMethod.
146 */
147 public static final String JSR181_ONEWAY = "Ljavax/jws/Oneway;";
148 protected static Set<String> noAnnotatedMethods = new HashSet<String>();
149
150
151 static {
152 noAnnotatedMethods.add("<init>");
153 noAnnotatedMethods.add("hashCode");
154 noAnnotatedMethods.add("getClass");
155 noAnnotatedMethods.add("wait");
156 noAnnotatedMethods.add("equals");
157 noAnnotatedMethods.add("notify");
158 noAnnotatedMethods.add("notifyAll");
159 noAnnotatedMethods.add("toString");
160 }
161 /**
162 * Logger.
163 */
164 private static final Logger LOG = LoggerFactory.getLogger(WebServiceAnnotationAdapter.class);
165 /** The class writer for this bytecode manipulation. */
166 protected ClassWriter classWriter = null;
167 /** The list of method's signature. */
168 protected List<MethodSignature> methodSignatureList = null;
169 boolean areClassAnnotationsPresent = false;
170 /** The namespace */
171 protected String nameSpace = null;
172 /** The porttype wsdl name */
173 protected String portTypeName = null;
174 /** All types in idl */
175 protected Set<Class> allTypes = null;
176
177 /**
178 * Constructor.
179 *
180 * @param cv The class visitor.
181 * @param cw The class writer.
182 * @param aMethodSignatureList The list of method to manipulate.
183 * @param ns
184 * @param portTypeName if not null, the port type name
185 */
186 public WebServiceAnnotationAdapter(ClassVisitor cv, ClassWriter cw,
187 List<MethodSignature> aMethodSignatureList, String ns, String ptn, String workingDir, Map<String, UnionType> unionTypes, Map<String, InterfaceType> intfTypes, Set<Class> allTypesIDL) {
188
189 super(cv);
190
191 classWriter = cw;
192 methodSignatureList = aMethodSignatureList;
193 nameSpace = ns;
194 portTypeName = ptn;
195 allUnionTypes = unionTypes;
196 allInterfaceTypes = intfTypes;
197 workingDirClasses = workingDir;
198 allTypes = allTypesIDL;
199 }
200
201 /**
202 * Override.
203 * @param version The version
204 * @param access The access
205 * @param name The name
206 * @param signature The signature
207 * @param superName The super name
208 * @param interfaces The interfaces
209 */
210 @Override
211 public void visit(int version, int access, String name, String signature,
212 String superName, String[] interfaces) {
213
214 LOG.debug("CRB000605_WebServiceAnnotationAdapter_visit", new Object[]{version, access, name, signature, superName, interfaces});
215
216 super.visit(version, access, name, signature, superName, interfaces);
217
218 addAnnotation(name);
219
220 }
221
222 @Override
223 public void visitEnd() {
224
225 cv.visitEnd();
226 }
227
228 /**
229 * Adds the Webservice and SOAPBinding annotations
230 * @param name The service name
231 */
232 private void addAnnotation(String name) {
233 if (!areClassAnnotationsPresent) {
234
235 // Adds the WebService annotation
236 AnnotationVisitor av = cv.visitAnnotation(JSR181_WEB_SERVICE, true);
237
238 // If the port type is pspecified, uses it. Otherwise uses the java class name.
239 if (portTypeName != null) {
240 LOG.debug("Adding port type name:" + portTypeName);
241 av.visit("name", portTypeName);
242 } else {
243 String javaSimpleName = name.substring(name.lastIndexOf("/") + 1);
244 av.visit("name", javaSimpleName);
245 }
246 if (nameSpace != null) {
247 av.visit("targetNamespace", nameSpace);
248 LOG.debug("Adding targetNamespace:" + nameSpace);
249 }
250 if (av != null) {
251 av.visitEnd();
252 }
253
254 // Adds the SOAP annotation
255 AnnotationVisitor av2 = cv.visitAnnotation(JSR181_SOAP_BINDING, true);
256 av2.visitEnum("use", JSR181_SOAP_BINDING_USE, JSR181_LITERAL);
257 av2.visitEnum("parameterStyle",
258 JSR181_SOAP_BINDING_STYLE, JSR181_WRAPPED);
259
260
261 if (av2 != null) {
262 av2.visitEnd();
263 }
264
265 // Adds the XMLSeeAlso annotation
266 AnnotationVisitor av3 = cv.visitAnnotation(JAXB_XML_SEE_ALSO_ANNOTATOIN, true);
267 AnnotationVisitor xmlElems = av3.visitArray("value");
268
269 for (Class typeClass : allTypes) {
270 String className = typeClass.getName();
271 UnionType union = UnionTypeUtils.isUnionType(className, false, allUnionTypes);
272 if (union != null) {
273 try {
274 typeClass = Util.classLoad(workingDirClasses, union.getTypeName() + "Wrapper");
275 } catch (ClassGenerationException e) {
276 //class not found ignoring
277 LOG.debug("WebServiceAnnotationAdapter.addAnnotation: Class not found for union: " + union.getTypeName());
278 }
279 }
280
281 if (!Util.isThrowableSubClass(typeClass) && !typeClass.isInterface()) {
282
283 xmlElems.visit("value", Type.getType(typeClass));
284 //Raf: added to manage jbi4corba-7 issue from nokia. To be removed if typedef defined type management is added
285 //all idlj generated java primitive types are always added in the array version
286 /*if (!typeClass.isArray() && !typeClass.isAnonymousClass() && !typeClass.isPrimitive()) {
287 if (LOG.isDebugEnabled()){
288 LOG.debug("orginal class: " + typeClass);
289 LOG.debug("type descriptor: " + Type.getType(String.class).getDescriptor());
290 LOG.debug("typeArray descriptor: " + Type.getType(String[].class).getDescriptor());
291 LOG.debug("annotation for arrays: " + Type.getType("[" + Type.getType(typeClass).getDescriptor()));
292 }
293 //LOG.debug("annotation for arrays2: "+Type.getObjectType("["+typeClass.getCanonicalName()));
294 xmlElems.visit("value", Type.getType("[" + Type.getType(typeClass).getDescriptor()));
295 }*/
296 }
297 }
298
299 //Raf: added to manage jbi4corba-7 issue from nokia. To be removed if typedef defined type management is added
300 //all idlj generated java primitive types are always added in the array version
301 /*
302 xmlElems.visit("value", Type.getType(boolean[].class));
303 xmlElems.visit("value", Type.getType(char[].class));
304 xmlElems.visit("value", Type.getType(byte[].class));
305 xmlElems.visit("value", Type.getType(String[].class));*/
306
307 /*xmlElems.visit("value", Type.getType(short[].class));
308 xmlElems.visit("value", Type.getType(int[].class));
309 xmlElems.visit("value", Type.getType(long[].class));
310 xmlElems.visit("value", Type.getType(float[].class));
311 xmlElems.visit("value", Type.getType(double[].class));
312 xmlElems.visit("value", Type.getType(java.math.BigDecimal[].class));
313 */
314 //ISSUE 27
315 //xmlElems.visit("value", Type.getType(String[][].class));
316 if (xmlElems != null) {
317 xmlElems.visitEnd();
318 }
319 if (av3 != null) {
320 av3.visitEnd();
321 }
322
323 areClassAnnotationsPresent = true;
324 }
325 }
326
327 /**
328 * Override.
329 * @param access The access
330 * @param name The name
331 * @param desc The desc
332 * @param signature The signature
333 * @param exceptions The exceptions
334 * @return The return
335 */
336 @Override
337 public MethodVisitor visitMethod(int access, String name, String desc,
338 String signature, String[] exceptions) {
339
340 LOG.debug("WebServiceAnnotationAdapter.visitMethod. access=" + access + "; name=" + name + "; desc=" + desc + "; signature=" + signature + "; exceptions=" + exceptions);
341
342 if (exceptions != null) {
343 for (int i = 0; i < exceptions.length; i++) {
344 LOG.debug("Exception found: " + exceptions[i]);
345 exceptionsThrown.add(exceptions[i]);
346 }
347 }
348
349 if (noAnnotatedMethods.contains(name)) {
350 LOG.debug("NO WebService Annotations [methodName=" + name + "]");
351 return super.visitMethod(access, name, desc, signature, exceptions);
352 }
353
354 LOG.debug("WebService Annotations for [methodName=" + name + "]");
355
356 // Gets the method visitor
357 MethodSignature methodSignature = findFirstMethodSignature(name);
358
359 // Change the Holder parameter (if holder are present in the parameters.
360 //**********************************************************************
361 // INOUT
362
363 if (methodSignature.isContainsHolder()) {
364 SignatureDescription sd = changeHolderParameters(methodSignature, desc, signature);
365 desc = sd.getDescription();
366 signature = sd.getSignature();
367 }
368 //**********************************************************************
369
370
371 MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
372
373 addMethodSignatureAnnotation(mv, methodSignature, desc, signature);
374
375 return mv;
376
377 }
378
379 /**
380 * Add annotation: WebMethod, Oneway, WebResult, WebParam.
381 *
382 * @param methodVisitor The method visitor
383 * @param sig the Method Signature
384 * @param methodDescription the bytecode method description
385 */
386 protected void addMethodSignatureAnnotation(MethodVisitor methodVisitor,
387 MethodSignature methodSignature, String description, String signature) {
388
389 addAnnotationOperationName(methodVisitor, methodSignature.getMethodName());
390
391 // One-Way
392 if (methodSignature.isOneway()) {
393 LOG.debug("The method " + methodSignature.getMethodName() + " is marked 'oneway'.");
394 AnnotationVisitor avOneway = methodVisitor.visitAnnotation(JSR181_ONEWAY, true);
395 avOneway.visitEnd();
396 }
397
398 addAnnotationReturnName(methodVisitor, methodSignature.getReturnName());
399
400 addParameterAnnotation(methodVisitor, methodSignature);
401
402 }
403
404 /**
405 * This method is used to add the annotation to the method's parameters.
406 *
407 * @param methodVisitor The method visitor.
408 * If null the annotation is not added.
409 *
410 * @param sig The method's signature.
411 * If null the annotation is not added.
412 *
413 */
414 protected void addParameterAnnotation(MethodVisitor methodVisitor,
415 MethodSignature sig) {
416
417 // check
418 if (methodVisitor == null) {
419 LOG.debug("The method visitor is null. add no annotation");
420 return;
421 }
422
423 // check
424 if (sig == null) {
425 LOG.debug("The method's signature is null. add no annotation");
426 return;
427 }
428
429 // check
430 if (sig.getParameters() == null || sig.getParameters().size() == 0) {
431
432 LOG.debug("The list of parameter name is null or empty." + "add no annotation");
433 return;
434 }
435
436
437 LOG.debug("Adding parameter for the method: " + sig);
438 for (int pos = 0; pos < sig.getParameters().size(); pos++) {
439
440 String param = sig.getParameters().get(pos).getName();
441 String paramType = sig.getParameters().get(pos).getTypeName();
442
443 LOG.debug("Adding parameter name: " + param + " of type: " + paramType);
444
445 AnnotationVisitor av = methodVisitor.visitParameterAnnotation(pos, JSR181_WEB_PARAM, true);
446 av.visit("name", param);
447
448
449 //av.visit("header", true); // default = false
450
451 // If it's a Holder, adds the INOUT webparam mode
452 if (sig.getParameters().get(pos).isHolder()) {
453 av.visitEnum("mode", JSR181_WEB_PARAM_MODE, JSR181_WEB_PARAM_MODE_INOUT);
454 }
455
456 av.visitEnd();
457
458 LOG.debug("WebParam annotation for [parameterName=" + param + "; parameterPosition=" + pos + "]");
459 }
460
461
462 }
463
464 /**
465 * This method is used to add an annotation to customize the name of the
466 * return element.
467 *
468 * @param methodVisitor A method visitor.
469 * If null the annotation is not added.
470 *
471 * @param returnName The new name.
472 * If null or empty the annotation is not added.
473 */
474 protected void addAnnotationReturnName(MethodVisitor methodVisitor,
475 String returnName) {
476
477 // check
478 if (methodVisitor == null) {
479 LOG.debug("The method visitor is null. add no annotation");
480 return;
481 }
482
483 // check
484 if (returnName == null || "".equals(returnName)) {
485 LOG.debug("The return name is null or empty. add no annotation");
486 return;
487 }
488
489 // annotation
490 AnnotationVisitor av = methodVisitor.visitAnnotation(JSR181_WEB_RESULT, true);
491
492 av.visit("name", returnName);
493 av.visitEnd();
494
495 }
496
497 /**
498 * This method is used to add an annotation to customize the operation name.
499 *
500 * @param methodVisitor A method visitor.
501 * If null the annotation is not added.
502 *
503 * @param operationName The new operation name.
504 * If null or empty the annotation is not added.
505 *
506 */
507 protected void addAnnotationOperationName(MethodVisitor methodVisitor,
508 String operationName) {
509
510 // check
511 if (methodVisitor == null) {
512 LOG.debug("The method visitor is null. add no annotation");
513 return;
514 }
515
516 // check
517 if (operationName == null || "".equals(operationName)) {
518 LOG.debug("The operation name is null or empty. add no annotation");
519 return;
520 }
521
522 // annotation
523 AnnotationVisitor av = methodVisitor.visitAnnotation(JSR181_WEB_METHOD, true);
524
525 av.visit("operationName", operationName);
526 //avSig.visit("action", ""); // "" = default
527 av.visitEnd();
528 }
529
530 /**
531 * Find a method.
532 *
533 * @param methodName The finding key.
534 *
535 * @return The method signature of the first element with the name
536 * in input. If the name is null or if the elemente does not exist
537 * the method return null.
538 *
539 */
540 protected MethodSignature findFirstMethodSignature(String methodName) {
541 if (methodSignatureList == null) {
542 LOG.debug("Method's signature not found:" + "The list of the MethodSignature is null.");
543 return null;
544 }
545 // else
546 if (methodName == null) {
547 LOG.debug("Method's signature not found:" + "The method name is null.");
548 return null;
549 }
550 // else
551 for (MethodSignature sig : methodSignatureList) {
552 if (methodName.equals(sig.getMethodName())) {
553 LOG.debug("MethodSignature FOUND. MethodName=" + methodName + "; MethodSignature=" + sig);
554 return sig;
555 }
556 }
557 // else
558 LOG.debug("Method's signature not found for the method " + methodName);
559 return null;
560 }
561
562 public Set<String> getExceptionsThrown() {
563 return exceptionsThrown;
564 }
565
566 /**
567 * Changes the method description and signature to change the method interface.
568 * For example, the <br/>
569 * public String test(org.omg.CORBA.StringHolder arg, String nogeneric) <br/>
570 *
571 * Must be changed in: <br/>
572 *
573 * public String test(javax.xml.ws.Holder<String> arg, String nogeneric) <br/>
574 *
575 * To do so, the description must change in: <br/>
576 *
577 * (Ljavax/xml/ws/Holder;Ljava/lang/String;)Ljava/lang/String; <br/>
578 *
579 * And the Signature must be not null and: <br/>
580 *
581 * (Ljavax/xml/ws/Holder<Ljava/lang/String;>;Ljava/lang/String;)Ljava/lang/String; <br/>
582 *
583 *
584 * @param methodVisitor
585 * @param sig
586 * @param methodDescription
587 * @param methodSignature
588 */
589 protected SignatureDescription changeHolderParameters(MethodSignature sig, String methodDescription, String methodSignature) {
590
591 StringBuffer newMethodDescription = new StringBuffer("(");
592 StringBuffer newMethodSignature = new StringBuffer("(");
593 InternalMethodDescriptionParser parser = new InternalMethodDescriptionParser(methodDescription);
594 List<String> internalParams = parser.parse();
595
596 if (internalParams.size() != 0) {
597
598 List<String> newParams = new ArrayList<String>();
599
600
601 // Change the Holder Corba type to java.xml.ws.Holder
602 for (int i = 0; i < sig.getParameters().size(); i++) {
603
604 Param param = (Param) sig.getParameters().get(i);
605 if (param.isHolder()) {
606 // Gets the paramt holder value type and converts it in the internal bytecode form.
607 Class paramClass = param.getHolderValueType();
608 String paramTypeDescriptor = Type.getDescriptor(paramClass);
609 String holderValueTypeStr = TypeUtils.getTypeNameWithoutBrackets(paramClass);
610 UnionType union = allUnionTypes.get(holderValueTypeStr);
611 InterfaceType intf = allInterfaceTypes.get(holderValueTypeStr);
612
613 String arrayStr = TypeUtils.getArrayDimmentionAsPrefix(paramClass);
614 boolean isAny = TypeUtils.getTypeNameWithoutBrackets(paramClass).equals(AnyType.CORBA_ANY_TYPE);
615
616 if (isAny) {
617 paramTypeDescriptor = arrayStr + "Ljava/lang/Object;";
618 }
619
620 if (intf != null) {
621 paramTypeDescriptor = W3CEPR;
622 }
623
624 if (union != null) {
625 String wrapperType = null;
626 try {
627 wrapperType = UnionTypeUtils.createUnionClassWrapper(union, allUnionTypes, workingDirClasses);
628 paramTypeDescriptor = arrayStr + "L" + wrapperType + ";";
629 } catch (ClassGenerationException e) {
630 LOG.error("Error generating wrapper class for uniontype:" + holderValueTypeStr);
631 }
632 }
633
634 LOG.debug("The parameter:" + param.getName() + "/" + param.getTypeName() + " is an Holder of type:" + paramTypeDescriptor);
635
636 // Sets the param type as javax.xml.ws.Holder
637 newParams.add(JAVAX_XML_WS_HOLDER_TYPE);
638 String newHolderParamName = JAVAX_XML_WS_HOLDER_TYPE_NO_SEMICOLON + "<" + paramTypeDescriptor + ">;";
639
640 // Sets javax.xml.Holder<class> as parameter type name.
641 param.setTypeName(JAVAX_XML_WS_HOLDER_TYPE_CANONICAL_NAME + "<" + param.getHolderValueType().getCanonicalName() + ">");
642
643 // Adds the generic to the signature:
644 newMethodSignature.append(newHolderParamName);
645
646 } else {
647 // It's a "normal" (i mean no holder) parameter.
648 newParams.add(internalParams.get(i));
649 newMethodSignature.append(internalParams.get(i));
650 }
651 newMethodDescription.append(newParams.get(i));
652 }
653
654 newMethodDescription.append(")").append(parser.getMethodDescriptionTail());
655 newMethodSignature.append(")").append(parser.getMethodDescriptionTail());
656
657 // Reconstruct the correct method description
658 methodDescription = newMethodDescription.toString();
659 methodSignature = newMethodSignature.toString();
660 }
661
662 return new SignatureDescription(methodDescription, methodSignature);
663 }
664
665 /**
666 * Wrapper class for the description and signature of the analized methods
667 * @author marco
668 *
669 */
670 public class SignatureDescription {
671
672 // method description
673 private String description;
674
675 // method signature
676 private String signature;
677
678 public SignatureDescription(String desc, String sig) {
679 description = desc;
680 signature = sig;
681 }
682
683 public String getDescription() {
684 return description;
685 }
686
687 public String getSignature() {
688 return signature;
689 }
690 }
691 }