KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > description > ServiceDesc


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Axis" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation. For more
52  * information on the Apache Software Foundation, please see
53  * <http://www.apache.org/>.
54  */

55 package org.jboss.axis.description;
56
57 import org.jboss.axis.AxisServiceConfig;
58 import org.jboss.axis.Constants;
59 import org.jboss.axis.InternalException;
60 import org.jboss.axis.encoding.DefaultTypeMappingImpl;
61 import org.jboss.axis.encoding.TypeMapping;
62 import org.jboss.axis.encoding.TypeMappingRegistry;
63 import org.jboss.axis.encoding.TypeMappingRegistryImpl;
64 import org.jboss.axis.enums.Style;
65 import org.jboss.axis.enums.Use;
66 import org.jboss.axis.message.SOAPBodyElementAxisImpl;
67 import org.jboss.axis.message.SOAPEnvelopeAxisImpl;
68 import org.jboss.axis.utils.JavaUtils;
69 import org.jboss.axis.utils.Messages;
70 import org.jboss.axis.utils.bytecode.ParamNameExtractor;
71 import org.jboss.axis.wsdl.Skeleton;
72 import org.jboss.axis.wsdl.fromJava.Namespaces;
73 import org.jboss.logging.Logger;
74 import org.w3c.dom.Document JavaDoc;
75 import org.w3c.dom.Element JavaDoc;
76
77 import javax.xml.namespace.QName JavaDoc;
78 import javax.xml.rpc.holders.Holder JavaDoc;
79 import javax.xml.rpc.server.ServiceLifecycle JavaDoc;
80 import java.lang.reflect.InvocationTargetException JavaDoc;
81 import java.lang.reflect.Method JavaDoc;
82 import java.lang.reflect.Modifier JavaDoc;
83 import java.util.ArrayList JavaDoc;
84 import java.util.Collection JavaDoc;
85 import java.util.Collections JavaDoc;
86 import java.util.Comparator JavaDoc;
87 import java.util.HashMap JavaDoc;
88 import java.util.Iterator JavaDoc;
89 import java.util.List JavaDoc;
90 import java.util.StringTokenizer JavaDoc;
91
92
93 /**
94  * A ServiceDesc is an abstract description of a service.
95  * <p/>
96  * ServiceDescs contain OperationDescs, which are descriptions of operations.
97  * The information about a service's operations comes from one of two places:
98  * 1) deployment, or 2) introspection.
99  *
100  * @author Glen Daniels (gdaniels@apache.org)
101  */

102 public class ServiceDesc
103 {
104
105    private static Logger log = Logger.getLogger(ServiceDesc.class.getName());
106
107    /**
108     * The name of this service
109     */

110    private String JavaDoc name = null;
111
112    /** List of allowed methods */
113    /**
114     * null allows everything, an empty ArrayList allows nothing
115     */

116    private List JavaDoc allowedMethods = null;
117
118    /**
119     * List if disallowed methods
120     */

121    private List JavaDoc disallowedMethods = null;
122
123    /**
124     * Style/Use
125     */

126    private Style style = Style.RPC;
127    private Use use = Use.ENCODED;
128
129    // Style and Use are related. By default, if Style==RPC, Use should be
130
// ENCODED. But if Style==DOCUMENT, Use should be LITERAL. So we want
131
// to keep the defaults synced until someone explicitly sets the Use.
132
private boolean useSet = false;
133
134    /**
135     * Implementation class
136     */

137    private Class JavaDoc implClass = null;
138
139    /**
140     * Our operations - a list of OperationDescs
141     */

142    private ArrayList JavaDoc operations = new ArrayList JavaDoc();
143
144    /**
145     * A collection of namespaces which will map to this service
146     */

147    private List JavaDoc namespaceMappings = null;
148
149    /**
150     * Where does our WSDL document live? If this is non-null, the "?WSDL"
151     * generation will automatically return this file instead of dynamically
152     * creating a WSDL. BE CAREFUL because this means that Handlers will
153     * not be able to add to the WSDL for extensions/headers....
154     */

155    private String JavaDoc wsdlFileName = null;
156
157    /**
158     * An endpoint URL which someone has specified for this service. If
159     * this is set, WSDL generation will pick it up instead of defaulting
160     * to the transport URL.
161     */

162    private String JavaDoc endpointURL = null;
163
164    /**
165     * Place to store user-extensible service-related properties
166     */

167    private HashMap JavaDoc properties = null;
168
169    /**
170     * Is the implementation a Skeleton? If this is true, it will generate
171     * a Fault to provide OperationDescs via WSDD.
172     */

173    private boolean isSkeletonClass = false;
174
175    /**
176     * Cached copy of the skeleton "getOperationDescByName" method
177     */

178    private Method JavaDoc skelMethod = null;
179
180    /**
181     * Classes at which we should stop looking up the inheritance chain
182     * when introspecting
183     */

184    private ArrayList JavaDoc stopClasses = null;
185
186    /**
187     * Lookup caches
188     */

189    private HashMap JavaDoc name2OperationsMap = null;
190    private HashMap JavaDoc qname2OperationsMap = null;
191    private HashMap JavaDoc method2OperationMap = new HashMap JavaDoc();
192    private HashMap JavaDoc method2ParamsMap = new HashMap JavaDoc();
193    private OperationDesc messageServiceDefaultOp = null;
194
195    /**
196     * Method names for which we have completed any introspection necessary
197     */

198    private ArrayList JavaDoc completedNames = new ArrayList JavaDoc();
199
200    /**
201     * Our typemapping for resolving Java<->XML type issues
202     */

203    private TypeMapping tm = DefaultTypeMappingImpl.getSingleton();
204
205    private TypeMappingRegistry tmr = null;
206
207    private boolean haveAllSkeletonMethods = false;
208    private boolean introspectionComplete = false;
209
210    /**
211     * Default constructor
212     */

213    public ServiceDesc()
214    {
215    }
216
217    /**
218     * What kind of service is this?
219     *
220     * @return
221     */

222    public Style getStyle()
223    {
224       return style;
225    }
226
227    public void setStyle(Style style)
228    {
229       this.style = style;
230       if (!useSet)
231       {
232          // Use hasn't been explicitly set, so track style
233
use = style == Style.RPC ? Use.ENCODED : Use.LITERAL;
234       }
235    }
236
237    /**
238     * What kind of use is this?
239     *
240     * @return
241     */

242    public Use getUse()
243    {
244       return use;
245    }
246
247    public void setUse(Use use)
248    {
249       useSet = true;
250       this.use = use;
251    }
252
253    /**
254     * Determine whether or not this is a "wrapped" invocation, i.e. whether
255     * the outermost XML element of the "main" body element represents a
256     * method call, with the immediate children of that element representing
257     * arguments to the method.
258     *
259     * @return true if this is wrapped (i.e. RPC or WRAPPED style),
260     * false otherwise
261     */

262    public boolean isWrapped()
263    {
264       return ((style == Style.RPC) ||
265               (style == Style.WRAPPED));
266    }
267
268    /**
269     * the wsdl file of the service.
270     * When null, it means that the wsdl should be autogenerated
271     *
272     * @return filename or null
273     */

274    public String JavaDoc getWSDLFile()
275    {
276       return wsdlFileName;
277    }
278
279    /**
280     * set the wsdl file of the service; this causes the named
281     * file to be returned on a ?wsdl, probe, not introspection
282     * generated wsdl.
283     *
284     * @param wsdlFileName filename or null to re-enable introspection
285     */

286    public void setWSDLFile(String JavaDoc wsdlFileName)
287    {
288       this.wsdlFileName = wsdlFileName;
289    }
290
291    public List JavaDoc getAllowedMethods()
292    {
293       return allowedMethods;
294    }
295
296    public void setAllowedMethods(List JavaDoc allowedMethods)
297    {
298       this.allowedMethods = allowedMethods;
299    }
300
301    public Class JavaDoc getImplClass()
302    {
303       return implClass;
304    }
305
306    /**
307     * set the implementation class
308     * <p/>
309     * Warning: You cannot call getInitializedServiceDesc() after setting this
310     * as it uses this to indicate its work has already been done.
311     *
312     * @param implClass
313     * @throws IllegalArgumentException if the implementation class is already
314     * set
315     */

316    public void setImplClass(Class JavaDoc implClass)
317    {
318       if (this.implClass != null)
319          throw new IllegalArgumentException JavaDoc(Messages.getMessage("implAlreadySet"));
320
321       this.implClass = implClass;
322       if (Skeleton.class.isAssignableFrom(implClass))
323       {
324          isSkeletonClass = true;
325          loadSkeletonOperations();
326       }
327    }
328
329    private void loadSkeletonOperations()
330    {
331       Method JavaDoc method = null;
332       try
333       {
334          method = implClass.getDeclaredMethod("getOperationDescs",
335                  new Class JavaDoc[]{});
336       }
337       catch (NoSuchMethodException JavaDoc e)
338       {
339       }
340       catch (SecurityException JavaDoc e)
341       {
342       }
343       if (method == null)
344       {
345          // FIXME : Throw an error?
346
return;
347       }
348
349       try
350       {
351          Collection JavaDoc opers = (Collection JavaDoc)method.invoke(implClass, null);
352          for (Iterator JavaDoc i = opers.iterator(); i.hasNext();)
353          {
354             OperationDesc skelDesc = (OperationDesc)i.next();
355             addOperationDesc(skelDesc);
356          }
357       }
358       catch (IllegalAccessException JavaDoc e)
359       {
360          return;
361       }
362       catch (IllegalArgumentException JavaDoc e)
363       {
364          return;
365       }
366       catch (InvocationTargetException JavaDoc e)
367       {
368          return;
369       }
370       haveAllSkeletonMethods = true;
371    }
372
373    public TypeMapping getTypeMapping()
374    {
375       return tm;
376    }
377
378    public void setTypeMapping(TypeMapping tm)
379    {
380       this.tm = tm;
381    }
382
383    /**
384     * the name of the service
385     */

386    public String JavaDoc getName()
387    {
388       return name;
389    }
390
391    /**
392     * the name of the service
393     *
394     * @param name
395     */

396    public void setName(String JavaDoc name)
397    {
398       this.name = name;
399    }
400
401    public ArrayList JavaDoc getStopClasses()
402    {
403       return stopClasses;
404    }
405
406    public void setStopClasses(ArrayList JavaDoc stopClasses)
407    {
408       this.stopClasses = stopClasses;
409    }
410
411    public List JavaDoc getDisallowedMethods()
412    {
413       return disallowedMethods;
414    }
415
416    public void setDisallowedMethods(List JavaDoc disallowedMethods)
417    {
418       this.disallowedMethods = disallowedMethods;
419    }
420
421    public void addOperationDesc(OperationDesc operation)
422    {
423       operations.add(operation);
424       operation.setParent(this);
425       if (name2OperationsMap == null)
426       {
427          name2OperationsMap = new HashMap JavaDoc();
428       }
429
430       // Add name to name2Operations Map
431
String JavaDoc name = operation.getName();
432       ArrayList JavaDoc overloads = (ArrayList JavaDoc)name2OperationsMap.get(name);
433       if (overloads == null)
434       {
435          overloads = new ArrayList JavaDoc();
436          name2OperationsMap.put(name, overloads);
437       }
438       overloads.add(operation);
439    }
440
441    /**
442     * get all the operations as a list of OperationDescs.
443     * this method triggers an evaluation of the valid operations by
444     * introspection, so use sparingly
445     *
446     * @return reference to the operations array. This is not a copy
447     */

448    public ArrayList JavaDoc getOperations()
449    {
450       loadServiceDescByIntrospection(); // Just in case...
451
return operations;
452    }
453
454    /**
455     * get all overloaded operations by name
456     *
457     * @param methodName
458     * @return null for no match, or an array of OperationDesc objects
459     */

460    public OperationDesc[] getOperationsByName(String JavaDoc methodName)
461    {
462       getSyncedOperationsForName(implClass, methodName);
463
464       if (name2OperationsMap == null)
465          return null;
466
467       ArrayList JavaDoc overloads = (ArrayList JavaDoc)name2OperationsMap.get(methodName);
468       if (overloads == null)
469       {
470          return null;
471       }
472
473       OperationDesc[] array = new OperationDesc[overloads.size()];
474       return (OperationDesc[])overloads.toArray(array);
475    }
476
477    /**
478     * Return an operation matching the given method name. Note that if we
479     * have multiple overloads for this method, we will return the first one.
480     *
481     * @return null for no match
482     */

483    public OperationDesc getOperationByName(String JavaDoc methodName)
484    {
485       // If we need to load up operations from introspection data, do it.
486
// This returns fast if we don't need to do anything, so it's not very
487
// expensive.
488
getSyncedOperationsForName(implClass, methodName);
489
490       if (name2OperationsMap == null)
491          return null;
492
493       ArrayList JavaDoc overloads = (ArrayList JavaDoc)name2OperationsMap.get(methodName);
494       if (overloads == null)
495       {
496          return null;
497       }
498
499       return (OperationDesc)overloads.get(0);
500    }
501
502    /**
503     * Map an XML QName to an operation. Returns the first one it finds
504     * in the case of mulitple matches.
505     *
506     * @return null for no match
507     */

508    public OperationDesc getOperationByElementQName(QName JavaDoc qname)
509    {
510       OperationDesc[] overloads = getOperationsByQName(qname);
511
512       // Return the first one....
513
if ((overloads != null) && overloads.length > 0)
514          return overloads[0];
515
516       return null;
517    }
518
519    /**
520     * Return all operations which match this QName (i.e. get all the
521     * overloads)
522     *
523     * @return null for no match
524     */

525    public OperationDesc[] getOperationsByQName(QName JavaDoc qname)
526    {
527       // Look in our mapping of QNames -> operations.
528

529       // But first, let's make sure we've initialized said mapping....
530
initQNameMap();
531
532       ArrayList JavaDoc overloads = (ArrayList JavaDoc)qname2OperationsMap.get(qname);
533
534       if (overloads == null)
535       {
536          // Nothing specifically matching this QName.
537
if ((isWrapped() ||
538                  ((style == Style.MESSAGE) &&
539                  (getDefaultNamespace() == null))) &&
540                  (name2OperationsMap != null))
541          {
542             // Try ignoring the namespace....?
543
overloads = (ArrayList JavaDoc)name2OperationsMap.get(qname.getLocalPart());
544          }
545
546          // Handle the case where a single Message-style operation wants
547
// to accept anything.
548
if ((style == Style.MESSAGE) && (messageServiceDefaultOp != null))
549             return new OperationDesc[]{messageServiceDefaultOp};
550
551          if (overloads == null)
552             return null;
553       }
554
555       getSyncedOperationsForName(implClass,
556               ((OperationDesc)overloads.get(0)).getName());
557
558       // Sort the overloads by number of arguments - prevents us calling methods
559
// with more parameters than supplied in the request (with missing parameters
560
// defaulted to null) when a perfectly good method exists with exactly the
561
// supplied parameters.
562
Collections.sort(overloads,
563               new Comparator JavaDoc()
564               {
565                  public int compare(Object JavaDoc o1, Object JavaDoc o2)
566                  {
567                     Method JavaDoc meth1 = ((OperationDesc)o1).getMethod();
568                     Method JavaDoc meth2 = ((OperationDesc)o2).getMethod();
569                     return (meth1.getParameterTypes().length -
570                             meth2.getParameterTypes().length);
571                  }
572               });
573
574       OperationDesc[] array = new OperationDesc[overloads.size()];
575       return (OperationDesc[])overloads.toArray(array);
576    }
577
578    private synchronized void initQNameMap()
579    {
580       if (qname2OperationsMap == null)
581       {
582          loadServiceDescByIntrospection();
583
584          qname2OperationsMap = new HashMap JavaDoc();
585          for (Iterator JavaDoc i = operations.iterator(); i.hasNext();)
586          {
587             OperationDesc operationDesc = (OperationDesc)i.next();
588             QName JavaDoc qname = operationDesc.getElementQName();
589             ArrayList JavaDoc list = (ArrayList JavaDoc)qname2OperationsMap.get(qname);
590             if (list == null)
591             {
592                list = new ArrayList JavaDoc();
593                qname2OperationsMap.put(qname, list);
594             }
595             list.add(operationDesc);
596          }
597       }
598    }
599
600    /**
601     * Synchronize an existing OperationDesc to a java.lang.Method.
602     * <p/>
603     * This method is used when the deployer has specified operation metadata
604     * and we want to match that up with a real java Method so that the
605     * Operation-level dispatch carries us all the way to the implementation.
606     * Search the declared methods on the implementation class to find one
607     * with an argument list which matches our parameter list.
608     */

609    private void syncOperationToClass(OperationDesc opDesc, Class JavaDoc implClass)
610    {
611       log.debug("Enter: syncOperationToClass " + opDesc);
612
613       // ------------------------------------------------
614
// Developer Note:
615
//
616
// The goal of the sync code is to associate
617
// the OperationDesc/ParamterDesc with the
618
// target Method. There are a number of ways to get to this
619
// point depending on what information
620
// is available. Here are the main scenarios:
621
//
622
// A) Deployment with wsdd (non-skeleton):
623
// * OperationDesc/ParameterDesc loaded from deploy.wsdd
624
// * Loaded ParameterDesc does not have javaType,
625
// so it is discovered using the TypeMappingRegistry
626
// (also loaded via deploy.wsdd) and the
627
// typeQName specified by the ParameterDesc.
628
// * Sync occurs using the discovered
629
// javaTypes and the javaTypes of the Method
630
// parameters
631
//
632
// B) Deployment with no wsdd OperationDesc info (non-skeleton):
633
// * Implementation Class introspected to build
634
// OperationDesc/ParameterDesc.
635
// * ParameterDesc is known via introspection.
636
// * ParameterDesc are discovered using javaType
637
// and TypeMappingRegistry.
638
// * Sync occurs using the introspected
639
// javaTypes and the javaTypes of the Method
640
// parameters
641
//
642
// C) Deployment with wsdd (skeleton):
643
// * OperationDesc/ParameterDesc loaded from the Skeleton
644
// * In this scenario the ParameterDescs' already
645
// have javaTypes (see E below).
646
// * Sync occurs using the ParameterDesc
647
// javaTypes and the javaTypes of the Method
648
// parameters.
649
//
650
// D) Commandline Java2WSDL loading non-Skeleton Class/Interface
651
// * Class/Interface introspected to build
652
// OperationDesc/ParameterDesc.
653
// * The javaTypes of the ParameterDesc are set using introspection.
654
// * typeQNames are determined for built-in types using
655
// from the default TypeMappingRegistry. Other
656
// typeQNames are guessed from the javaType. Note
657
// that there is no loaded TypeMappingRegistry.
658
// * Sync occurs using the ParameterDesc
659
// javaTypes and the javaTypes of the Method
660
// parameters.
661
//
662
// E) Commandline Java2WSDL loading Skeleton Class
663
// * OperationDesc/ParameterDesc loaded from Skeleton
664
// * Each ParameterDesc has an appropriate typeQName
665
// * Each ParameterDesc also has a javaType, which is
666
// essential for sync'ing up with the
667
// method since there is no loaded TypeMappingRegistry.
668
// * Syncronization occurs using the ParameterDesc
669
// javaTypes and the javaTypes of the Method
670
// parameters.
671
//
672
// So in each scenario, the ultimate sync'ing occurs
673
// using the javaTypes of the ParameterDescs and the
674
// javaTypes of the Method parameters.
675
//
676
// ------------------------------------------------
677

678       // If we're already mapped to a Java method, no need to do anything.
679
if (opDesc.getMethod() != null)
680          return;
681
682       // Find the method. We do this once for each Operation.
683

684       Method JavaDoc[] methods = implClass.getDeclaredMethods();
685       // A place to keep track of possible matches
686
Method JavaDoc possibleMatch = null;
687
688       for (int i = 0; i < methods.length; i++)
689       {
690          Method JavaDoc method = methods[i];
691          if (Modifier.isPublic(method.getModifiers()) &&
692                  method.getName().equals(opDesc.getName()) &&
693                  method2OperationMap.get(method) == null)
694          {
695
696             log.debug("Sync method: " + method);
697
698             if (style == Style.MESSAGE)
699             {
700                int messageOperType = checkMessageMethod(method);
701                if (messageOperType == OperationDesc.MSG_METHOD_NONCONFORMING) continue;
702                if (messageOperType == -1)
703                {
704                   throw new InternalException("Couldn't match method to any of the allowable message-style patterns!");
705                }
706                opDesc.setMessageOperationStyle(messageOperType);
707             }
708
709             // Check params
710
Class JavaDoc[] paramTypes = method.getParameterTypes();
711             if (paramTypes.length != opDesc.getNumParams())
712             {
713                log.debug("Number of parameters don't match");
714                continue;
715             }
716
717             int j;
718             boolean conversionNecessary = false;
719             for (j = 0; j < paramTypes.length; j++)
720             {
721                Class JavaDoc type = paramTypes[j];
722                Class JavaDoc actualType = type;
723
724                log.debug("Converting param: " + type);
725
726                if (Holder JavaDoc.class.isAssignableFrom(type))
727                   actualType = JavaUtils.getHolderValueType(type);
728
729                ParameterDesc param = opDesc.getParameter(j);
730                Class JavaDoc paramClass = param.getJavaType();
731
732                QName JavaDoc typeQName = param.getTypeQName();
733                if (typeQName == null)
734                {
735                   // No typeQName is available. Set it using
736
// information from the actual type.
737
// (Scenarios B and D)
738
// There is no need to try and match with
739
// the Method parameter javaType because
740
// the ParameterDesc is being constructed
741
// by introspecting the Method.
742
typeQName = tm.getTypeQName(type);
743                   param.setTypeQName(typeQName);
744                   log.debug("Setting param TypeQName: " + typeQName);
745
746                }
747                else
748                {
749                   // A type qname is available.
750
// Ensure that the ParameterDesc javaType
751
// is convertable to the Method parameter type
752
//
753
// Use the available javaType (Scenarios C and E)
754
// or get one from the TMR (Scenario A).
755
if (paramClass != null && JavaUtils.getHolderValueType(paramClass) != null)
756                   {
757                      paramClass = JavaUtils.getHolderValueType(paramClass);
758                      log.debug("Setting param class to holder type: " + paramClass);
759                   }
760                   if (paramClass == null)
761                   {
762                      paramClass = tm.getClassForQName(param.getTypeQName());
763                      log.debug("Setting param class from TypeQName: " + paramClass);
764                   }
765
766                   if (paramClass != null)
767                   {
768                      // This is a match if the paramClass is somehow
769
// convertable to the "real" parameter type. If not,
770
// break out of this loop.
771
if (!JavaUtils.isConvertable(paramClass, actualType))
772                      {
773                         log.debug("Param class is not convertible: [param=" + paramClass + ",actual=" + actualType + "]");
774                         break;
775                      }
776
777                      if (!actualType.isAssignableFrom(paramClass))
778                      {
779                         // This doesn't fit without conversion
780
conversionNecessary = true;
781                         log.debug("Actual type is not assignable from param class: [param=" + paramClass + ",actual=" + actualType + "]");
782                      }
783                   }
784                }
785                // In all scenarios the ParameterDesc javaType is set to
786
// match the javaType in the corresponding parameter.
787
// This is essential.
788
param.setJavaType(type);
789                log.debug("Setting param java type: " + type);
790             }
791
792             if (j != paramTypes.length)
793             {
794                // failed.
795
continue;
796             }
797
798             // This is our latest possibility
799
possibleMatch = method;
800             log.debug("Possible match: " + possibleMatch);
801
802             // If this is exactly it, stop now. Otherwise keep looking
803
// just in case we find a better match.
804
if (!conversionNecessary)
805             {
806                break;
807             }
808
809             log.debug("Conversion still necessary");
810          }
811       }
812
813       // At this point, we may or may not have a possible match.
814
// FIXME : Should we prefer an exact match from a base class over
815
// a with-conversion match from the target class? If so,
816
// we'll need to change the logic below.
817
if (possibleMatch != null)
818       {
819          ParameterDesc retParamDesc = opDesc.getReturnParamDesc();
820          QName JavaDoc retTypeQName = retParamDesc.getTypeQName();
821          Class JavaDoc retType = retParamDesc.getJavaType();
822          if (retTypeQName != null && retType == null)
823             retType = tm.getClassForQName(retTypeQName);
824
825          if (retType != null)
826          {
827             Class JavaDoc seiReturnType = possibleMatch.getReturnType();
828             if (JavaUtils.isConvertable(retType, seiReturnType))
829             {
830                opDesc.setReturnClass(seiReturnType);
831                log.debug("Setting return type: " + seiReturnType);
832             }
833             else
834             {
835                log.warn("Return type is not convertible to: " + retType);
836                //possibleMatch = null;
837
}
838          }
839
840          if (possibleMatch != null)
841          {
842             // Do the faults
843
createFaultMetadata(possibleMatch, opDesc);
844
845             opDesc.setMethod(possibleMatch);
846             method2OperationMap.put(possibleMatch, opDesc);
847             log.debug("Setting operation method: " + possibleMatch);
848          }
849       }
850
851       // Didn't find a match. Try the superclass, if appropriate
852
if (opDesc.getMethod() == null)
853       {
854          Class JavaDoc superClass = implClass.getSuperclass();
855          if (superClass != null &&
856                  !superClass.getName().startsWith("java.") &&
857                  !superClass.getName().startsWith("javax.") &&
858                  (stopClasses == null ||
859                  !stopClasses.contains(superClass.getName())))
860          {
861
862             log.debug("No match found, trying super class");
863             syncOperationToClass(opDesc, superClass);
864          }
865       }
866
867       // Exception if sync fails to find method for operation
868
if (opDesc.getMethod() == null)
869       {
870          InternalException ie =
871                  new InternalException(Messages.getMessage("serviceDescOperSync00",
872                          opDesc.getName(),
873                          implClass.getName()));
874          throw ie;
875       }
876    }
877
878    private int checkMessageMethod(Method JavaDoc method)
879    {
880       // Collect the types so we know what we're dealing with in the target
881
// method.
882
Class JavaDoc[] params = method.getParameterTypes();
883
884       if (params.length == 1)
885       {
886          if ((params[0] == Element JavaDoc[].class) &&
887                  (method.getReturnType() == Element JavaDoc[].class))
888          {
889             return OperationDesc.MSG_METHOD_ELEMENTARRAY;
890          }
891
892          if ((params[0] == SOAPBodyElementAxisImpl[].class) &&
893                  (method.getReturnType() == SOAPBodyElementAxisImpl[].class))
894          {
895             return OperationDesc.MSG_METHOD_BODYARRAY;
896          }
897
898          if ((params[0] == Document JavaDoc.class) &&
899                  (method.getReturnType() == Document JavaDoc.class))
900          {
901             return OperationDesc.MSG_METHOD_DOCUMENT;
902          }
903       }
904       else if (params.length == 2)
905       {
906          if ((params[0] == SOAPEnvelopeAxisImpl.class) &&
907                  (params[1] == SOAPEnvelopeAxisImpl.class) &&
908                  (method.getReturnType() == void.class))
909          {
910             return OperationDesc.MSG_METHOD_SOAPENVELOPE;
911          }
912       }
913       if (null != allowedMethods && !allowedMethods.isEmpty())
914          throw new InternalException(Messages.getMessage("badMsgMethodParams",
915                  method.getName()));
916       return OperationDesc.MSG_METHOD_NONCONFORMING;
917    }
918
919    /**
920     * Fill in a service description by introspecting the implementation
921     * class.
922     */

923    public void loadServiceDescByIntrospection()
924    {
925       loadServiceDescByIntrospection(implClass);
926
927       // Setting this to null means there is nothing more to do, and it
928
// avoids future string compares.
929
completedNames = null;
930    }
931
932    /**
933     * Fill in a service description by introspecting the implementation
934     * class.
935     */

936    public void loadServiceDescByIntrospection(Class JavaDoc implClass)
937    {
938       if (introspectionComplete || implClass == null)
939       {
940          return;
941       }
942
943       // set the implementation class for the service description
944
this.implClass = implClass;
945       if (Skeleton.class.isAssignableFrom(implClass))
946       {
947          isSkeletonClass = true;
948          loadSkeletonOperations();
949       }
950
951       /** If the class knows what it should be exporting,
952        * respect its wishes.
953        */

954       AxisServiceConfig axisConfig = null;
955       try
956       {
957          Method JavaDoc method = implClass.getDeclaredMethod("getAxisServiceConfig", new Class JavaDoc[]{});
958          if (method != null && Modifier.isStatic(method.getModifiers()))
959          {
960             axisConfig = (AxisServiceConfig)method.invoke(null, null);
961          }
962       }
963       catch (Exception JavaDoc e)
964       {
965          // No problem, just continue without...
966
}
967
968       if (axisConfig != null)
969       {
970          String JavaDoc allowedMethodsStr = axisConfig.getAllowedMethods();
971          if (allowedMethodsStr != null && !"*".equals(allowedMethodsStr))
972          {
973             ArrayList JavaDoc methodList = new ArrayList JavaDoc();
974             StringTokenizer JavaDoc tokenizer =
975                     new StringTokenizer JavaDoc(allowedMethodsStr, " ,");
976             while (tokenizer.hasMoreTokens())
977             {
978                methodList.add(tokenizer.nextToken());
979             }
980             setAllowedMethods(methodList);
981          }
982       }
983
984       loadServiceDescByIntrospectionRecursive(implClass);
985
986       // All operations should now be synchronized. Check it.
987
for (Iterator JavaDoc iterator = operations.iterator(); iterator.hasNext();)
988       {
989          OperationDesc operation = (OperationDesc)iterator.next();
990          if (operation.getMethod() == null)
991          {
992             throw new InternalException(Messages.getMessage("badWSDDOperation",
993                     operation.getName(),
994                     "" + operation.getNumParams()));
995          }
996       }
997
998       if ((style == Style.MESSAGE) && operations.size() == 1)
999       {
1000         messageServiceDefaultOp = (OperationDesc)operations.get(0);
1001      }
1002
1003      introspectionComplete = true;
1004   }
1005
1006   /**
1007    * Is this method from ServiceLifeCycle interface?
1008    *
1009    * @param m
1010    * @return true if this method is from ServiceLifeCycle interface
1011    */

1012   private boolean isServiceLifeCycleMethod(Class JavaDoc implClass, Method JavaDoc m)
1013   {
1014      if (ServiceLifecycle JavaDoc.class.isAssignableFrom(implClass))
1015      {
1016         String JavaDoc methodName = m.getName();
1017
1018         if (methodName.equals("init"))
1019         {
1020            // Check if the method signature is
1021
// "public abstract void init(Object context) throws ServiceException;"
1022
Class JavaDoc[] classes = m.getParameterTypes();
1023            if (classes != null &&
1024                    classes.length == 1 &&
1025                    classes[0] == Object JavaDoc.class &&
1026                    m.getReturnType() == Void.TYPE)
1027            {
1028               return true;
1029            }
1030         }
1031         else if (methodName.equals("destroy"))
1032         {
1033            // Check if the method signature is
1034
// "public abstract void destroy();"
1035
Class JavaDoc[] classes = m.getParameterTypes();
1036            if (classes != null &&
1037                    classes.length == 0 &&
1038                    m.getReturnType() == Void.TYPE)
1039            {
1040               return true;
1041            }
1042         }
1043      }
1044      return false;
1045   }
1046
1047   /**
1048    * Recursive helper class for loadServiceDescByIntrospection
1049    */

1050   private void loadServiceDescByIntrospectionRecursive(Class JavaDoc implClass)
1051   {
1052      if (Skeleton.class.equals(implClass))
1053      {
1054         return;
1055      }
1056
1057      Method JavaDoc[] methods = implClass.getDeclaredMethods();
1058
1059      for (int i = 0; i < methods.length; i++)
1060      {
1061         if (Modifier.isPublic(methods[i].getModifiers()) && !isServiceLifeCycleMethod(implClass, methods[i]))
1062         {
1063            getSyncedOperationsForName(implClass, methods[i].getName());
1064         }
1065      }
1066
1067      if (implClass.isInterface())
1068      {
1069         Class JavaDoc[] superClasses = implClass.getInterfaces();
1070         for (int i = 0; i < superClasses.length; i++)
1071         {
1072            Class JavaDoc superClass = superClasses[i];
1073            if (!superClass.getName().startsWith("java.") &&
1074                    !superClass.getName().startsWith("javax.") &&
1075                    (stopClasses == null ||
1076                    !stopClasses.contains(superClass.getName())))
1077            {
1078               loadServiceDescByIntrospectionRecursive(superClass);
1079            }
1080         }
1081      }
1082      else
1083      {
1084         Class JavaDoc superClass = implClass.getSuperclass();
1085         if (superClass != null &&
1086                 !superClass.getName().startsWith("java.") &&
1087                 !superClass.getName().startsWith("javax.") &&
1088                 (stopClasses == null ||
1089                 !stopClasses.contains(superClass.getName())))
1090         {
1091            loadServiceDescByIntrospectionRecursive(superClass);
1092         }
1093      }
1094   }
1095
1096   /**
1097    * Fill in a service description by introspecting the implementation
1098    * class. This version takes the implementation class and the in-scope
1099    * TypeMapping.
1100    */

1101   public void loadServiceDescByIntrospection(Class JavaDoc cls, TypeMapping tm)
1102   {
1103      // Should we complain if the implClass changes???
1104
implClass = cls;
1105      this.tm = tm;
1106
1107      if (Skeleton.class.isAssignableFrom(implClass))
1108      {
1109         isSkeletonClass = true;
1110         loadSkeletonOperations();
1111      }
1112
1113      loadServiceDescByIntrospection();
1114   }
1115
1116   /**
1117    * Makes sure we have completely synchronized OperationDescs with
1118    * the implementation class.
1119    */

1120   private void getSyncedOperationsForName(Class JavaDoc implClass, String JavaDoc methodName)
1121   {
1122      // If we're a Skeleton deployment, skip the statics.
1123
if (isSkeletonClass)
1124      {
1125         if (methodName.equals("getOperationDescByName") ||
1126                 methodName.equals("getOperationDescs"))
1127            return;
1128      }
1129
1130      // If we have no implementation class, don't worry about it (we're
1131
// probably on the client)
1132
if (implClass == null)
1133         return;
1134
1135      // If we're done introspecting, or have completed this method, return
1136
if (completedNames == null || completedNames.contains(methodName))
1137         return;
1138
1139      // Skip it if it's not a sanctioned method name
1140
if ((allowedMethods != null) &&
1141              !allowedMethods.contains(methodName))
1142         return;
1143
1144      if ((disallowedMethods != null) &&
1145              disallowedMethods.contains(methodName))
1146         return;
1147
1148      // If we're a skeleton class, make sure we don't already have any
1149
// OperationDescs for this name (as that might cause conflicts),
1150
// then load them up from the Skeleton class.
1151
if (isSkeletonClass && !haveAllSkeletonMethods)
1152      {
1153         // FIXME : Check for existing ones and fault if found
1154

1155         if (skelMethod == null)
1156         {
1157            // Grab metadata from the Skeleton for parameter info
1158
try
1159            {
1160               skelMethod = implClass.getDeclaredMethod("getOperationDescByName",
1161                       new Class JavaDoc[]{String JavaDoc.class});
1162            }
1163            catch (NoSuchMethodException JavaDoc e)
1164            {
1165            }
1166            catch (SecurityException JavaDoc e)
1167            {
1168            }
1169            if (skelMethod == null)
1170            {
1171               // FIXME : Throw an error?
1172
return;
1173            }
1174         }
1175         try
1176         {
1177            List JavaDoc skelList =
1178                    (List JavaDoc)skelMethod.invoke(implClass,
1179                            new Object JavaDoc[]{methodName});
1180            if (skelList != null)
1181            {
1182               Iterator JavaDoc i = skelList.iterator();
1183               while (i.hasNext())
1184               {
1185                  addOperationDesc((OperationDesc)i.next());
1186               }
1187            }
1188         }
1189         catch (IllegalAccessException JavaDoc e)
1190         {
1191            return;
1192         }
1193         catch (IllegalArgumentException JavaDoc e)
1194         {
1195            return;
1196         }
1197         catch (InvocationTargetException JavaDoc e)
1198         {
1199            return;
1200         }
1201      }
1202
1203      // OK, go find any current OperationDescs for this method name and
1204
// make sure they're synced with the actual class.
1205
if (name2OperationsMap != null)
1206      {
1207         ArrayList JavaDoc currentOverloads =
1208                 (ArrayList JavaDoc)name2OperationsMap.get(methodName);
1209         if (currentOverloads != null)
1210         {
1211            // For each one, sync it to the implementation class' methods
1212
for (Iterator JavaDoc i = currentOverloads.iterator(); i.hasNext();)
1213            {
1214               OperationDesc oper = (OperationDesc)i.next();
1215               if (oper.getMethod() == null)
1216               {
1217                  syncOperationToClass(oper, implClass);
1218               }
1219            }
1220         }
1221      }
1222
1223      // Now all OperationDescs from deployment data have been completely
1224
// filled in. So we now make new OperationDescs for any method
1225
// overloads which were not covered above.
1226
// NOTE : This is the "lenient" approach, which allows you to
1227
// specify one overload and still get the others by introspection.
1228
// We could equally well return above if we found OperationDescs,
1229
// and have a rule that if you specify any overloads, you must specify
1230
// all the ones you want accessible.
1231

1232      createOperationsForName(implClass, methodName);
1233
1234      // Note that we never have to look at this method name again.
1235
completedNames.add(methodName);
1236   }
1237
1238   /**
1239    * Look for methods matching this name, and for each one, create an
1240    * OperationDesc (if it's not already in our list).
1241    * <p/>
1242    * TODO: Make this more efficient
1243    */

1244   private void createOperationsForName(Class JavaDoc implClass, String JavaDoc methodName)
1245   {
1246      // If we're a Skeleton deployment, skip the statics.
1247
if (isSkeletonClass)
1248      {
1249         if (methodName.equals("getOperationDescByName") ||
1250                 methodName.equals("getOperationDescs"))
1251            return;
1252      }
1253
1254      Method JavaDoc[] methods = implClass.getDeclaredMethods();
1255
1256      for (int i = 0; i < methods.length; i++)
1257      {
1258         Method JavaDoc method = methods[i];
1259         if (Modifier.isPublic(method.getModifiers()) &&
1260                 method.getName().equals(methodName))
1261         {
1262            createOperationForMethod(method);
1263         }
1264      }
1265
1266      Class JavaDoc superClass = implClass.getSuperclass();
1267      if (superClass != null &&
1268              !superClass.getName().startsWith("java.") &&
1269              !superClass.getName().startsWith("javax."))
1270      {
1271         createOperationsForName(superClass, methodName);
1272      }
1273   }
1274
1275   /**
1276    * Make an OperationDesc from a Java method.
1277    * <p/>
1278    * In the absence of deployment metadata, this code will introspect a
1279    * Method and create an appropriate OperationDesc. If the class
1280    * implements the Skeleton interface, we will use the metadata from there
1281    * in constructing the OperationDesc. If not, we use parameter names
1282    * from the bytecode debugging info if available, or "in0", "in1", etc.
1283    * if not.
1284    */

1285   private void createOperationForMethod(Method JavaDoc method)
1286   {
1287      // If we've already got it, never mind
1288
if (method2OperationMap.get(method) != null)
1289      {
1290         return;
1291      }
1292
1293      Class JavaDoc[] paramTypes = method.getParameterTypes();
1294
1295      // And if we've already got an exact match (i.e. an override),
1296
// never mind
1297

1298      ArrayList JavaDoc overloads = name2OperationsMap == null ? null :
1299              (ArrayList JavaDoc)name2OperationsMap.get(method.getName());
1300      if (overloads != null && !overloads.isEmpty())
1301      {
1302         // Search each OperationDesc that already has a Method
1303
// associated with it, and check for parameter type equivalence.
1304
for (int i = 0; i < overloads.size(); i++)
1305         {
1306            OperationDesc op = (OperationDesc)overloads.get(i);
1307            Method JavaDoc checkMethod = op.getMethod();
1308            if (checkMethod != null)
1309            {
1310               Class JavaDoc[] others = checkMethod.getParameterTypes();
1311               if (paramTypes.length == others.length)
1312               {
1313                  int j = 0;
1314                  for (; j < others.length; j++)
1315                  {
1316                     if (!others[j].equals(paramTypes[j]))
1317                        break;
1318                  }
1319                  // If we got all the way through, we have a match.
1320
if (j == others.length)
1321                     return;
1322               }
1323            }
1324         }
1325      }
1326
1327      // Make an OperationDesc, fill in common stuff
1328
OperationDesc operation = new OperationDesc();
1329      operation.setName(method.getName());
1330      String JavaDoc defaultNS = "";
1331      if (namespaceMappings != null && !namespaceMappings.isEmpty())
1332      {
1333         // If we have a default namespace mapping, require callers to
1334
// use that namespace.
1335
defaultNS = (String JavaDoc)namespaceMappings.get(0);
1336      }
1337      if (defaultNS.length() == 0)
1338      {
1339         defaultNS = Namespaces.makeNamespace(method.getDeclaringClass().getName());
1340      }
1341      operation.setElementQName(new QName JavaDoc(defaultNS, method.getName()));
1342      operation.setMethod(method);
1343
1344      // If this is a MESSAGE style service, set up the OperationDesc
1345
// appropriately.
1346
if (style == Style.MESSAGE)
1347      {
1348         int messageOperType = checkMessageMethod(method);
1349         if (messageOperType == OperationDesc.MSG_METHOD_NONCONFORMING) return;
1350         if (messageOperType == -1)
1351         {
1352            throw new InternalException("Couldn't match method to any of the allowable message-style patterns!");
1353         }
1354         operation.setMessageOperationStyle(messageOperType);
1355         operation.setReturnClass(Object JavaDoc.class);
1356         operation.setReturnType(Constants.XSD_ANYTYPE);
1357      }
1358      else
1359      {
1360         // For other styles, continue here.
1361
Class JavaDoc retClass = method.getReturnType();
1362         operation.setReturnClass(retClass);
1363         operation.setReturnType(tm.getTypeQName(method.getReturnType()));
1364
1365         String JavaDoc[] paramNames = getParamNames(method);
1366
1367         for (int k = 0; k < paramTypes.length; k++)
1368         {
1369            Class JavaDoc type = paramTypes[k];
1370            ParameterDesc paramDesc = new ParameterDesc();
1371            String JavaDoc opNamespace = operation.getElementQName().getNamespaceURI();
1372
1373            // If we have a name for this param, use it, otherwise call
1374
// it "in*"
1375
if (paramNames != null && paramNames[k] != null &&
1376                    paramNames[k].length() > 0)
1377            {
1378               paramDesc.setQName(new QName JavaDoc(opNamespace, paramNames[k]));
1379            }
1380            else
1381            {
1382               paramDesc.setQName(new QName JavaDoc(opNamespace, "in" + k));
1383            }
1384
1385            // If it's a Holder, mark it INOUT, and set the XML type QName
1386
// to the held type. Otherwise it's IN.
1387

1388            Class JavaDoc heldClass = JavaUtils.getHolderValueType(type);
1389            if (heldClass != null)
1390            {
1391               paramDesc.setMode(ParameterDesc.INOUT);
1392               paramDesc.setTypeQName(tm.getTypeQName(heldClass));
1393            }
1394            else
1395            {
1396               paramDesc.setMode(ParameterDesc.IN);
1397               paramDesc.setTypeQName(tm.getTypeQName(type));
1398            }
1399            paramDesc.setJavaType(type);
1400            operation.addParameter(paramDesc);
1401         }
1402      }
1403
1404      createFaultMetadata(method, operation);
1405
1406      addOperationDesc(operation);
1407      method2OperationMap.put(method, operation);
1408   }
1409
1410   private void createFaultMetadata(Method JavaDoc method, OperationDesc operation)
1411   {
1412
1413      // Create Exception Types
1414
Class JavaDoc[] exceptionTypes = new Class JavaDoc[method.getExceptionTypes().length];
1415      exceptionTypes = method.getExceptionTypes();
1416
1417      for (int i = 0; i < exceptionTypes.length; i++)
1418      {
1419
1420         // Every remote method declares a java.rmi.RemoteException
1421
// Only interested in application specific exceptions.
1422
// Ignore java and javax package exceptions.
1423
Class JavaDoc ex = exceptionTypes[i];
1424         if (ex != java.rmi.RemoteException JavaDoc.class &&
1425                 ex != org.jboss.axis.AxisFault.class &&
1426                 !ex.getName().startsWith("java.") &&
1427                 !ex.getName().startsWith("javax."))
1428         {
1429
1430            log.debug("createFaultMetadata: " + ex);
1431
1432            // For JSR 101 v.1.0, there is a simple fault mapping
1433
// and a complexType fault mapping...both mappings
1434
// generate a class that extends (directly or indirectly)
1435
// Exception.
1436
// When converting java back to wsdl it is not possible
1437
// to determine which way to do the mapping,
1438
// so it is always mapped back using the complexType
1439
// fault mapping because it is more useful (i.e. it
1440
// establishes a hierarchy of exceptions). Note that this
1441
// will not cause any roundtripping problems.
1442
// Rich
1443

1444
1445            /* Old Simple Type Mode
1446            Field[] f = ex.getDeclaredFields();
1447            ArrayList exceptionParams = new ArrayList();
1448            for (int j = 0; j < f.length; j++) {
1449                int mod = f[j].getModifiers();
1450                if (Modifier.isPublic(mod) &&
1451                     !Modifier.isStatic(mod)) {
1452                    QName qname = new QName("", f[j].getName());
1453                    QName typeQName = tm.getTypeQName(f[j].getType());
1454                    ParameterDesc param = new ParameterDesc(qname,
1455                                                            ParameterDesc.IN,
1456                                                            typeQName);
1457                    param.setJavaType(f[j].getType());
1458                    exceptionParams.add(param);
1459                }
1460            }
1461            String pkgAndClsName = ex.getName();
1462            FaultDesc fault = new FaultDesc();
1463            fault.setName(pkgAndClsName);
1464            fault.setParameters(exceptionParams);
1465            operation.addFault(fault);
1466            */

1467
1468            FaultDesc fault = operation.getFaultByClass(ex);
1469
1470            // If we didn't find one, create a new one
1471
if (fault == null)
1472            {
1473               fault = new FaultDesc();
1474               log.debug("Creating new fault desc: " + fault);
1475            }
1476
1477            // Try to fil in any parts of the faultDesc that aren't there
1478

1479            // XMLType
1480
QName JavaDoc xmlType = fault.getXmlType();
1481            if (xmlType == null)
1482            {
1483               QName JavaDoc typeQName = tm.getTypeQName(ex);
1484               fault.setXmlType(typeQName);
1485               log.debug("Setting XMLType: " + typeQName);
1486            }
1487
1488            // Name and Class Name
1489
String JavaDoc pkgAndClsName = ex.getName();
1490            if (fault.getClassName() == null)
1491            {
1492               fault.setClassName(pkgAndClsName);
1493               log.debug("Setting ClassName: " + pkgAndClsName);
1494            }
1495
1496            if (fault.getName() == null)
1497            {
1498               String JavaDoc name = pkgAndClsName.substring(pkgAndClsName.lastIndexOf('.') + 1,
1499                       pkgAndClsName.length());
1500               fault.setName(name);
1501               log.debug("Setting Name: " + name);
1502            }
1503
1504            // Parameters
1505
// We add a single parameter which points to the type
1506
if (fault.getParameters() == null)
1507            {
1508               if (xmlType == null)
1509               {
1510                  xmlType = tm.getTypeQName(ex);
1511               }
1512               QName JavaDoc qname = fault.getQName();
1513               if (qname == null)
1514               {
1515                  qname = new QName JavaDoc("", "fault");
1516               }
1517               ParameterDesc param = new ParameterDesc(qname, ParameterDesc.IN, xmlType);
1518               param.setJavaType(ex);
1519               ArrayList JavaDoc exceptionParams = new ArrayList JavaDoc();
1520               exceptionParams.add(param);
1521               fault.setParameters(exceptionParams);
1522            }
1523
1524            // QName
1525
if (fault.getQName() == null)
1526            {
1527               fault.setQName(new QName JavaDoc(pkgAndClsName));
1528            }
1529
1530            // Add the fault to the operation
1531
operation.addFault(fault);
1532         }
1533      }
1534   }
1535
1536   private String JavaDoc[] getParamNames(Method JavaDoc method)
1537   {
1538      synchronized (method2ParamsMap)
1539      {
1540         String JavaDoc[] paramNames = (String JavaDoc[])method2ParamsMap.get(method);
1541         if (paramNames != null)
1542            return paramNames;
1543         paramNames = ParamNameExtractor.getParameterNamesFromDebugInfo(method);
1544         method2ParamsMap.put(method, paramNames);
1545         return paramNames;
1546      }
1547   }
1548
1549   public void setNamespaceMappings(List JavaDoc namespaces)
1550   {
1551      namespaceMappings = namespaces;
1552   }
1553
1554   public String JavaDoc getDefaultNamespace()
1555   {
1556      if (namespaceMappings == null || namespaceMappings.isEmpty())
1557         return null;
1558      return (String JavaDoc)namespaceMappings.get(0);
1559   }
1560
1561   public void setDefaultNamespace(String JavaDoc namespace)
1562   {
1563      if (namespaceMappings == null)
1564         namespaceMappings = new ArrayList JavaDoc();
1565      namespaceMappings.add(0, namespace);
1566   }
1567
1568   public void setProperty(String JavaDoc name, Object JavaDoc value)
1569   {
1570      if (properties == null)
1571      {
1572         properties = new HashMap JavaDoc();
1573      }
1574      properties.put(name, value);
1575   }
1576
1577   public Object JavaDoc getProperty(String JavaDoc name)
1578   {
1579      if (properties == null)
1580         return null;
1581
1582      return properties.get(name);
1583   }
1584
1585   public String JavaDoc getEndpointURL()
1586   {
1587      return endpointURL;
1588   }
1589
1590   public void setEndpointURL(String JavaDoc endpointURL)
1591   {
1592      this.endpointURL = endpointURL;
1593   }
1594
1595   public TypeMappingRegistry getTypeMappingRegistry()
1596   {
1597      if (tmr == null)
1598      {
1599         tmr = new TypeMappingRegistryImpl();
1600      }
1601      return tmr;
1602   }
1603
1604   public void setTypeMappingRegistry(TypeMappingRegistry tmr)
1605   {
1606      this.tmr = tmr;
1607   }
1608}
1609
Popular Tags