KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > description > JavaServiceDesc


1 /*
2  * Copyright 2002-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.axis.description;
17
18 import org.apache.axis.AxisServiceConfig;
19 import org.apache.axis.Constants;
20 import org.apache.axis.InternalException;
21 import org.apache.axis.AxisProperties;
22 import org.apache.axis.components.logger.LogFactory;
23 import org.apache.axis.encoding.*;
24 import org.apache.axis.constants.Style;
25 import org.apache.axis.constants.Use;
26 import org.apache.axis.message.SOAPBodyElement;
27 import org.apache.axis.message.SOAPEnvelope;
28 import org.apache.axis.utils.JavaUtils;
29 import org.apache.axis.utils.Messages;
30 import org.apache.axis.utils.bytecode.ParamNameExtractor;
31 import org.apache.axis.wsdl.Skeleton;
32 import org.apache.axis.wsdl.fromJava.Namespaces;
33 import org.apache.commons.logging.Log;
34 import org.w3c.dom.Document JavaDoc;
35 import org.w3c.dom.Element JavaDoc;
36
37 import javax.xml.namespace.QName JavaDoc;
38 import javax.xml.rpc.holders.Holder JavaDoc;
39 import java.lang.reflect.InvocationTargetException JavaDoc;
40 import java.lang.reflect.Method JavaDoc;
41 import java.lang.reflect.Modifier JavaDoc;
42 import java.util.ArrayList JavaDoc;
43 import java.util.Collection JavaDoc;
44 import java.util.Collections JavaDoc;
45 import java.util.Comparator JavaDoc;
46 import java.util.HashMap JavaDoc;
47 import java.util.Iterator JavaDoc;
48 import java.util.List JavaDoc;
49 import java.util.StringTokenizer JavaDoc;
50
51
52 /**
53  * A ServiceDesc is an abstract description of a service.
54  *
55  * ServiceDescs contain OperationDescs, which are descriptions of operations.
56  * The information about a service's operations comes from one of two places:
57  * 1) deployment, or 2) introspection.
58  *
59  * @author Glen Daniels (gdaniels@apache.org)
60  */

61 public class JavaServiceDesc implements ServiceDesc {
62     protected static Log log =
63             LogFactory.getLog(JavaServiceDesc.class.getName());
64
65     /** The name of this service */
66     private String JavaDoc name = null;
67
68     /** The documentation of this service */
69     private String JavaDoc documentation = null;
70
71     /** Style/Use */
72     private Style style = Style.RPC;
73     private Use use = Use.ENCODED;
74
75     // Style and Use are related. By default, if Style==RPC, Use should be
76
// ENCODED. But if Style==DOCUMENT, Use should be LITERAL. So we want
77
// to keep the defaults synced until someone explicitly sets the Use.
78
private boolean useSet = false;
79
80     /** Our operations - a list of OperationDescs */
81     private ArrayList JavaDoc operations = new ArrayList JavaDoc();
82
83     /** A collection of namespaces which will map to this service */
84     private List JavaDoc namespaceMappings = null;
85
86     /**
87      * Where does our WSDL document live? If this is non-null, the "?WSDL"
88      * generation will automatically return this file instead of dynamically
89      * creating a WSDL. BE CAREFUL because this means that Handlers will
90      * not be able to add to the WSDL for extensions/headers....
91      */

92     private String JavaDoc wsdlFileName = null;
93
94     /**
95      * An endpoint URL which someone has specified for this service. If
96      * this is set, WSDL generation will pick it up instead of defaulting
97      * to the transport URL.
98      */

99     private String JavaDoc endpointURL = null;
100
101     /** Place to store user-extensible service-related properties */
102     private HashMap JavaDoc properties = null;
103
104     /** Lookup caches */
105     private HashMap JavaDoc name2OperationsMap = null;
106     private HashMap JavaDoc qname2OperationsMap = null;
107     private transient HashMap JavaDoc method2OperationMap = new HashMap JavaDoc();
108     
109     // THE FOLLOWING STUFF IS ALL JAVA-SPECIFIC, AND WILL BE FACTORED INTO
110
// A JAVA-SPECIFIC SUBCLASS. --Glen
111

112     /** List of allowed methods */
113     /** null allows everything, an empty ArrayList allows nothing */
114     private List JavaDoc allowedMethods = null;
115
116     /** List if disallowed methods */
117     private List JavaDoc disallowedMethods = null;
118
119     /** Implementation class */
120     private Class JavaDoc implClass = null;
121
122     /**
123      * Is the implementation a Skeleton? If this is true, it will generate
124      * a Fault to provide OperationDescs via WSDD.
125      */

126     private boolean isSkeletonClass = false;
127
128     /** Cached copy of the skeleton "getOperationDescByName" method */
129     private transient Method JavaDoc skelMethod = null;
130
131     /** Classes at which we should stop looking up the inheritance chain
132      * when introspecting
133      */

134     private ArrayList JavaDoc stopClasses = null;
135
136     /** Lookup caches */
137     private transient HashMap JavaDoc method2ParamsMap = new HashMap JavaDoc();
138     private OperationDesc messageServiceDefaultOp = null;
139
140     /** Method names for which we have completed any introspection necessary */
141     private ArrayList JavaDoc completedNames = new ArrayList JavaDoc();
142
143     /** Our typemapping for resolving Java<->XML type issues */
144     private TypeMapping tm = null;
145     private TypeMappingRegistry tmr = null;
146
147     private boolean haveAllSkeletonMethods = false;
148     private boolean introspectionComplete = false;
149
150     /**
151      * Default constructor
152      */

153     public JavaServiceDesc() {
154     }
155
156     /**
157      * What kind of service is this?
158      * @return
159      */

160     public Style getStyle() {
161         return style;
162     }
163
164     public void setStyle(Style style) {
165         this.style = style;
166         if (!useSet) {
167             // Use hasn't been explicitly set, so track style
168
use = style == Style.RPC ? Use.ENCODED : Use.LITERAL;
169         }
170     }
171
172
173     /**
174      * What kind of use is this?
175      * @return
176      */

177     public Use getUse() {
178         return use;
179     }
180
181     public void setUse(Use use) {
182         useSet = true;
183         this.use = use;
184     }
185
186     /**
187      * Determine whether or not this is a "wrapped" invocation, i.e. whether
188      * the outermost XML element of the "main" body element represents a
189      * method call, with the immediate children of that element representing
190      * arguments to the method.
191      *
192      * @return true if this is wrapped (i.e. RPC or WRAPPED style),
193      * false otherwise
194      */

195     public boolean isWrapped()
196     {
197         return ((style == Style.RPC) ||
198                 (style == Style.WRAPPED));
199     }
200
201     /**
202      * the wsdl file of the service.
203      * When null, it means that the wsdl should be autogenerated
204      * @return filename or null
205      */

206     public String JavaDoc getWSDLFile() {
207         return wsdlFileName;
208     }
209
210     /**
211      * set the wsdl file of the service; this causes the named
212      * file to be returned on a ?wsdl, probe, not introspection
213      * generated wsdl.
214      * @param wsdlFileName filename or null to re-enable introspection
215      */

216     public void setWSDLFile(String JavaDoc wsdlFileName) {
217         this.wsdlFileName = wsdlFileName;
218     }
219
220     public List JavaDoc getAllowedMethods() {
221         return allowedMethods;
222     }
223
224     public void setAllowedMethods(List JavaDoc allowedMethods) {
225         this.allowedMethods = allowedMethods;
226     }
227
228     public Class JavaDoc getImplClass() {
229         return implClass;
230     }
231
232     /**
233      * set the implementation class
234      * <p>
235      * Warning: You cannot call getInitializedServiceDesc() after setting this
236      * as it uses this to indicate its work has already been done.
237      *
238      * @param implClass
239      * @throws IllegalArgumentException if the implementation class is already
240      * set
241      */

242     public void setImplClass(Class JavaDoc implClass) {
243         if (this.implClass != null)
244             throw new IllegalArgumentException JavaDoc(
245                     Messages.getMessage("implAlreadySet"));
246
247         this.implClass = implClass;
248         if (Skeleton.class.isAssignableFrom(implClass)) {
249             isSkeletonClass = true;
250             loadSkeletonOperations();
251         }
252     }
253
254     private void loadSkeletonOperations() {
255         Method JavaDoc method = null;
256         try {
257             method = implClass.getDeclaredMethod("getOperationDescs",
258                                                  new Class JavaDoc [] {});
259         } catch (NoSuchMethodException JavaDoc e) {
260         } catch (SecurityException JavaDoc e) {
261         }
262         if (method == null) {
263             // FIXME : Throw an error?
264
return;
265         }
266
267         try {
268             Collection JavaDoc opers = (Collection JavaDoc)method.invoke(implClass, null);
269             for (Iterator JavaDoc i = opers.iterator(); i.hasNext();) {
270                 OperationDesc skelDesc = (OperationDesc)i.next();
271                 addOperationDesc(skelDesc);
272             }
273         } catch (IllegalAccessException JavaDoc e) {
274             if(log.isDebugEnabled()) {
275                 log.debug(Messages.getMessage("exception00"), e);
276             }
277             return;
278         } catch (IllegalArgumentException JavaDoc e) {
279             if(log.isDebugEnabled()) {
280                 log.debug(Messages.getMessage("exception00"), e);
281             }
282             return;
283         } catch (InvocationTargetException JavaDoc e) {
284             if(log.isDebugEnabled()) {
285                 log.debug(Messages.getMessage("exception00"), e);
286             }
287             return;
288         }
289         haveAllSkeletonMethods = true;
290     }
291
292     public TypeMapping getTypeMapping() {
293         if(tm == null) {
294             return DefaultTypeMappingImpl.getSingletonDelegate();
295 // throw new RuntimeException(Messages.getMessage("noDefaultTypeMapping00"));
296
}
297         return tm;
298     }
299
300     public void setTypeMapping(TypeMapping tm) {
301         this.tm = tm;
302     }
303
304     /**
305      * the name of the service
306      */

307     public String JavaDoc getName() {
308         return name;
309     }
310
311     /**
312      * the name of the service
313      * @param name
314      */

315     public void setName(String JavaDoc name) {
316         this.name = name;
317     }
318
319     /**
320      * get the documentation for the service
321      */

322     public String JavaDoc getDocumentation() {
323         return documentation;
324     }
325
326     /**
327      * set the documentation for the service
328      */

329     public void setDocumentation(String JavaDoc documentation) {
330         this.documentation = documentation;
331     }
332
333     public ArrayList JavaDoc getStopClasses() {
334         return stopClasses;
335     }
336
337     public void setStopClasses(ArrayList JavaDoc stopClasses) {
338         this.stopClasses = stopClasses;
339     }
340
341     public List JavaDoc getDisallowedMethods() {
342         return disallowedMethods;
343     }
344
345     public void setDisallowedMethods(List JavaDoc disallowedMethods) {
346         this.disallowedMethods = disallowedMethods;
347     }
348
349     public void removeOperationDesc(OperationDesc operation) {
350         operations.remove(operation);
351         operation.setParent(null);
352
353         if (name2OperationsMap != null) {
354             String JavaDoc name = operation.getName();
355             ArrayList JavaDoc overloads = (ArrayList JavaDoc)name2OperationsMap.get(name);
356             if (overloads != null) {
357                 overloads.remove(operation);
358                 if (overloads.size() == 0) {
359                     name2OperationsMap.remove(name);
360                 }
361             }
362         }
363         
364         if (qname2OperationsMap != null) {
365             QName JavaDoc qname = operation.getElementQName();
366             ArrayList JavaDoc list = (ArrayList JavaDoc)qname2OperationsMap.get(qname);
367             if (list != null) {
368                 list.remove(operation);
369             }
370         }
371         
372         if (method2OperationMap != null) {
373             Method JavaDoc method = operation.getMethod();
374             if (method != null) {
375                 method2OperationMap.remove(method);
376             }
377         }
378     }
379     
380     public void addOperationDesc(OperationDesc operation)
381     {
382         operations.add(operation);
383         operation.setParent(this);
384         if (name2OperationsMap == null) {
385             name2OperationsMap = new HashMap JavaDoc();
386         }
387
388         // Add name to name2Operations Map
389
String JavaDoc name = operation.getName();
390         ArrayList JavaDoc overloads = (ArrayList JavaDoc)name2OperationsMap.get(name);
391         if (overloads == null) {
392             overloads = new ArrayList JavaDoc();
393             name2OperationsMap.put(name, overloads);
394         } else if (JavaUtils.isTrue(
395                 AxisProperties.getProperty(Constants.WSIBP11_COMPAT_PROPERTY)) &&
396                 overloads.size() > 0) {
397             throw new RuntimeException JavaDoc(Messages.getMessage("noOverloadedOperations", name));
398         }
399         overloads.add(operation);
400     }
401
402     /**
403      * get all the operations as a list of OperationDescs.
404      * this method triggers an evaluation of the valid operations by
405      * introspection, so use sparingly
406      * @return reference to the operations array. This is not a copy
407      */

408     public ArrayList JavaDoc getOperations()
409     {
410         loadServiceDescByIntrospection(); // Just in case...
411
return operations;
412     }
413
414     /**
415      * get all overloaded operations by name
416      * @param methodName
417      * @return null for no match, or an array of OperationDesc objects
418      */

419     public OperationDesc [] getOperationsByName(String JavaDoc methodName)
420     {
421         getSyncedOperationsForName(implClass, methodName);
422
423         if (name2OperationsMap == null)
424             return null;
425
426         ArrayList JavaDoc overloads = (ArrayList JavaDoc)name2OperationsMap.get(methodName);
427         if (overloads == null) {
428             return null;
429         }
430
431         OperationDesc [] array = new OperationDesc [overloads.size()];
432         return (OperationDesc[])overloads.toArray(array);
433     }
434
435     /**
436      * Return an operation matching the given method name. Note that if we
437      * have multiple overloads for this method, we will return the first one.
438      * @return null for no match
439      */

440     public OperationDesc getOperationByName(String JavaDoc methodName)
441     {
442         // If we need to load up operations from introspection data, do it.
443
// This returns fast if we don't need to do anything, so it's not very
444
// expensive.
445
getSyncedOperationsForName(implClass, methodName);
446
447         if (name2OperationsMap == null)
448             return null;
449
450         ArrayList JavaDoc overloads = (ArrayList JavaDoc)name2OperationsMap.get(methodName);
451         if (overloads == null) {
452             return null;
453         }
454
455         return (OperationDesc)overloads.get(0);
456     }
457
458     /**
459      * Map an XML QName to an operation. Returns the first one it finds
460      * in the case of mulitple matches.
461      * @return null for no match
462      */

463     public OperationDesc getOperationByElementQName(QName JavaDoc qname)
464     {
465         OperationDesc [] overloads = getOperationsByQName(qname);
466
467         // Return the first one....
468
if ((overloads != null) && overloads.length > 0)
469             return overloads[0];
470
471         return null;
472     }
473
474     /**
475      * Return all operations which match this QName (i.e. get all the
476      * overloads)
477      * @return null for no match
478      */

479     public OperationDesc [] getOperationsByQName(QName JavaDoc qname)
480     {
481         // Look in our mapping of QNames -> operations.
482

483         // But first, let's make sure we've initialized said mapping....
484
initQNameMap();
485
486         ArrayList JavaDoc overloads = (ArrayList JavaDoc)qname2OperationsMap.get(qname);
487         if (overloads == null) {
488             // Nothing specifically matching this QName.
489
if (name2OperationsMap != null) {
490                 if ((isWrapped() ||
491                      ((style == Style.MESSAGE) &&
492                       (getDefaultNamespace() == null)))) {
493                     // Try ignoring the namespace....?
494
overloads = (ArrayList JavaDoc) name2OperationsMap.get(qname.getLocalPart());
495                 } else {
496                     // TODO the above code is weird: a JavaServiceDesc can be document or rpc and
497
// still define a WSDL operation using a wrapper style mapping.
498
// The following code handles this case.
499
Object JavaDoc ops = name2OperationsMap.get(qname.getLocalPart());
500                     if (ops != null) {
501                         overloads = new ArrayList JavaDoc((Collection JavaDoc) ops);
502                         for (Iterator JavaDoc iter = overloads.iterator(); iter.hasNext();) {
503                             OperationDesc operationDesc = (OperationDesc) iter.next();
504                             if (Style.WRAPPED != operationDesc.getStyle()) {
505                                 iter.remove();
506                             }
507                         }
508                     }
509                 }
510             }
511             // Handle the case where a single Message-style operation wants
512
// to accept anything.
513
if ((style == Style.MESSAGE) && (messageServiceDefaultOp != null))
514                 return new OperationDesc [] { messageServiceDefaultOp };
515
516             if (overloads == null)
517                 return null;
518         }
519
520         getSyncedOperationsForName(implClass,
521                                    ((OperationDesc)overloads.get(0)).getName());
522
523         // Sort the overloads by number of arguments - prevents us calling methods
524
// with more parameters than supplied in the request (with missing parameters
525
// defaulted to null) when a perfectly good method exists with exactly the
526
// supplied parameters.
527
Collections.sort(overloads,
528             new Comparator JavaDoc() {
529                 public int compare(Object JavaDoc o1, Object JavaDoc o2)
530                 {
531                     Method JavaDoc meth1 = ((OperationDesc)o1).getMethod();
532                     Method JavaDoc meth2 = ((OperationDesc)o2).getMethod();
533                     return (meth1.getParameterTypes().length -
534                                          meth2.getParameterTypes().length);
535                 }
536             });
537
538         OperationDesc [] array = new OperationDesc [overloads.size()];
539         return (OperationDesc[])overloads.toArray(array);
540     }
541
542     private synchronized void initQNameMap() {
543         if (qname2OperationsMap == null) {
544             loadServiceDescByIntrospection();
545
546             qname2OperationsMap = new HashMap JavaDoc();
547             for (Iterator JavaDoc i = operations.iterator(); i.hasNext();) {
548                 OperationDesc operationDesc = (OperationDesc) i.next();
549                 QName JavaDoc qname = operationDesc.getElementQName();
550                 ArrayList JavaDoc list = (ArrayList JavaDoc)qname2OperationsMap.get(qname);
551                 if (list == null) {
552                     list = new ArrayList JavaDoc();
553                     qname2OperationsMap.put(qname, list);
554                 }
555                 list.add(operationDesc);
556             }
557         }
558     }
559
560     /**
561      * Synchronize an existing OperationDesc to a java.lang.Method.
562      *
563      * This method is used when the deployer has specified operation metadata
564      * and we want to match that up with a real java Method so that the
565      * Operation-level dispatch carries us all the way to the implementation.
566      * Search the declared methods on the implementation class to find one
567      * with an argument list which matches our parameter list.
568      */

569     private void syncOperationToClass(OperationDesc oper, Class JavaDoc implClass)
570     {
571         // ------------------------------------------------
572
// Developer Note:
573
//
574
// The goal of the sync code is to associate
575
// the OperationDesc/ParamterDesc with the
576
// target Method. There are a number of ways to get to this
577
// point depending on what information
578
// is available. Here are the main scenarios:
579
//
580
// A) Deployment with wsdd (non-skeleton):
581
// * OperationDesc/ParameterDesc loaded from deploy.wsdd
582
// * Loaded ParameterDesc does not have javaType,
583
// so it is discovered using the TypeMappingRegistry
584
// (also loaded via deploy.wsdd) and the
585
// typeQName specified by the ParameterDesc.
586
// * Sync occurs using the discovered
587
// javaTypes and the javaTypes of the Method
588
// parameters
589
//
590
// B) Deployment with no wsdd OperationDesc info (non-skeleton):
591
// * Implementation Class introspected to build
592
// OperationDesc/ParameterDesc.
593
// * ParameterDesc is known via introspection.
594
// * ParameterDesc are discovered using javaType
595
// and TypeMappingRegistry.
596
// * Sync occurs using the introspected
597
// javaTypes and the javaTypes of the Method
598
// parameters
599
//
600
// C) Deployment with wsdd (skeleton):
601
// * OperationDesc/ParameterDesc loaded from the Skeleton
602
// * In this scenario the ParameterDescs' already
603
// have javaTypes (see E below).
604
// * Sync occurs using the ParameterDesc
605
// javaTypes and the javaTypes of the Method
606
// parameters.
607
//
608
// D) Commandline Java2WSDL loading non-Skeleton Class/Interface
609
// * Class/Interface introspected to build
610
// OperationDesc/ParameterDesc.
611
// * The javaTypes of the ParameterDesc are set using introspection.
612
// * typeQNames are determined for built-in types using
613
// from the default TypeMappingRegistry. Other
614
// typeQNames are guessed from the javaType. Note
615
// that there is no loaded TypeMappingRegistry.
616
// * Sync occurs using the ParameterDesc
617
// javaTypes and the javaTypes of the Method
618
// parameters.
619
//
620
// E) Commandline Java2WSDL loading Skeleton Class
621
// * OperationDesc/ParameterDesc loaded from Skeleton
622
// * Each ParameterDesc has an appropriate typeQName
623
// * Each ParameterDesc also has a javaType, which is
624
// essential for sync'ing up with the
625
// method since there is no loaded TypeMappingRegistry.
626
// * Syncronization occurs using the ParameterDesc
627
// javaTypes and the javaTypes of the Method
628
// parameters.
629
//
630
// So in each scenario, the ultimate sync'ing occurs
631
// using the javaTypes of the ParameterDescs and the
632
// javaTypes of the Method parameters.
633
//
634
// ------------------------------------------------
635

636         // If we're already mapped to a Java method, no need to do anything.
637
if (oper.getMethod() != null)
638             return;
639
640         // Find the method. We do this once for each Operation.
641

642         Method JavaDoc[] methods = getMethods(implClass);
643         // A place to keep track of possible matches
644
Method JavaDoc possibleMatch = null;
645         
646         for (int i = 0; i < methods.length; i++) {
647             Method JavaDoc method = methods[i];
648             if (Modifier.isPublic(method.getModifiers()) &&
649                     method.getName().equals(oper.getName()) &&
650                     method2OperationMap.get(method) == null) {
651
652                 if (style == Style.MESSAGE) {
653                     int messageOperType = checkMessageMethod(method);
654                     if(messageOperType == OperationDesc.MSG_METHOD_NONCONFORMING) continue;
655                     if (messageOperType == -1) {
656                         throw new InternalException("Couldn't match method to any of the allowable message-style patterns!");
657                     }
658                     oper.setMessageOperationStyle(messageOperType);
659
660                     // Don't bother checking params if we're message style
661
possibleMatch = method;
662                     break;
663                 }
664
665                 // Check params
666
Class JavaDoc [] paramTypes = method.getParameterTypes();
667                 if (paramTypes.length != oper.getNumParams())
668                     continue;
669
670                 int j;
671                 boolean conversionNecessary = false;
672                 for (j = 0; j < paramTypes.length; j++) {
673                     Class JavaDoc type = paramTypes[j];
674                     Class JavaDoc actualType = type;
675                     if (Holder JavaDoc.class.isAssignableFrom(type)) {
676                         actualType = JavaUtils.getHolderValueType(type);
677                     }
678                     ParameterDesc param = oper.getParameter(j);
679                     QName JavaDoc typeQName = param.getTypeQName();
680                     if (typeQName == null) {
681                         // No typeQName is available. Set it using
682
// information from the actual type.
683
// (Scenarios B and D)
684
// There is no need to try and match with
685
// the Method parameter javaType because
686
// the ParameterDesc is being constructed
687
// by introspecting the Method.
688
typeQName = getTypeMapping().getTypeQName(actualType);
689                         param.setTypeQName(typeQName);
690                     } else {
691                         // A type qname is available.
692
// Ensure that the ParameterDesc javaType
693
// is convertable to the Method parameter type
694
//
695
// Use the available javaType (Scenarios C and E)
696
// or get one from the TMR (Scenario A).
697
Class JavaDoc paramClass = param.getJavaType();
698                         if (paramClass != null &&
699                             JavaUtils.getHolderValueType(paramClass) != null) {
700                             paramClass = JavaUtils.getHolderValueType(paramClass);
701                         }
702                         if (paramClass == null) {
703                             paramClass = getTypeMapping().getClassForQName(param.getTypeQName(),
704                                                                            type);
705                         }
706
707                         if (paramClass != null) {
708                             // This is a match if the paramClass is somehow
709
// convertable to the "real" parameter type. If not,
710
// break out of this loop.
711
if (!JavaUtils.isConvertable(paramClass, actualType)) {
712                                 break;
713                             }
714                             
715                             if (!actualType.isAssignableFrom(paramClass)) {
716                                 // This doesn't fit without conversion
717
conversionNecessary = true;
718                             }
719                         }
720                     }
721                     // In all scenarios the ParameterDesc javaType is set to
722
// match the javaType in the corresponding parameter.
723
// This is essential.
724
param.setJavaType(type);
725                 }
726
727                 if (j != paramTypes.length) {
728                     // failed.
729
continue;
730                 }
731                 
732                 // This is our latest possibility
733
possibleMatch = method;
734
735                 // If this is exactly it, stop now. Otherwise keep looking
736
// just in case we find a better match.
737
if (!conversionNecessary) {
738                     break;
739                 }
740
741             }
742         }
743
744         // At this point, we may or may not have a possible match.
745
// FIXME : Should we prefer an exact match from a base class over
746
// a with-conversion match from the target class? If so,
747
// we'll need to change the logic below.
748
if (possibleMatch != null) {
749             Class JavaDoc returnClass = possibleMatch.getReturnType();
750             oper.setReturnClass(returnClass);
751             
752             QName JavaDoc returnType = oper.getReturnType();
753             if (returnType == null) {
754                 oper.setReturnType(getTypeMapping().getTypeQName(returnClass));
755             }
756
757             // Do the faults
758
createFaultMetadata(possibleMatch, oper);
759                 
760             oper.setMethod(possibleMatch);
761             method2OperationMap.put(possibleMatch, oper);
762             return;
763         }
764
765         // Didn't find a match. Try the superclass, if appropriate
766
Class JavaDoc superClass = implClass.getSuperclass();
767         if (superClass != null &&
768                 !superClass.getName().startsWith("java.") &&
769                 !superClass.getName().startsWith("javax.") &&
770                 (stopClasses == null ||
771                           !stopClasses.contains(superClass.getName()))) {
772             syncOperationToClass(oper, superClass);
773         }
774
775         // Exception if sync fails to find method for operation
776
if (oper.getMethod() == null) {
777             InternalException ie =
778                 new InternalException(Messages.getMessage("serviceDescOperSync00",
779                                                            oper.getName(),
780                                                            implClass.getName()));
781             throw ie;
782         }
783     }
784
785     private Method JavaDoc[] getMethods(Class JavaDoc implClass) {
786         if (implClass.isInterface()){
787             // Returns all methods incl inherited
788
return implClass.getMethods();
789         } else {
790             return implClass.getDeclaredMethods();
791         }
792     }
793
794     private int checkMessageMethod(Method JavaDoc method) {
795         // Collect the types so we know what we're dealing with in the target
796
// method.
797
Class JavaDoc [] params = method.getParameterTypes();
798
799         if (params.length == 1) {
800             if ((params[0] == Element[].class) &&
801                     (method.getReturnType() == Element[].class)) {
802                 return OperationDesc.MSG_METHOD_ELEMENTARRAY;
803             }
804
805             if ((params[0] == SOAPBodyElement[].class) &&
806                     (method.getReturnType() == SOAPBodyElement[].class)) {
807                 return OperationDesc.MSG_METHOD_BODYARRAY;
808             }
809
810             if ((params[0] == Document JavaDoc.class) &&
811                     (method.getReturnType() == Document JavaDoc.class)) {
812                 return OperationDesc.MSG_METHOD_DOCUMENT;
813             }
814         } else if (params.length == 2) {
815             if (((params[0] == SOAPEnvelope.class) &&
816                     (params[1] == SOAPEnvelope.class)) ||
817                 ((params[0] == javax.xml.soap.SOAPEnvelope JavaDoc.class) &&
818                     (params[1] == javax.xml.soap.SOAPEnvelope JavaDoc.class)) &&
819                     (method.getReturnType() == void.class)){
820                 return OperationDesc.MSG_METHOD_SOAPENVELOPE;
821             }
822         }
823         if( null != allowedMethods && !allowedMethods.isEmpty() )
824           throw new InternalException (Messages.getMessage("badMsgMethodParams",
825                                                          method.getName()));
826         return OperationDesc.MSG_METHOD_NONCONFORMING;
827     }
828
829     /**
830      * Fill in a service description by introspecting the implementation
831      * class.
832      */

833     public void loadServiceDescByIntrospection()
834     {
835         loadServiceDescByIntrospection(implClass);
836
837         // Setting this to null means there is nothing more to do, and it
838
// avoids future string compares.
839
completedNames = null;
840     }
841
842     /**
843      * Fill in a service description by introspecting the implementation
844      * class.
845      */

846     public void loadServiceDescByIntrospection(Class JavaDoc implClass) {
847         if (introspectionComplete || implClass == null) {
848             return;
849         }
850
851         // set the implementation class for the service description
852
this.implClass = implClass;
853         if (Skeleton.class.isAssignableFrom(implClass)) {
854             isSkeletonClass = true;
855             loadSkeletonOperations();
856         }
857
858         /** If the class knows what it should be exporting,
859         * respect its wishes.
860         */

861         AxisServiceConfig axisConfig = null;
862         try {
863             Method JavaDoc method = implClass.getDeclaredMethod(
864                     "getAxisServiceConfig", new Class JavaDoc [] {});
865             if (method != null && Modifier.isStatic(method.getModifiers())) {
866                 axisConfig = (AxisServiceConfig)method.invoke(null, null);
867             }
868         } catch (Exception JavaDoc e) {
869             // No problem, just continue without...
870
}
871
872         if (axisConfig != null) {
873             String JavaDoc allowedMethodsStr = axisConfig.getAllowedMethods();
874             if (allowedMethodsStr != null && !"*".equals(allowedMethodsStr)) {
875                 ArrayList JavaDoc methodList = new ArrayList JavaDoc();
876                 StringTokenizer JavaDoc tokenizer =
877                         new StringTokenizer JavaDoc(allowedMethodsStr, " ,");
878                 while (tokenizer.hasMoreTokens()) {
879                     methodList.add(tokenizer.nextToken());
880                 }
881                 setAllowedMethods(methodList);
882             }
883         }
884
885         loadServiceDescByIntrospectionRecursive(implClass);
886
887         // All operations should now be synchronized. Check it.
888
for (Iterator JavaDoc iterator = operations.iterator(); iterator.hasNext();) {
889             OperationDesc operation = (OperationDesc) iterator.next();
890             if (operation.getMethod() == null) {
891                 throw new InternalException(
892                         Messages.getMessage("badWSDDOperation",
893                                             operation.getName(),
894                                             "" + operation.getNumParams()));
895             }
896         }
897
898         if ((style == Style.MESSAGE) && operations.size() == 1) {
899             messageServiceDefaultOp = (OperationDesc)operations.get(0);
900         }
901
902         introspectionComplete = true;
903     }
904
905     /**
906      * Is this method from ServiceLifeCycle interface?
907      * @param m
908      * @return true if this method is from ServiceLifeCycle interface
909      */

910     private boolean isServiceLifeCycleMethod(Class JavaDoc implClass, Method JavaDoc m) {
911         if(javax.xml.rpc.server.ServiceLifecycle JavaDoc.class.isAssignableFrom(implClass)) {
912             String JavaDoc methodName = m.getName();
913
914             if(methodName.equals("init")) {
915                 // Check if the method signature is
916
// "public abstract void init(Object context) throws ServiceException;"
917
Class JavaDoc[] classes = m.getParameterTypes();
918                 if(classes != null &&
919                    classes.length == 1 &&
920                    classes[0] == Object JavaDoc.class &&
921                    m.getReturnType() == Void.TYPE) {
922                     return true;
923                 }
924             } else if (methodName.equals("destroy")){
925                 // Check if the method signature is
926
// "public abstract void destroy();"
927
Class JavaDoc[] classes = m.getParameterTypes();
928                 if(classes != null &&
929                    classes.length == 0 &&
930                    m.getReturnType() == Void.TYPE) {
931                     return true;
932                 }
933             }
934         }
935         return false;
936     }
937     
938     /**
939      * Recursive helper class for loadServiceDescByIntrospection
940      */

941     private void loadServiceDescByIntrospectionRecursive(Class JavaDoc implClass)
942     {
943         if (Skeleton.class.equals(implClass)) {
944             return;
945         }
946
947         Method JavaDoc [] methods = getMethods(implClass);
948
949         for (int i = 0; i < methods.length; i++) {
950             if (Modifier.isPublic(methods[i].getModifiers()) && !isServiceLifeCycleMethod(implClass, methods[i])) {
951                 getSyncedOperationsForName(implClass, methods[i].getName());
952             }
953         }
954
955         if (implClass.isInterface()) {
956             Class JavaDoc [] superClasses = implClass.getInterfaces();
957             for (int i = 0; i < superClasses.length; i++) {
958                 Class JavaDoc superClass = superClasses[i];
959                 if (!superClass.getName().startsWith("java.") &&
960                         !superClass.getName().startsWith("javax.") &&
961                         (stopClasses == null ||
962                         !stopClasses.contains(superClass.getName()))) {
963                     loadServiceDescByIntrospectionRecursive(superClass);
964                 }
965             }
966         } else {
967             Class JavaDoc superClass = implClass.getSuperclass();
968             if (superClass != null &&
969                     !superClass.getName().startsWith("java.") &&
970                     !superClass.getName().startsWith("javax.") &&
971                     (stopClasses == null ||
972                         !stopClasses.contains(superClass.getName()))) {
973                 loadServiceDescByIntrospectionRecursive(superClass);
974             }
975         }
976     }
977
978     /**
979      * Fill in a service description by introspecting the implementation
980      * class. This version takes the implementation class and the in-scope
981      * TypeMapping.
982      */

983     public void loadServiceDescByIntrospection(Class JavaDoc cls, TypeMapping tm)
984     {
985         // Should we complain if the implClass changes???
986
implClass = cls;
987         this.tm = tm;
988
989         if (Skeleton.class.isAssignableFrom(implClass)) {
990             isSkeletonClass = true;
991             loadSkeletonOperations();
992         }
993
994         loadServiceDescByIntrospection();
995     }
996
997     /**
998      * Makes sure we have completely synchronized OperationDescs with
999      * the implementation class.
1000     */

1001    private void getSyncedOperationsForName(Class JavaDoc implClass, String JavaDoc methodName)
1002    {
1003        // If we're a Skeleton deployment, skip the statics.
1004
if (isSkeletonClass) {
1005            if (methodName.equals("getOperationDescByName") ||
1006                methodName.equals("getOperationDescs"))
1007                return;
1008        }
1009        
1010        // If we have no implementation class, don't worry about it (we're
1011
// probably on the client)
1012
if (implClass == null)
1013            return;
1014
1015        // If we're done introspecting, or have completed this method, return
1016
if (completedNames == null || completedNames.contains(methodName))
1017            return;
1018
1019        // Skip it if it's not a sanctioned method name
1020
if ((allowedMethods != null) &&
1021            !allowedMethods.contains(methodName))
1022            return;
1023
1024        if ((disallowedMethods != null) &&
1025            disallowedMethods.contains(methodName))
1026            return;
1027
1028        // If we're a skeleton class, make sure we don't already have any
1029
// OperationDescs for this name (as that might cause conflicts),
1030
// then load them up from the Skeleton class.
1031
if (isSkeletonClass && !haveAllSkeletonMethods) {
1032            // FIXME : Check for existing ones and fault if found
1033

1034            if (skelMethod == null) {
1035                // Grab metadata from the Skeleton for parameter info
1036
try {
1037                    skelMethod = implClass.getDeclaredMethod(
1038                                            "getOperationDescByName",
1039                                            new Class JavaDoc [] { String JavaDoc.class });
1040                } catch (NoSuchMethodException JavaDoc e) {
1041                } catch (SecurityException JavaDoc e) {
1042                }
1043                if (skelMethod == null) {
1044                    // FIXME : Throw an error?
1045
return;
1046                }
1047            }
1048            try {
1049                List JavaDoc skelList =
1050                        (List JavaDoc)skelMethod.invoke(implClass,
1051                                new Object JavaDoc [] { methodName });
1052                if (skelList != null) {
1053                    Iterator JavaDoc i = skelList.iterator();
1054                    while (i.hasNext()) {
1055                        addOperationDesc((OperationDesc)i.next());
1056                    }
1057                }
1058            } catch (IllegalAccessException JavaDoc e) {
1059                if(log.isDebugEnabled()) {
1060                    log.debug(Messages.getMessage("exception00"), e);
1061                }
1062                return;
1063            } catch (IllegalArgumentException JavaDoc e) {
1064                if(log.isDebugEnabled()) {
1065                    log.debug(Messages.getMessage("exception00"), e);
1066                }
1067                return;
1068            } catch (InvocationTargetException JavaDoc e) {
1069                if(log.isDebugEnabled()) {
1070                    log.debug(Messages.getMessage("exception00"), e);
1071                }
1072                return;
1073            }
1074        }
1075
1076        // OK, go find any current OperationDescs for this method name and
1077
// make sure they're synced with the actual class.
1078
if (name2OperationsMap != null) {
1079            ArrayList JavaDoc currentOverloads =
1080                    (ArrayList JavaDoc)name2OperationsMap.get(methodName);
1081            if (currentOverloads != null) {
1082                // For each one, sync it to the implementation class' methods
1083
for (Iterator JavaDoc i = currentOverloads.iterator(); i.hasNext();) {
1084                    OperationDesc oper = (OperationDesc) i.next();
1085                    if (oper.getMethod() == null) {
1086                        syncOperationToClass(oper, implClass);
1087                    }
1088                }
1089            }
1090        }
1091
1092        // Now all OperationDescs from deployment data have been completely
1093
// filled in. So we now make new OperationDescs for any method
1094
// overloads which were not covered above.
1095
// NOTE : This is the "lenient" approach, which allows you to
1096
// specify one overload and still get the others by introspection.
1097
// We could equally well return above if we found OperationDescs,
1098
// and have a rule that if you specify any overloads, you must specify
1099
// all the ones you want accessible.
1100

1101        createOperationsForName(implClass, methodName);
1102
1103        // Note that we never have to look at this method name again.
1104
completedNames.add(methodName);
1105    }
1106
1107    private String JavaDoc getUniqueOperationName(String JavaDoc name) {
1108        int i = 1;
1109        String JavaDoc candidate;
1110        do {
1111            candidate = name + i++;
1112        } while (name2OperationsMap.get(candidate) != null);
1113
1114        return candidate;
1115    }
1116
1117    /**
1118     * Look for methods matching this name, and for each one, create an
1119     * OperationDesc (if it's not already in our list).
1120     *
1121     * TODO: Make this more efficient
1122     */

1123    private void createOperationsForName(Class JavaDoc implClass, String JavaDoc methodName)
1124    {
1125        // If we're a Skeleton deployment, skip the statics.
1126
if (isSkeletonClass) {
1127            if (methodName.equals("getOperationDescByName") ||
1128                methodName.equals("getOperationDescs"))
1129                return;
1130        }
1131        
1132        Method JavaDoc [] methods = getMethods(implClass);
1133
1134        for (int i = 0; i < methods.length; i++) {
1135            Method JavaDoc method = methods[i];
1136            if (Modifier.isPublic(method.getModifiers()) &&
1137                method.getName().equals(methodName) &&
1138                !isServiceLifeCycleMethod(implClass, method)) {
1139                createOperationForMethod(method);
1140            }
1141        }
1142
1143        Class JavaDoc superClass = implClass.getSuperclass();
1144        if (superClass != null &&
1145                !superClass.getName().startsWith("java.") &&
1146                !superClass.getName().startsWith("javax.") &&
1147                    (stopClasses == null ||
1148                        !stopClasses.contains(superClass.getName()))) {
1149            createOperationsForName(superClass, methodName);
1150        }
1151    }
1152
1153    /**
1154     * Make an OperationDesc from a Java method.
1155     *
1156     * In the absence of deployment metadata, this code will introspect a
1157     * Method and create an appropriate OperationDesc. If the class
1158     * implements the Skeleton interface, we will use the metadata from there
1159     * in constructing the OperationDesc. If not, we use parameter names
1160     * from the bytecode debugging info if available, or "in0", "in1", etc.
1161     * if not.
1162     */

1163    private void createOperationForMethod(Method JavaDoc method) {
1164        // If we've already got it, never mind
1165
if (method2OperationMap.get(method) != null) {
1166            return;
1167        }
1168
1169        Class JavaDoc [] paramTypes = method.getParameterTypes();
1170
1171        // And if we've already got an exact match (i.e. an override),
1172
// never mind
1173

1174        ArrayList JavaDoc overloads = name2OperationsMap == null ? null :
1175                (ArrayList JavaDoc)name2OperationsMap.get(method.getName());
1176        if (overloads != null && !overloads.isEmpty()) {
1177            // Search each OperationDesc that already has a Method
1178
// associated with it, and check for parameter type equivalence.
1179
for (int i = 0; i < overloads.size(); i++) {
1180                OperationDesc op = (OperationDesc)overloads.get(i);
1181                Method JavaDoc checkMethod = op.getMethod();
1182                if (checkMethod != null) {
1183                    Class JavaDoc [] others = checkMethod.getParameterTypes();
1184                    if (paramTypes.length == others.length) {
1185                        int j = 0;
1186                        for (; j < others.length; j++) {
1187                            if (!others[j].equals(paramTypes[j]))
1188                                break;
1189                        }
1190                        // If we got all the way through, we have a match.
1191
if (j == others.length)
1192                            return;
1193                    }
1194                }
1195            }
1196        }
1197
1198        boolean isWSICompliant = JavaUtils.isTrue(
1199                AxisProperties.getProperty(Constants.WSIBP11_COMPAT_PROPERTY));
1200        
1201        // Make an OperationDesc, fill in common stuff
1202
OperationDesc operation = new OperationDesc();
1203        
1204        // If we're WS-I compliant, we can't have overloaded operation names.
1205
// If we find duplicates, we generate unique names for them and map
1206
// those names to the correct Method.
1207
String JavaDoc name = method.getName();
1208        if (isWSICompliant && name2OperationsMap != null) {
1209            Collection JavaDoc methodNames = name2OperationsMap.keySet();
1210            name = JavaUtils.getUniqueValue(methodNames, name);
1211        }
1212        operation.setName(name);
1213        String JavaDoc defaultNS = "";
1214        if (namespaceMappings != null && !namespaceMappings.isEmpty()) {
1215            // If we have a default namespace mapping, require callers to
1216
// use that namespace.
1217
defaultNS = (String JavaDoc)namespaceMappings.get(0);
1218        }
1219        if(defaultNS.length() == 0) {
1220            defaultNS = Namespaces.makeNamespace(method.getDeclaringClass().getName());
1221        }
1222        operation.setElementQName(new QName JavaDoc(defaultNS, name));
1223        operation.setMethod(method);
1224
1225        // If this is a MESSAGE style service, set up the OperationDesc
1226
// appropriately.
1227
if (style == Style.MESSAGE) {
1228            int messageOperType = checkMessageMethod(method);
1229            if(messageOperType == OperationDesc.MSG_METHOD_NONCONFORMING) return;
1230            if (messageOperType == -1) {
1231                throw new InternalException("Couldn't match method to any of the allowable message-style patterns!");
1232            }
1233            operation.setMessageOperationStyle(messageOperType);
1234            operation.setReturnClass(Object JavaDoc.class);
1235            operation.setReturnType(Constants.XSD_ANYTYPE);
1236        } else {
1237            // For other styles, continue here.
1238
Class JavaDoc retClass = method.getReturnType();
1239            operation.setReturnClass(retClass);
1240            QName JavaDoc typeQName = getTypeQName(retClass);
1241            operation.setReturnType(typeQName);
1242
1243            String JavaDoc [] paramNames = getParamNames(method);
1244
1245            for (int k = 0; k < paramTypes.length; k++) {
1246                Class JavaDoc type = paramTypes[k];
1247                ParameterDesc paramDesc = new ParameterDesc();
1248                // param should be unqualified if we're using rpc style,
1249
// or should use the operation's namespace if its document style
1250
String JavaDoc paramNamespace = (this.style == Style.RPC ? "" : operation.getElementQName().getNamespaceURI());
1251
1252                // If we have a name for this param, use it, otherwise call
1253
// it "in*"
1254
if (paramNames != null && paramNames[k] != null &&
1255                        paramNames[k].length()>0) {
1256                    paramDesc.setQName(new QName JavaDoc(paramNamespace, paramNames[k]));
1257                } else {
1258                    paramDesc.setQName(new QName JavaDoc(paramNamespace, "in" + k));
1259                }
1260
1261                // If it's a Holder, mark it INOUT, and set the XML type QName
1262
// to the held type. Otherwise it's IN.
1263

1264                Class JavaDoc heldClass = JavaUtils.getHolderValueType(type);
1265                if (heldClass != null) {
1266                    paramDesc.setMode(ParameterDesc.INOUT);
1267                    paramDesc.setTypeQName(getTypeQName(heldClass));
1268                } else {
1269                    paramDesc.setMode(ParameterDesc.IN);
1270                    paramDesc.setTypeQName(getTypeQName(type));
1271                }
1272                paramDesc.setJavaType(type);
1273                operation.addParameter(paramDesc);
1274            }
1275        }
1276
1277        createFaultMetadata(method, operation);
1278
1279        addOperationDesc(operation);
1280        method2OperationMap.put(method, operation);
1281    }
1282
1283    private QName JavaDoc getTypeQName(Class JavaDoc javaClass) {
1284        QName JavaDoc typeQName;
1285        TypeMapping tm = getTypeMapping();
1286        if (style == Style.RPC) {
1287            typeQName = tm.getTypeQName(javaClass);
1288        } else {
1289            typeQName = tm.getTypeQNameExact(javaClass);
1290            if (typeQName == null && javaClass.isArray()) {
1291                typeQName = tm.getTypeQName(javaClass.getComponentType());
1292            } else {
1293                typeQName = tm.getTypeQName(javaClass);
1294            }
1295        }
1296        return typeQName;
1297    }
1298
1299    private void createFaultMetadata(Method JavaDoc method, OperationDesc operation) {
1300        // Create Exception Types
1301
Class JavaDoc[] exceptionTypes = method.getExceptionTypes();
1302
1303        for (int i=0; i < exceptionTypes.length; i++) {
1304            // Every remote method declares a java.rmi.RemoteException
1305
// Only interested in application specific exceptions.
1306
// Ignore java and javax package exceptions.
1307
Class JavaDoc ex = exceptionTypes[i];
1308            if (ex != java.rmi.RemoteException JavaDoc.class &&
1309                ex != org.apache.axis.AxisFault.class &&
1310                !ex.getName().startsWith("java.") &&
1311                !ex.getName().startsWith("javax.")) {
1312
1313                // For JSR 101 v.1.0, there is a simple fault mapping
1314
// and a complexType fault mapping...both mappings
1315
// generate a class that extends (directly or indirectly)
1316
// Exception.
1317
// When converting java back to wsdl it is not possible
1318
// to determine which way to do the mapping,
1319
// so it is always mapped back using the complexType
1320
// fault mapping because it is more useful (i.e. it
1321
// establishes a hierarchy of exceptions). Note that this
1322
// will not cause any roundtripping problems.
1323
// Rich
1324

1325
1326                /* Old Simple Type Mode
1327                Field[] f = ex.getDeclaredFields();
1328                ArrayList exceptionParams = new ArrayList();
1329                for (int j = 0; j < f.length; j++) {
1330                    int mod = f[j].getModifiers();
1331                    if (Modifier.isPublic(mod) &&
1332                         !Modifier.isStatic(mod)) {
1333                        QName qname = new QName("", f[j].getName());
1334                        QName typeQName = tm.getTypeQName(f[j].getType());
1335                        ParameterDesc param = new ParameterDesc(qname,
1336                                                                ParameterDesc.IN,
1337                                                                typeQName);
1338                        param.setJavaType(f[j].getType());
1339                        exceptionParams.add(param);
1340                    }
1341                }
1342                String pkgAndClsName = ex.getName();
1343                FaultDesc fault = new FaultDesc();
1344                fault.setName(pkgAndClsName);
1345                fault.setParameters(exceptionParams);
1346                operation.addFault(fault);
1347                */

1348
1349                FaultDesc fault = operation.getFaultByClass(ex, false);
1350                boolean isNew;
1351                
1352                // If we didn't find one, create a new one
1353
if (fault == null) {
1354                    fault = new FaultDesc();
1355                    isNew = true;
1356                } else {
1357                    isNew = false;
1358                }
1359                
1360                // Try to fil in any parts of the faultDesc that aren't there
1361

1362                // XMLType
1363
QName JavaDoc xmlType = fault.getXmlType();
1364                if (xmlType == null) {
1365                    fault.setXmlType(getTypeMapping().getTypeQName(ex));
1366                }
1367                
1368                // Name and Class Name
1369
String JavaDoc pkgAndClsName = ex.getName();
1370                if (fault.getClassName() == null) {
1371                    fault.setClassName(pkgAndClsName);
1372                }
1373                if (fault.getName() == null) {
1374                    String JavaDoc name = pkgAndClsName.substring(
1375                            pkgAndClsName.lastIndexOf('.') + 1,
1376                            pkgAndClsName.length());
1377                    fault.setName(name);
1378                }
1379                
1380                // Parameters
1381
// We add a single parameter which points to the type
1382
if (fault.getParameters() == null) {
1383                    if (xmlType == null) {
1384                        xmlType = getTypeMapping().getTypeQName(ex);
1385                    }
1386                    QName JavaDoc qname = fault.getQName();
1387                    if (qname == null) {
1388                        qname = new QName JavaDoc("", "fault");
1389                    }
1390                    ParameterDesc param = new ParameterDesc(
1391                            qname,
1392                            ParameterDesc.IN,
1393                            xmlType);
1394                    param.setJavaType(ex);
1395                    ArrayList JavaDoc exceptionParams = new ArrayList JavaDoc();
1396                    exceptionParams.add(param);
1397                    fault.setParameters(exceptionParams);
1398                }
1399                
1400                // QName
1401
if (fault.getQName() == null) {
1402                    fault.setQName(new QName JavaDoc(pkgAndClsName));
1403                }
1404
1405                if (isNew) {
1406                    // Add the fault to the operation
1407
operation.addFault(fault);
1408                }
1409            }
1410        }
1411    }
1412
1413    private String JavaDoc[] getParamNames(Method JavaDoc method) {
1414        synchronized (method2ParamsMap) {
1415            String JavaDoc [] paramNames = (String JavaDoc []) method2ParamsMap.get(method);
1416            if(paramNames != null)
1417                return paramNames;
1418            paramNames = ParamNameExtractor.getParameterNamesFromDebugInfo(method);
1419            method2ParamsMap.put(method, paramNames);
1420            return paramNames;
1421        }
1422    }
1423
1424    public void setNamespaceMappings(List JavaDoc namespaces) {
1425        namespaceMappings = namespaces;
1426    }
1427
1428    public String JavaDoc getDefaultNamespace() {
1429        if (namespaceMappings == null || namespaceMappings.isEmpty())
1430            return null;
1431        return (String JavaDoc)namespaceMappings.get(0);
1432    }
1433
1434    public void setDefaultNamespace(String JavaDoc namespace) {
1435        if (namespaceMappings == null)
1436            namespaceMappings = new ArrayList JavaDoc();
1437        namespaceMappings.add(0, namespace);
1438    }
1439
1440    public void setProperty(String JavaDoc name, Object JavaDoc value) {
1441        if (properties == null) {
1442            properties = new HashMap JavaDoc();
1443        }
1444        properties.put(name, value);
1445    }
1446
1447    public Object JavaDoc getProperty(String JavaDoc name) {
1448        if (properties == null)
1449            return null;
1450
1451        return properties.get(name);
1452    }
1453
1454    public String JavaDoc getEndpointURL() {
1455        return endpointURL;
1456    }
1457
1458    public void setEndpointURL(String JavaDoc endpointURL) {
1459        this.endpointURL = endpointURL;
1460    }
1461
1462    public TypeMappingRegistry getTypeMappingRegistry() {
1463        if (tmr == null) {
1464            tmr = new TypeMappingRegistryImpl(false);
1465        }
1466        return tmr;
1467    }
1468
1469    public void setTypeMappingRegistry(TypeMappingRegistry tmr) {
1470        this.tmr = tmr;
1471    }
1472
1473    public boolean isInitialized() {
1474        return implClass != null;
1475    }
1476}
1477
Popular Tags