KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > client > Call


1 /*
2 * The Apache Software License, Version 1.1
3 *
4 *
5 * Copyright (c) 2001-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
56 package org.jboss.axis.client;
57
58 import java.net.MalformedURLException JavaDoc;
59 import java.net.URL JavaDoc;
60 import java.rmi.RemoteException JavaDoc;
61 import java.util.ArrayList JavaDoc;
62 import java.util.HashMap JavaDoc;
63 import java.util.Hashtable JavaDoc;
64 import java.util.Iterator JavaDoc;
65 import java.util.List JavaDoc;
66 import java.util.Map JavaDoc;
67 import java.util.StringTokenizer JavaDoc;
68 import java.util.Vector JavaDoc;
69
70 import javax.wsdl.Binding;
71 import javax.wsdl.BindingInput;
72 import javax.wsdl.BindingOperation;
73 import javax.wsdl.Operation;
74 import javax.wsdl.Part;
75 import javax.wsdl.Port;
76 import javax.wsdl.PortType;
77 import javax.wsdl.extensions.soap.SOAPAddress;
78 import javax.wsdl.extensions.soap.SOAPBody;
79 import javax.wsdl.extensions.soap.SOAPOperation;
80 import javax.xml.namespace.QName JavaDoc;
81 import javax.xml.rpc.JAXRPCException JavaDoc;
82 import javax.xml.rpc.ParameterMode JavaDoc;
83 import javax.xml.rpc.holders.Holder JavaDoc;
84 import javax.xml.soap.MimeHeaders JavaDoc;
85
86 import org.jboss.axis.AxisEngine;
87 import org.jboss.axis.AxisFault;
88 import org.jboss.axis.AxisProperties;
89 import org.jboss.axis.Constants;
90 import org.jboss.axis.Handler;
91 import org.jboss.axis.InternalException;
92 import org.jboss.axis.Message;
93 import org.jboss.axis.MessageContext;
94 import org.jboss.axis.attachments.Attachments;
95 import org.jboss.axis.description.FaultDesc;
96 import org.jboss.axis.description.OperationDesc;
97 import org.jboss.axis.description.ParameterDesc;
98 import org.jboss.axis.encoding.DeserializerFactory;
99 import org.jboss.axis.encoding.SerializerFactory;
100 import org.jboss.axis.encoding.TypeMapping;
101 import org.jboss.axis.encoding.TypeMappingRegistry;
102 import org.jboss.axis.encoding.XMLType;
103 import org.jboss.axis.encoding.ser.BaseDeserializerFactory;
104 import org.jboss.axis.encoding.ser.BaseSerializerFactory;
105 import org.jboss.axis.enums.Style;
106 import org.jboss.axis.enums.Use;
107 import org.jboss.axis.handlers.soap.SOAPService;
108 import org.jboss.axis.message.RPCElement;
109 import org.jboss.axis.message.RPCHeaderParam;
110 import org.jboss.axis.message.RPCParam;
111 import org.jboss.axis.message.SOAPBodyElementAxisImpl;
112 import org.jboss.axis.message.SOAPEnvelopeAxisImpl;
113 import org.jboss.axis.message.SOAPFaultImpl;
114 import org.jboss.axis.message.SOAPHeaderElementAxisImpl;
115 import org.jboss.axis.soap.SOAPConstants;
116 import org.jboss.axis.transport.http.HTTPConstants;
117 import org.jboss.axis.transport.http.HTTPTransport;
118 import org.jboss.axis.transport.java.JavaTransport;
119 import org.jboss.axis.transport.local.LocalTransport;
120 import org.jboss.axis.utils.ClassUtils;
121 import org.jboss.axis.utils.JavaUtils;
122 import org.jboss.axis.utils.Messages;
123 import org.jboss.axis.wsdl.symbolTable.BindingEntry;
124 import org.jboss.axis.wsdl.symbolTable.FaultInfo;
125 import org.jboss.axis.wsdl.symbolTable.Parameter;
126 import org.jboss.axis.wsdl.symbolTable.Parameters;
127 import org.jboss.axis.wsdl.symbolTable.SymbolTable;
128 import org.jboss.axis.wsdl.toJava.Utils;
129 import org.jboss.logging.Logger;
130
131 /**
132  * Axis' JAXRPC Dynamic Invocation Interface implementation of the Call
133  * interface. This class should be used to actually invoke the Web Service.
134  * It can be prefilled by a WSDL document (on the constructor to the Service
135  * object) or you can fill in the data yourself.
136  * <pre>
137  * Standard properties defined by in JAX-RPC's javax..xml.rpc.Call interface:
138  * USERNAME_PROPERTY - User name for authentication
139  * PASSWORD_PROPERTY - Password for authentication
140  * SESSION_PROPERTY - Participate in a session with the endpoint?
141  * OPERATION_STYLE_PROPERTY - "rpc" or "document"
142  * SOAPACTION_USE_PROPERTY - Should SOAPAction be used?
143  * SOAPACTION_URI_PROPERTY - If SOAPAction is used, this is that action
144  * ENCODING_STYLE_PROPERTY - Default is SOAP 1.1: "http://schemas.xmlsoap.org/soap/encoding/"
145  * <p/>
146  * AXIS properties:
147  * SEND_TYPE_ATTR - Should we send the XSI type attributes (true/false)
148  * TIMEOUT - Timeout used by transport sender in milliseconds
149  * TRANSPORT_NAME - Name of transport handler to use
150  * ATTACHMENT_ENCAPSULATION_FORMAT- Send attachments as MIME the default, or DIME.
151  * </pre>
152  *
153  * @author Doug Davis (dug@us.ibm.com)
154  */

155
156 public class Call implements javax.xml.rpc.Call JavaDoc
157 {
158
159    private static Logger log = Logger.getLogger(Call.class.getName());
160
161    private static Logger tlog = Logger.getLogger(Constants.TIME_LOG_CATEGORY);
162
163    private boolean parmAndRetReq = true;
164    private Service service;
165    private QName JavaDoc portName;
166    private QName JavaDoc operationName;
167
168    protected MessageContext msgContext;
169
170    // Collection of properties to store and put in MessageContext at
171
// invoke() time. Known ones are stored in actual variables for
172
// efficiency/type-consistency. Unknown ones are in myProperties.
173
private Hashtable JavaDoc myProperties = new Hashtable JavaDoc();
174    private String JavaDoc username;
175    private String JavaDoc password;
176    private boolean maintainSession;
177    private boolean useSOAPAction;
178    private String JavaDoc SOAPActionURI;
179    private Integer JavaDoc timeout;
180
181    /**
182     * Metadata for the operation associated with this Call
183     */

184    private OperationDesc operation;
185    /**
186     * This will be true if an OperationDesc is handed to us whole
187     */

188    private boolean operationSetManually;
189
190    // Is this a one-way call?
191
private boolean invokeOneWay;
192    private boolean isMsg;
193
194    // Our Transport, if any
195
private Transport transport;
196    private String JavaDoc transportName;
197
198    // A couple places to store output parameters.
199
// As a HashMap, retrievable via QName (for getOutputParams).
200
private HashMap JavaDoc outParams;
201    // As a list, retrievable by index (for getOutputValues).
202
private ArrayList JavaDoc outParamsList;
203
204    // A place to store any client-specified headers
205
private Vector JavaDoc headers;
206
207    protected Vector JavaDoc attachmentParts = new Vector JavaDoc();
208
209    public static final String JavaDoc SEND_TYPE_ATTR = "send_type_attr";
210    public static final String JavaDoc TRANSPORT_NAME = "transport_name";
211    public static final String JavaDoc TRANSPORT_PROPERTY = "java.protocol.handler.pkgs";
212
213    public static final String JavaDoc WSDL_SERVICE = "wsdl.service";
214
215    public static final String JavaDoc WSDL_PORT_NAME = "wsdl.portName";
216
217    // @deprecated use WSDL_SERVICE instead.
218
public static final String JavaDoc JAXRPC_SERVICE = WSDL_SERVICE;
219
220    // @deprected use WSDL_PORT_NAME instead.
221
public static final String JavaDoc JAXRPC_PORTTYPE_NAME = WSDL_PORT_NAME;
222
223    // If true, the code will throw a fault if there is no
224
// response message from the server. Otherwise, the
225
// invoke method will return a null.
226
public static final boolean FAULT_ON_NO_RESPONSE = false;
227
228    /**
229     * Property for setting attachment format.
230     */

231    public static final String JavaDoc ATTACHMENT_ENCAPSULATION_FORMAT =
232            "attachment_encapsulation_format";
233    /**
234     * Property value for setting attachment format as MIME.
235     */

236    public static final String JavaDoc ATTACHMENT_ENCAPSULATION_FORMAT_MIME =
237            "axis.attachment.style.mime";
238    /**
239     * Property value for setting attachment format as DIME.
240     */

241    public static final String JavaDoc ATTACHMENT_ENCAPSULATION_FORMAT_DIME =
242            "axis.attachment.style.dime";
243
244    /**
245     * A Hashtable mapping protocols (Strings) to Transports (classes)
246     */

247    private static Hashtable JavaDoc transports = new Hashtable JavaDoc();
248
249    static ParameterMode JavaDoc[] modes = new ParameterMode JavaDoc[]{null,
250                                                       ParameterMode.IN,
251                                                       ParameterMode.OUT,
252                                                       ParameterMode.INOUT};
253
254    /**
255     * This is true when someone has called setEncodingStyle()
256     */

257    private boolean encodingStyleExplicitlySet;
258    /**
259     * This is true when someone has called setOperationUse()
260     */

261    private boolean useExplicitlySet;
262
263    /************************************************************************/
264    /* Start of core JAX-RPC stuff */
265    /************************************************************************/
266
267    /**
268     * Default constructor - not much else to say.
269     */

270    public Call(Service service)
271    {
272       this.service = service;
273       maintainSession = service.getMaintainSession();
274       initialize();
275    }
276
277    /**
278     * Build a call from a URL string
279     *
280     * @param url the target endpoint URL
281     * @throws MalformedURLException
282     */

283    public Call(String JavaDoc url) throws MalformedURLException JavaDoc
284    {
285       this(new Service());
286       setTargetEndpointAddress(new URL JavaDoc(url));
287    }
288
289    /**
290     * Build a call from a URL
291     *
292     * @param url the target endpoint URL
293     */

294    public Call(URL JavaDoc url)
295    {
296       this(new Service());
297       setTargetEndpointAddress(url);
298    }
299
300    ////////////////////////////
301
//
302
// Properties and the shortcuts for common ones.
303
//
304

305    /**
306     * Allows you to set a named property to the passed in value.
307     * There are a few known properties (like username, password, etc)
308     * that are variables in Call. The rest of the properties are
309     * stored in a Hashtable. These common properties should be
310     * accessed via the accessors for speed/type safety, but they may
311     * still be obtained via this method. It's up to one of the
312     * Handlers (or the Axis engine itself) to go looking for
313     * one of them.
314     *
315     * @param name Name of the property
316     * @param value Value of the property
317     */

318    public void setProperty(String JavaDoc name, Object JavaDoc value)
319    {
320       if (name == null || value == null)
321       {
322          throw new JAXRPCException JavaDoc(Messages.getMessage(name == null ?
323                  "badProp03" : "badProp04"));
324       }
325       else if (name.equals(USERNAME_PROPERTY))
326       {
327          if (!(value instanceof String JavaDoc))
328          {
329             throw new JAXRPCException JavaDoc(Messages.getMessage("badProp00", new String JavaDoc[]{
330                name, "java.lang.String", value.getClass().getName()}));
331          }
332          setUsername((String JavaDoc)value);
333       }
334       else if (name.equals(PASSWORD_PROPERTY))
335       {
336          if (!(value instanceof String JavaDoc))
337          {
338             throw new JAXRPCException JavaDoc(Messages.getMessage("badProp00", new String JavaDoc[]{
339                name, "java.lang.String", value.getClass().getName()}));
340          }
341          setPassword((String JavaDoc)value);
342       }
343       else if (name.equals(SESSION_MAINTAIN_PROPERTY))
344       {
345          if (!(value instanceof Boolean JavaDoc))
346          {
347             throw new JAXRPCException JavaDoc(Messages.getMessage("badProp00", new String JavaDoc[]
348             {name,
349              "java.lang.Boolean",
350              value.getClass().getName()}));
351          }
352          setMaintainSession(((Boolean JavaDoc)value).booleanValue());
353       }
354       else if (name.equals(OPERATION_STYLE_PROPERTY))
355       {
356          if (!(value instanceof String JavaDoc))
357          {
358             throw new JAXRPCException JavaDoc(Messages.getMessage("badProp00", new String JavaDoc[]{
359                name, "java.lang.String", value.getClass().getName()}));
360          }
361          setOperationStyle((String JavaDoc)value);
362          if (getOperationStyle() == Style.DOCUMENT ||
363                  getOperationStyle() == Style.WRAPPED)
364          {
365             setOperationUse(Use.LITERAL_STR);
366          }
367          else if (getOperationStyle() == Style.RPC)
368          {
369             setOperationUse(Use.ENCODED_STR);
370          }
371       }
372       else if (name.equals(SOAPACTION_USE_PROPERTY))
373       {
374          if (!(value instanceof Boolean JavaDoc))
375          {
376             throw new JAXRPCException JavaDoc(Messages.getMessage("badProp00", new String JavaDoc[]
377             {name,
378              "java.lang.Boolean",
379              value.getClass().getName()}));
380          }
381          setUseSOAPAction(((Boolean JavaDoc)value).booleanValue());
382       }
383       else if (name.equals(SOAPACTION_URI_PROPERTY))
384       {
385          if (!(value instanceof String JavaDoc))
386          {
387             throw new JAXRPCException JavaDoc(Messages.getMessage("badProp00", new String JavaDoc[]
388             {name,
389              "java.lang.String",
390              value.getClass().getName()}));
391          }
392          setSOAPActionURI((String JavaDoc)value);
393       }
394       else if (name.equals(ENCODINGSTYLE_URI_PROPERTY))
395       {
396          if (!(value instanceof String JavaDoc))
397          {
398             throw new JAXRPCException JavaDoc(Messages.getMessage("badProp00", new String JavaDoc[]
399             {name,
400              "java.lang.String",
401              value.getClass().getName()}));
402          }
403          setEncodingStyle((String JavaDoc)value);
404       }
405       else if (name.equals(Stub.ENDPOINT_ADDRESS_PROPERTY))
406       {
407          if (!(value instanceof String JavaDoc))
408          {
409             throw new JAXRPCException JavaDoc(Messages.getMessage("badProp00", new String JavaDoc[]
410             {name,
411              "java.lang.String",
412              value.getClass().getName()}));
413          }
414          setTargetEndpointAddress((String JavaDoc)value);
415       }
416       else if (name.equals(TRANSPORT_NAME))
417       {
418          if (!(value instanceof String JavaDoc))
419          {
420             throw new JAXRPCException JavaDoc(Messages.getMessage("badProp00", new String JavaDoc[]{
421                name, "java.lang.String", value.getClass().getName()}));
422          }
423          transportName = (String JavaDoc)value;
424          if (transport != null)
425             transport.setTransportName((String JavaDoc)value);
426       }
427       else if (name.equals(ATTACHMENT_ENCAPSULATION_FORMAT))
428       {
429          if (!(value instanceof String JavaDoc))
430          {
431             throw new JAXRPCException JavaDoc(Messages.getMessage("badProp00", new String JavaDoc[]{
432                name, "java.lang.String", value.getClass().getName()}));
433          }
434          if (!value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_MIME) &&
435                  !value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_DIME))
436             throw new JAXRPCException JavaDoc(Messages.getMessage("badattachmenttypeerr", new String JavaDoc[]{
437                (String JavaDoc)value, ATTACHMENT_ENCAPSULATION_FORMAT_MIME + " "
438                     + ATTACHMENT_ENCAPSULATION_FORMAT_DIME}));
439       }
440       else if (name.startsWith("java.") || name.startsWith("javax."))
441       {
442          throw new JAXRPCException JavaDoc(Messages.getMessage("badProp05", name));
443       }
444       myProperties.put(name, value);
445    } // setProperty
446

447    /**
448     * Returns the value associated with the named property
449     *
450     * @return Object value of the property or null if the property is not set
451     * @throws JAXRPCException if the requested property is not a supported property
452     */

453    public Object JavaDoc getProperty(String JavaDoc name)
454    {
455       if (Stub.ENDPOINT_ADDRESS_PROPERTY.equals(name))
456       {
457          return getTargetEndpointAddress();
458       }
459       else if (!isPropertySupported(name))
460       {
461          throw new JAXRPCException JavaDoc(name == null ?
462                  Messages.getMessage("badProp03") :
463                  Messages.getMessage("badProp05", name));
464       }
465       return myProperties.get(name);
466    } // getProperty
467

468    /**
469     * Removes (if set) the named property.
470     *
471     * @param name name of the property to remove
472     */

473    public void removeProperty(String JavaDoc name)
474    {
475       if (name == null || !isPropertySupported(name))
476       {
477          throw new JAXRPCException JavaDoc(name == null ?
478                  Messages.getMessage("badProp03") :
479                  Messages.getMessage("badProp05", name));
480       }
481       myProperties.remove(name);
482    } // removeProperty
483

484    /**
485     * Set a scoped property on the call (i.e. one that propagates down into
486     * the runtime).
487     * <p/>
488     * Deprecated, since setProperty() now does the right thing here. Expect
489     * this to disappear in 1.1.
490     *
491     * @param name
492     * @param value
493     * @deprecated
494     */

495    public void setScopedProperty(String JavaDoc name, Object JavaDoc value)
496    {
497       if (name == null || value == null)
498       {
499          throw new JAXRPCException JavaDoc(Messages.getMessage(name == null ?
500                  "badProp03" : "badProp04"));
501       }
502       myProperties.put(name, value);
503    } // setScopedProperty
504

505    /**
506     * Get a scoped property (i.e. one that propagates down into the runtime).
507     * <p/>
508     * Deprecated, since there's only one property bag now. Expect this to
509     * disappear in 1.1.
510     *
511     * @param name
512     * @return
513     * @deprecated
514     */

515    public Object JavaDoc getScopedProperty(String JavaDoc name)
516    {
517       if (name != null)
518       {
519          return myProperties.get(name);
520       }
521       return null;
522    } // getScopedProperty
523

524    /**
525     * Remove a scoped property (i.e. one that propagates down into the
526     * runtime).
527     * <p/>
528     * Deprecated, since there's only one property bag now. Expect this to
529     * disappear in 1.1.
530     *
531     * @param name
532     * @deprecated
533     */

534    public void removeScopedProperty(String JavaDoc name)
535    {
536       if (name == null || myProperties == null) return;
537       myProperties.remove(name);
538    } // removeScopedProperty
539

540    /**
541     * Configurable properties supported by this Call object.
542     */

543    private static ArrayList JavaDoc propertyNames = new ArrayList JavaDoc();
544
545    static
546    {
547       propertyNames.add(USERNAME_PROPERTY);
548       propertyNames.add(PASSWORD_PROPERTY);
549       propertyNames.add(SESSION_MAINTAIN_PROPERTY);
550       propertyNames.add(ATTACHMENT_ENCAPSULATION_FORMAT);
551       propertyNames.add(OPERATION_STYLE_PROPERTY);
552       propertyNames.add(SOAPACTION_USE_PROPERTY);
553       propertyNames.add(SOAPACTION_URI_PROPERTY);
554       propertyNames.add(ENCODINGSTYLE_URI_PROPERTY);
555       propertyNames.add(TRANSPORT_NAME);
556       propertyNames.add(ATTACHMENT_ENCAPSULATION_FORMAT);
557    }
558
559    public Iterator JavaDoc getPropertyNames()
560    {
561       return propertyNames.iterator();
562    }
563
564    public boolean isPropertySupported(String JavaDoc name)
565    {
566       boolean isSupported = false;
567       if (name != null)
568       {
569          isSupported = propertyNames.contains(name) || (!name.startsWith("java.") && !name.startsWith("javax."));
570       }
571       return isSupported;
572    }
573
574    /**
575     * Set the username.
576     */

577    public void setUsername(String JavaDoc username)
578    {
579       this.username = username;
580    } // setUsername
581

582    /**
583     * Get the user name
584     */

585    public String JavaDoc getUsername()
586    {
587       return username;
588    } // getUsername
589

590    /**
591     * Set the password.
592     */

593    public void setPassword(String JavaDoc password)
594    {
595       this.password = password;
596    } // setPassword
597

598    /**
599     * Get the password
600     */

601    public String JavaDoc getPassword()
602    {
603       return password;
604    } // getPassword
605

606    /**
607     * Determine whether we'd like to track sessions or not. This
608     * overrides the default setting from the service.
609     * This just passes through the value into the MessageContext.
610     * Note: Not part of JAX-RPC specification.
611     *
612     * @param yesno true if session state is desired, false if not.
613     */

614    public void setMaintainSession(boolean yesno)
615    {
616       maintainSession = yesno;
617    }
618
619    /**
620     * Get the value of maintainSession flag.
621     */

622    public boolean getMaintainSession()
623    {
624       return maintainSession;
625    }
626
627    /**
628     * Set the operation style: "document", "rpc"
629     *
630     * @param operationStyle string designating style
631     */

632    public void setOperationStyle(String JavaDoc operationStyle)
633    {
634       Style style = Style.getStyle(operationStyle, Style.DEFAULT);
635       setOperationStyle(style);
636    } // setOperationStyle
637

638    /**
639     * Set the operation style
640     *
641     * @param operationStyle
642     */

643    public void setOperationStyle(Style operationStyle)
644    {
645       if (operation == null)
646       {
647          operation = new OperationDesc();
648       }
649
650       operation.setStyle(operationStyle);
651
652       // If no one has explicitly set the use, we should track
653
// the style. If it's non-RPC, default to LITERAL.
654
if (!useExplicitlySet)
655       {
656          if (operationStyle != Style.RPC)
657          {
658             operation.setUse(Use.LITERAL);
659          }
660       }
661
662       // If no one has explicitly set the encodingStyle, we should
663
// track the style. If it's RPC, default to SOAP-ENC, otherwise
664
// default to "".
665
if (!encodingStyleExplicitlySet)
666       {
667          String JavaDoc encStyle = "";
668          if (operationStyle == Style.RPC)
669          {
670             // RPC style defaults to encoded, otherwise default to literal
671
encStyle = getMessageContext().getSOAPConstants().getEncodingURI();
672          }
673          getMessageContext().setEncodingStyle(encStyle);
674       }
675    }
676
677    /**
678     * Get the operation style.
679     */

680    public Style getOperationStyle()
681    {
682       if (operation != null)
683       {
684          return operation.getStyle();
685       }
686       return Style.DEFAULT;
687    } // getOperationStyle
688

689    /**
690     * Set the operation use: "literal", "encoded"
691     *
692     * @param operationUse string designating use
693     */

694    public void setOperationUse(String JavaDoc operationUse)
695    {
696       Use use = Use.getUse(operationUse, Use.DEFAULT);
697       setOperationUse(use);
698    } // setOperationUse
699

700    /**
701     * Set the operation use
702     *
703     * @param operationUse
704     */

705    public void setOperationUse(Use operationUse)
706    {
707       useExplicitlySet = true;
708
709       if (operation == null)
710       {
711          operation = new OperationDesc();
712       }
713
714       operation.setUse(operationUse);
715       if (!encodingStyleExplicitlySet)
716       {
717          String JavaDoc encStyle = "";
718          if (operationUse == Use.ENCODED)
719          {
720             // RPC style defaults to encoded, otherwise default to literal
721
encStyle = getMessageContext().getSOAPConstants().getEncodingURI();
722          }
723          getMessageContext().setEncodingStyle(encStyle);
724       }
725    }
726
727    /**
728     * Get the operation use.
729     */

730    public Use getOperationUse()
731    {
732       if (operation != null)
733       {
734          return operation.getUse();
735       }
736       return Use.DEFAULT;
737    } // getOperationStyle
738

739    /**
740     * Should soapAction be used?
741     */

742    public void setUseSOAPAction(boolean useSOAPAction)
743    {
744       this.useSOAPAction = useSOAPAction;
745    } // setUseSOAPAction
746

747    /**
748     * Are we using soapAction?
749     */

750    public boolean useSOAPAction()
751    {
752       return useSOAPAction;
753    } // useSOAPAction
754

755    /**
756     * Set the soapAction URI.
757     */

758    public void setSOAPActionURI(String JavaDoc SOAPActionURI)
759            throws IllegalArgumentException JavaDoc
760    {
761       useSOAPAction = true;
762       this.SOAPActionURI = SOAPActionURI;
763    } // setSOAPActionURI
764

765    /**
766     * Get the soapAction URI.
767     */

768    public String JavaDoc getSOAPActionURI()
769    {
770       return SOAPActionURI;
771    } // getSOAPActionURI
772

773    /**
774     * Sets the encoding style to the URL passed in.
775     *
776     * @param namespaceURI URI of the encoding to use.
777     */

778    public void setEncodingStyle(String JavaDoc namespaceURI)
779    {
780       encodingStyleExplicitlySet = true;
781       getMessageContext().setEncodingStyle(namespaceURI);
782    }
783
784    /**
785     * Returns the encoding style as a URI that should be used for the SOAP
786     * message.
787     *
788     * @return String URI of the encoding style to use
789     */

790    public String JavaDoc getEncodingStyle()
791    {
792       return getMessageContext().getEncodingStyle();
793    }
794
795    /**
796     * Sets the endpoint address of the target service port. This address must
797     * correspond to the transport specified in the binding for this Call
798     * instance.
799     *
800     * @param address - Endpoint address of the target service port; specified
801     * as URI
802     */

803    public void setTargetEndpointAddress(String JavaDoc address)
804    {
805       URL JavaDoc urlAddress;
806       try
807       {
808          urlAddress = new URL JavaDoc(address);
809       }
810       catch (MalformedURLException JavaDoc mue)
811       {
812          throw new JAXRPCException JavaDoc(mue);
813       }
814       setTargetEndpointAddress(urlAddress);
815    }
816
817    /**
818     * Sets the URL of the target Web Service.
819     * <p/>
820     * Note: Not part of JAX-RPC specification.
821     *
822     * @param address URL of the target Web Service
823     */

824    public void setTargetEndpointAddress(java.net.URL JavaDoc address)
825    {
826       try
827       {
828          if (address == null)
829          {
830             setTransport(null);
831             return;
832          }
833
834          String JavaDoc protocol = address.getProtocol();
835
836          // Handle the case where the protocol is the same but we
837
// just want to change the URL - if so just set the URL,
838
// creating a new Transport object will drop all session
839
// data - and we want that stuff to persist between invoke()s.
840
// Technically the session data should be in the message
841
// context so that it can be persistent across transports
842
// as well, but for now the data is in the Transport object.
843
////////////////////////////////////////////////////////////////
844
if (this.transport != null)
845          {
846             String JavaDoc oldAddr = this.transport.getUrl();
847             if (oldAddr != null && !oldAddr.equals(""))
848             {
849                URL JavaDoc tmpURL = new URL JavaDoc(oldAddr);
850                String JavaDoc oldProto = tmpURL.getProtocol();
851                if (protocol.equals(oldProto))
852                {
853                   this.transport.setUrl(address.toString());
854                   return;
855                }
856             }
857          }
858
859          // Do we already have a transport for this address?
860
Transport transport = service.getTransportForURL(address);
861          if (transport != null)
862          {
863             setTransport(transport);
864          }
865          else
866          {
867             // We don't already have a transport for this address. Create one.
868
transport = getTransportForProtocol(protocol);
869             if (transport == null)
870                throw new AxisFault("Call.setTargetEndpointAddress",
871                        Messages.getMessage("noTransport01",
872                                protocol), null, null);
873             transport.setUrl(address.toString());
874             setTransport(transport);
875             service.registerTransportForURL(address, transport);
876          }
877       }
878       catch (Exception JavaDoc exp)
879       {
880          log.error(Messages.getMessage("exception00"), exp);
881          // do what?
882
// throw new AxisFault("Call.setTargetEndpointAddress",
883
//"Malformed URL Exception: " + e.getMessage(), null, null);
884
}
885    }
886
887    /**
888     * Returns the URL of the target Web Service.
889     *
890     * @return URL URL of the target Web Service
891     */

892    public String JavaDoc getTargetEndpointAddress()
893    {
894       try
895       {
896          if (transport == null) return (null);
897          return (transport.getUrl());
898       }
899       catch (Exception JavaDoc exp)
900       {
901          return (null);
902       }
903    }
904
905    public Integer JavaDoc getTimeout()
906    {
907       return timeout;
908    }
909
910    public void setTimeout(Integer JavaDoc timeout)
911    {
912       this.timeout = timeout;
913    }
914    //
915
// end properties code.
916
//
917
////////////////////////////
918

919    /**
920     * Is the caller required to provide the parameter and return type
921     * specification?
922     * If true, then
923     * addParameter and setReturnType MUST be called to provide the meta data.
924     * If false, then
925     * addParameter and setReturnType SHOULD NOT be called because the
926     * Call object already has the meta data describing the
927     * parameters and return type. If addParameter is called, the specified
928     * parameter is added to the end of the list of parameters.
929     */

930    public boolean isParameterAndReturnSpecRequired(QName JavaDoc operationName)
931    {
932       return parmAndRetReq;
933    } // isParameterAndReturnSpecRequired
934

935    /**
936     * Adds the specified parameter to the list of parameters for the
937     * operation associated with this Call object.
938     * <p/>
939     * Note: Not part of JAX-RPC specification.
940     *
941     * @param paramName Name that will be used for the parameter in the XML
942     * @param xmlType XMLType of the parameter
943     * @param parameterMode one of IN, OUT or INOUT
944     */

945    public void addParameter(QName JavaDoc paramName, QName JavaDoc xmlType,
946                             ParameterMode JavaDoc parameterMode)
947    {
948       Class JavaDoc javaType = null;
949       TypeMapping tm = getTypeMapping();
950       if (tm != null)
951       {
952          javaType = tm.getClassForQName(xmlType);
953       }
954       addParameter(paramName, xmlType, javaType, parameterMode);
955    }
956
957    /**
958     * Adds the specified parameter to the list of parameters for the
959     * operation associated with this Call object.
960     * <p/>
961     * <p/>
962     * Note: Not part of JAX-RPC specification.
963     *
964     * @param paramName Name that will be used for the parameter in the XML
965     * @param xmlType XMLType of the parameter
966     * @param javaType The Java class of the parameter
967     * @param parameterMode one of IN, OUT or INOUT
968     */

969    public void addParameter(QName JavaDoc paramName, QName JavaDoc xmlType,
970                             Class JavaDoc javaType, ParameterMode JavaDoc parameterMode,
971                             boolean inHeader, boolean outHeader)
972    {
973
974       if (operationSetManually)
975       {
976          throw new RuntimeException JavaDoc(Messages.getMessage("operationAlreadySet"));
977       }
978
979       if (operation == null)
980          operation = new OperationDesc();
981
982       // In order to allow any Call to be re-used, Axis
983
// chooses to allow parameters to be added when
984
// parmAndRetReq==false. This does not conflict with
985
// JSR 101 which indicates an exception MAY be thrown.
986

987       //if (parmAndRetReq) {
988
ParameterDesc param = new ParameterDesc();
989       param.setQName(paramName);
990       param.setTypeQName(xmlType);
991
992       byte mode = ParameterDesc.IN;
993       if (parameterMode == ParameterMode.INOUT)
994       {
995          mode = ParameterDesc.INOUT;
996       }
997       else if (parameterMode == ParameterMode.OUT)
998       {
999          mode = ParameterDesc.OUT;
1000      }
1001      param.setMode(mode);
1002
1003      param.setJavaType(javaType);
1004
1005      param.setInHeader(inHeader);
1006      param.setOutHeader(outHeader);
1007
1008      operation.addParameter(param);
1009      parmAndRetReq = true;
1010      //}
1011
//else {
1012
//throw new JAXRPCException(Messages.getMessage("noParmAndRetReq"));
1013
//}
1014
}
1015
1016   /**
1017    * Adds the specified parameter to the list of parameters for the
1018    * operation associated with this Call object.
1019    * <p/>
1020    * <p/>
1021    * Note: Not part of JAX-RPC specification.
1022    *
1023    * @param paramName Name that will be used for the parameter in the XML
1024    * @param xmlType XMLType of the parameter
1025    * @param javaType The Java class of the parameter
1026    * @param parameterMode one of IN, OUT or INOUT
1027    */

1028   public void addParameter(QName JavaDoc paramName, QName JavaDoc xmlType,
1029                            Class JavaDoc javaType, ParameterMode JavaDoc parameterMode)
1030   {
1031
1032      if (operationSetManually)
1033      {
1034         throw new RuntimeException JavaDoc(Messages.getMessage("operationAlreadySet"));
1035      }
1036
1037      if (operation == null)
1038         operation = new OperationDesc();
1039
1040      // In order to allow any Call to be re-used, Axis
1041
// chooses to allow parameters to be added when
1042
// parmAndRetReq==false. This does not conflict with
1043
// JSR 101 which indicates an exception MAY be thrown.
1044

1045      //if (parmAndRetReq) {
1046
ParameterDesc param = new ParameterDesc();
1047      param.setQName(paramName);
1048      param.setTypeQName(xmlType);
1049      param.setJavaType(javaType);
1050      byte mode = ParameterDesc.IN;
1051      if (parameterMode == ParameterMode.INOUT)
1052      {
1053         mode = ParameterDesc.INOUT;
1054      }
1055      else if (parameterMode == ParameterMode.OUT)
1056      {
1057         mode = ParameterDesc.OUT;
1058      }
1059      param.setMode(mode);
1060
1061      operation.addParameter(param);
1062      parmAndRetReq = true;
1063      //}
1064
//else {
1065
//throw new JAXRPCException(Messages.getMessage("noParmAndRetReq"));
1066
//}
1067
}
1068
1069   /**
1070    * Adds the specified parameter to the list of parameters for the
1071    * operation associated with this Call object.
1072    *
1073    * @param paramName Name that will be used for the parameter in the XML
1074    * @param xmlType XMLType of the parameter
1075    * @param parameterMode one of IN, OUT or INOUT
1076    */

1077   public void addParameter(String JavaDoc paramName, QName JavaDoc xmlType,
1078                            ParameterMode JavaDoc parameterMode)
1079   {
1080      Class JavaDoc javaType = null;
1081      TypeMapping tm = getTypeMapping();
1082      if (tm != null)
1083      {
1084         javaType = tm.getClassForQName(xmlType);
1085      }
1086      addParameter(new QName JavaDoc("", paramName), xmlType,
1087              javaType, parameterMode);
1088   }
1089
1090   /**
1091    * Adds a parameter type and mode for a specific operation. Note that the
1092    * client code is not required to call any addParameter and setReturnType
1093    * methods before calling the invoke method. A Call implementation class
1094    * can determine the parameter types by using the Java reflection and
1095    * configured type mapping registry.
1096    *
1097    * @param paramName - Name of the parameter
1098    * @param xmlType - XML datatype of the parameter
1099    * @param javaType - The Java class of the parameter
1100    * @param parameterMode - Mode of the parameter-whether IN, OUT or INOUT
1101    * @throws JAXRPCException - if isParameterAndReturnSpecRequired returns
1102    * false, then addParameter MAY throw
1103    * JAXRPCException....actually Axis allows
1104    * modification in such cases
1105    */

1106   public void addParameter(String JavaDoc paramName, QName JavaDoc xmlType,
1107                            Class JavaDoc javaType, ParameterMode JavaDoc parameterMode)
1108   {
1109      addParameter(new QName JavaDoc("", paramName), xmlType,
1110              javaType, parameterMode);
1111   }
1112
1113   /**
1114    * Adds a parameter type as a soap:header.
1115    *
1116    * @param paramName - Name of the parameter
1117    * @param xmlType - XML datatype of the parameter
1118    * @param javaType - The Java class of the parameter
1119    * @param parameterMode - Mode of the parameter-whether IN, OUT or INOUT
1120    * @param headerMode - Mode of the header. Even if this is an INOUT
1121    * parameter, it need not be in the header in both
1122    * directions.
1123    * @throws JAXRPCException - if isParameterAndReturnSpecRequired returns
1124    * false, then addParameter MAY throw
1125    * JAXRPCException....actually Axis allows
1126    * modification in such cases
1127    */

1128   public void addParameterAsHeader(QName JavaDoc paramName, QName JavaDoc xmlType,
1129                                    Class JavaDoc javaType, ParameterMode JavaDoc parameterMode,
1130                                    ParameterMode JavaDoc headerMode)
1131   {
1132      if (operationSetManually)
1133      {
1134         throw new RuntimeException JavaDoc(Messages.getMessage("operationAlreadySet"));
1135      }
1136
1137      if (operation == null)
1138         operation = new OperationDesc();
1139
1140      ParameterDesc param = new ParameterDesc();
1141      param.setQName(paramName);
1142      param.setTypeQName(xmlType);
1143      param.setJavaType(javaType);
1144      if (parameterMode == ParameterMode.IN)
1145      {
1146         param.setMode(ParameterDesc.IN);
1147      }
1148      else if (parameterMode == ParameterMode.INOUT)
1149      {
1150         param.setMode(ParameterDesc.INOUT);
1151      }
1152      else if (parameterMode == ParameterMode.OUT)
1153      {
1154         param.setMode(ParameterDesc.OUT);
1155      }
1156      if (headerMode == ParameterMode.IN)
1157      {
1158         param.setInHeader(true);
1159      }
1160      else if (headerMode == ParameterMode.INOUT)
1161      {
1162         param.setInHeader(true);
1163         param.setOutHeader(true);
1164      }
1165      else if (headerMode == ParameterMode.OUT)
1166      {
1167         param.setOutHeader(true);
1168      }
1169      operation.addParameter(param);
1170      parmAndRetReq = true;
1171   } // addParameterAsHeader
1172

1173   /**
1174    * Return the QName of the type of the parameters with the given name.
1175    *
1176    * @param paramName name of the parameter to return
1177    * @return XMLType XMLType of paramName, or null if not found.
1178    */

1179   public QName JavaDoc getParameterTypeByName(String JavaDoc paramName)
1180   {
1181      QName JavaDoc paramQName = new QName JavaDoc("", paramName);
1182
1183      return getParameterTypeByQName(paramQName);
1184   }
1185
1186   /**
1187    * Return the QName of the type of the parameters with the given name.
1188    * <p/>
1189    * Note: Not part of JAX-RPC specification.
1190    *
1191    * @param paramQName QName of the parameter to return
1192    * @return XMLType XMLType of paramQName, or null if not found.
1193    */

1194   public QName JavaDoc getParameterTypeByQName(QName JavaDoc paramQName)
1195   {
1196      ParameterDesc param = operation.getParamByQName(paramQName);
1197      if (param != null)
1198      {
1199         return param.getTypeQName();
1200      }
1201      return (null);
1202   }
1203
1204   /**
1205    * Sets the return type of the operation associated with this Call object.
1206    *
1207    * @param returnType QName of the return value type.
1208    */

1209   public void setReturnType(QName JavaDoc returnType)
1210   {
1211      if (operationSetManually)
1212      {
1213         throw new RuntimeException JavaDoc(Messages.getMessage("operationAlreadySet"));
1214      }
1215
1216      if (operation == null)
1217         operation = new OperationDesc();
1218
1219      // [TDI 09-Aug-2004] How do we treat anonymous names ???
1220
while (returnType != null && returnType.getLocalPart().startsWith(">"))
1221      {
1222         log.debug("Removing leading '>' from anonymous type" + returnType);
1223         returnType = new QName JavaDoc(returnType.getNamespaceURI(), returnType.getLocalPart().substring(1));
1224      }
1225
1226      // In order to allow any Call to be re-used, Axis
1227
// chooses to allow setReturnType to be changed when
1228
// parmAndRetReq==false. This does not conflict with
1229
// JSR 101 which indicates an exception MAY be thrown.
1230

1231      //if (parmAndRetReq) {
1232
operation.setReturnType(returnType);
1233      TypeMapping tm = getTypeMapping();
1234      operation.setReturnClass(tm.getClassForQName(returnType));
1235      parmAndRetReq = true;
1236      //}
1237
//else {
1238
//throw new JAXRPCException(Messages.getMessage("noParmAndRetReq"));
1239
//}
1240
}
1241
1242   /**
1243    * Sets the return type for a specific operation.
1244    *
1245    * @param xmlType - QName of the data type of the return value
1246    * @param javaType - Java class of the return value
1247    * @throws JAXRPCException - if isParameterAndReturnSpecRequired returns
1248    * false, then setReturnType MAY throw JAXRPCException...Axis allows
1249    * modification without throwing the exception.
1250    */

1251   public void setReturnType(QName JavaDoc xmlType, Class JavaDoc javaType)
1252   {
1253      setReturnType(xmlType);
1254      // Use specified type as the operation return
1255
operation.setReturnClass(javaType);
1256   }
1257
1258   /**
1259    * Set the return type as a header
1260    */

1261   public void setReturnTypeAsHeader(QName JavaDoc xmlType)
1262   {
1263      setReturnType(xmlType);
1264      operation.setReturnHeader(true);
1265   } // setReturnTypeAsHeader
1266

1267   /**
1268    * Set the return type as a header
1269    */

1270   public void setReturnTypeAsHeader(QName JavaDoc xmlType, Class JavaDoc javaType)
1271   {
1272      setReturnType(xmlType, javaType);
1273      operation.setReturnHeader(true);
1274   } // setReturnTypeAsHeader
1275

1276   /**
1277    * Returns the QName of the type of the return value of this Call - or null
1278    * if not set.
1279    * <p/>
1280    * Note: Not part of JAX-RPC specification.
1281    *
1282    * @return the XMLType specified for this Call (or null).
1283    */

1284   public QName JavaDoc getReturnType()
1285   {
1286      if (operation != null)
1287         return operation.getReturnType();
1288
1289      return null;
1290   }
1291
1292   /**
1293    * Set the QName of the return element
1294    * <p/>
1295    * NOT part of JAX-RPC
1296    */

1297   public void setReturnQName(QName JavaDoc qname)
1298   {
1299      if (operationSetManually)
1300      {
1301         throw new RuntimeException JavaDoc(Messages.getMessage("operationAlreadySet"));
1302      }
1303
1304      if (operation == null)
1305         operation = new OperationDesc();
1306
1307      operation.setReturnQName(qname);
1308   }
1309
1310   /**
1311    * Sets the desired return Java Class. This is a convenience method
1312    * which will cause the Call to automatically convert return values
1313    * into a desired class if possible. For instance, we return object
1314    * arrays by default now for SOAP arrays - you could specify:
1315    * <p/>
1316    * setReturnClass(Vector.class)
1317    * <p/>
1318    * and you'd get a Vector back from invoke() instead of having to do
1319    * the conversion yourself.
1320    * <p/>
1321    * Note: Not part of JAX-RPC specification. To be JAX-RPC compliant,
1322    * use setReturnType(QName, Class).
1323    *
1324    * @param cls the desired return class.
1325    */

1326   public void setReturnClass(Class JavaDoc cls)
1327   {
1328      if (operationSetManually)
1329      {
1330         throw new RuntimeException JavaDoc(Messages.getMessage("operationAlreadySet"));
1331      }
1332
1333      if (operation == null)
1334         operation = new OperationDesc();
1335
1336      operation.setReturnClass(cls);
1337      TypeMapping tm = getTypeMapping();
1338      operation.setReturnType(tm.getTypeQName(cls));
1339      parmAndRetReq = true;
1340   }
1341
1342   /**
1343    * Clears the list of parameters.
1344    *
1345    * @throws JAXRPCException - if isParameterAndReturnSpecRequired returns
1346    * false, then removeAllParameters MAY throw JAXRPCException...Axis allows
1347    * modification to the Call object without throwing an exception.
1348    */

1349   public void removeAllParameters()
1350   {
1351      //if (parmAndRetReq) {
1352
operation = new OperationDesc();
1353      operationSetManually = false;
1354      parmAndRetReq = true;
1355      //}
1356
//else {
1357
//throw new JAXRPCException(Messages.getMessage("noParmAndRetReq"));
1358
//}
1359
}
1360
1361   /**
1362    * Returns the operation name associated with this Call object.
1363    *
1364    * @return String Name of the operation or null if not set.
1365    */

1366   public QName JavaDoc getOperationName()
1367   {
1368      return (operationName);
1369   }
1370
1371   /**
1372    * Sets the operation name associated with this Call object. This will
1373    * not check the WSDL (if there is WSDL) to make sure that it's a valid
1374    * operation name.
1375    *
1376    * @param opName Name of the operation.
1377    */

1378   public void setOperationName(QName JavaDoc opName)
1379   {
1380      operationName = opName;
1381   }
1382
1383   /**
1384    * This is a convenience method. If the user doesn't care about the QName
1385    * of the operation, the user can call this method, which converts a String
1386    * operation name to a QName.
1387    */

1388   public void setOperationName(String JavaDoc opName)
1389   {
1390      operationName = new QName JavaDoc(opName);
1391   }
1392
1393   /**
1394    * Prefill as much info from the WSDL as it can.
1395    * Right now it's SOAPAction, operation qname, parameter types
1396    * and return type of the Web Service.
1397    * <p/>
1398    * This methods considers that port name and target endpoint address have
1399    * already been set. This is useful when you want to use the same Call
1400    * instance for several calls on the same Port
1401    * <p/>
1402    * Note: Not part of JAX-RPC specification.
1403    *
1404    * @param opName Operation(method) that's going to be invoked
1405    */

1406   public void setOperation(String JavaDoc opName)
1407   {
1408      if (service == null)
1409         throw new JAXRPCException JavaDoc(Messages.getMessage("noService04"));
1410
1411      // remove all settings concerning an operation
1412
// leave portName and targetEndPoint as they are
1413
this.setOperationName(opName);
1414      this.setEncodingStyle(null);
1415      this.setReturnType(null);
1416      this.removeAllParameters();
1417
1418      javax.wsdl.Service wsdlService = service.getWSDLService();
1419      // Nothing to do is the WSDL is not already set.
1420
if (wsdlService == null)
1421         return;
1422
1423      Port port = wsdlService.getPort(portName.getLocalPart());
1424      if (port == null)
1425         throw new JAXRPCException JavaDoc(Messages.getMessage("noPort00", "" +
1426                 portName));
1427
1428      Binding binding = port.getBinding();
1429      PortType portType = binding.getPortType();
1430      if (portType == null)
1431         throw new JAXRPCException JavaDoc(Messages.getMessage("noPortType00", "" +
1432                 portName));
1433
1434      List JavaDoc operations = portType.getOperations();
1435      if (operations == null)
1436         throw new JAXRPCException JavaDoc(Messages.getMessage("noOperation01",
1437                 opName));
1438
1439      Operation wsdlOp = null;
1440      for (int i = 0; i < operations.size(); i++, wsdlOp = null)
1441      {
1442         wsdlOp = (Operation)operations.get(i);
1443         String JavaDoc wsdlOpName = getWsdlOpName(opName);
1444         if (wsdlOp.getName().equals(wsdlOpName)) break;
1445      }
1446      if (wsdlOp == null)
1447         throw new UnsupportedOperationException JavaDoc(Messages.getMessage("noOperation01", opName));
1448
1449      // form now on, the opName is the wsdl op name
1450
opName = wsdlOp.getName();
1451
1452      // Get the SOAPAction
1453
////////////////////////////////////////////////////////////////////
1454
List JavaDoc list = port.getExtensibilityElements();
1455      String JavaDoc opStyle = null;
1456      BindingOperation bop = binding.getBindingOperation(opName,
1457              null, null);
1458      if (bop == null)
1459         throw new JAXRPCException JavaDoc(Messages.getMessage("noOperation02",
1460                 opName));
1461      list = bop.getExtensibilityElements();
1462      for (int i = 0; list != null && i < list.size(); i++)
1463      {
1464         Object JavaDoc obj = list.get(i);
1465         if (obj instanceof SOAPOperation)
1466         {
1467            SOAPOperation sop = (SOAPOperation)obj;
1468            opStyle = ((SOAPOperation)obj).getStyle();
1469            String JavaDoc action = sop.getSoapActionURI();
1470            if (action != null)
1471            {
1472               setUseSOAPAction(true);
1473               setSOAPActionURI(action);
1474            }
1475            else
1476            {
1477               setUseSOAPAction(false);
1478               setSOAPActionURI(null);
1479            }
1480            break;
1481         }
1482      }
1483
1484      // Get the body's namespace URI and encoding style
1485
////////////////////////////////////////////////////////////////////
1486
BindingInput bIn = bop.getBindingInput();
1487      if (bIn != null)
1488      {
1489         list = bIn.getExtensibilityElements();
1490         for (int i = 0; list != null && i < list.size(); i++)
1491         {
1492            Object JavaDoc obj = list.get(i);
1493            if (obj instanceof
1494                    javax.wsdl.extensions.mime.MIMEMultipartRelated)
1495            {
1496               javax.wsdl.extensions.mime.MIMEMultipartRelated mpr =
1497                       (javax.wsdl.extensions.mime.MIMEMultipartRelated)obj;
1498               Object JavaDoc part = null;
1499               List JavaDoc l = mpr.getMIMEParts();
1500               for (int j = 0; l != null && j < l.size() && part == null; j++)
1501               {
1502                  javax.wsdl.extensions.mime.MIMEPart mp
1503                          = (javax.wsdl.extensions.mime.MIMEPart)l.get(j);
1504                  List JavaDoc ll = mp.getExtensibilityElements();
1505                  for (int k = 0; ll != null && k < ll.size() && part == null;
1506                       k++)
1507                  {
1508                     part = ll.get(k);
1509                     if (!(part instanceof SOAPBody)) part = null;
1510                  }
1511               }
1512               if (null != part) obj = part;
1513            }
1514
1515            if (obj instanceof SOAPBody)
1516            {
1517               SOAPBody sBody = (SOAPBody)obj;
1518               list = sBody.getEncodingStyles();
1519               if (list != null && list.size() > 0)
1520                  this.setEncodingStyle((String JavaDoc)list.get(0));
1521               String JavaDoc ns = sBody.getNamespaceURI();
1522               if (ns != null && !ns.equals(""))
1523                  setOperationName(new QName JavaDoc(ns, opName));
1524               break;
1525            }
1526         }
1527      }
1528
1529      Service service = this.getService();
1530      SymbolTable symbolTable = service.getWSDLParser().getSymbolTable();
1531      BindingEntry bEntry = symbolTable.getBindingEntry(binding.getQName());
1532      Parameters parameters = bEntry.getParameters(bop.getOperation());
1533
1534      // loop over paramters and set up in/out params
1535
for (int j = 0; j < parameters.list.size(); ++j)
1536      {
1537         Parameter p = (Parameter)parameters.list.get(j);
1538         // Get the QName representing the parameter type
1539
QName JavaDoc paramType = Utils.getXSIType(p);
1540
1541         boolean isInHeader = p.isInHeader();
1542         boolean isOutHeader = p.isOutHeader();
1543         this.addParameter(p.getQName(), paramType, modes[p.getMode()], isInHeader, isOutHeader);
1544      }
1545
1546      Map JavaDoc faultMap = bEntry.getFaults();
1547      // Get the list of faults for this operation
1548
ArrayList JavaDoc faults = (ArrayList JavaDoc)faultMap.get(bop);
1549
1550      // check for no faults
1551
if (faults == null)
1552      {
1553         return;
1554      }
1555      // For each fault, register its information
1556
for (Iterator JavaDoc faultIt = faults.iterator(); faultIt.hasNext();)
1557      {
1558         FaultInfo info = (FaultInfo)faultIt.next();
1559         QName JavaDoc qname = info.getQName();
1560
1561         // if no parts in fault, skip it!
1562
if (qname == null)
1563         {
1564            continue;
1565         }
1566         try
1567         {
1568            Class JavaDoc clazz = getTypeMapping().getClassForQName(info.getXMLType());
1569            addFault(qname, clazz, info.getXMLType(), true);
1570         }
1571         catch (Exception JavaDoc e)
1572         {
1573            //TODO: ???
1574
}
1575      }
1576
1577      // set output type
1578
if (parameters.returnParam != null)
1579      {
1580         // Get the QName for the return Type
1581
QName JavaDoc returnType = Utils.getXSIType(parameters.returnParam);
1582         QName JavaDoc returnQName = parameters.returnParam.getQName();
1583
1584         // Get the javaType
1585
String JavaDoc javaType = null;
1586         if (parameters.returnParam.getMIMEInfo() != null)
1587         {
1588            javaType = "javax.activation.DataHandler";
1589         }
1590         else
1591         {
1592            javaType = parameters.returnParam.getType().getName();
1593         }
1594         if (javaType == null)
1595         {
1596            javaType = "";
1597         }
1598         else
1599         {
1600            javaType = javaType + ".class";
1601         }
1602         this.setReturnType(returnType);
1603         try
1604         {
1605            this.setReturnClass(ClassUtils.forName(javaType));
1606         }
1607         catch (Exception JavaDoc e)
1608         {
1609            //TODO: ???
1610
}
1611         this.setReturnQName(returnQName);
1612      }
1613      else
1614      {
1615         this.setReturnType(XMLType.AXIS_VOID);
1616      }
1617
1618      boolean hasMIME = Utils.hasMIME(bEntry, bop);
1619      Use use = bEntry.getInputBodyType(bop.getOperation());
1620      Style style = Style.getStyle(opStyle, bEntry.getBindingStyle());
1621      if (use == Use.LITERAL)
1622      {
1623         // Turn off encoding
1624
setEncodingStyle(null);
1625         // turn off XSI types
1626
setProperty(Call.SEND_TYPE_ATTR, Boolean.FALSE);
1627      }
1628      if (hasMIME || use == Use.LITERAL)
1629      {
1630         // If it is literal, turn off multirefs.
1631
//
1632
// If there are any MIME types, turn off multirefs.
1633
// I don't know enough about the guts to know why
1634
// attachments don't work with multirefs, but they don't.
1635
setProperty(AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
1636      }
1637
1638      if (style == Style.DOCUMENT && symbolTable.isWrapped())
1639      {
1640         style = Style.WRAPPED;
1641      }
1642
1643      // Operation name
1644
if (style == Style.WRAPPED)
1645      {
1646         // We need to make sure the operation name, which is what we
1647
// wrap the elements in, matches the Qname of the parameter
1648
// element.
1649
Map JavaDoc partsMap = bop.getOperation().getInput().getMessage().getParts();
1650         Part p = (Part)partsMap.values().iterator().next();
1651         QName JavaDoc q = p.getElementName();
1652         setOperationName(q);
1653      }
1654      else
1655      {
1656         QName JavaDoc elementQName =
1657                 Utils.getOperationQName(bop, bEntry, symbolTable);
1658         if (elementQName != null)
1659         {
1660            setOperationName(elementQName);
1661         }
1662      }
1663
1664      // Indicate that the parameters and return no longer
1665
// need to be specified with addParameter calls.
1666
parmAndRetReq = false;
1667      return;
1668
1669   }
1670
1671   private void addParameter(QName JavaDoc paramName, QName JavaDoc xmlType,
1672                             ParameterMode JavaDoc parameterMode, boolean inHeader, boolean outHeader)
1673   {
1674      Class JavaDoc javaType = null;
1675      TypeMapping tm = getTypeMapping();
1676      if (tm != null)
1677      {
1678         javaType = tm.getClassForQName(xmlType);
1679      }
1680
1681      if (parameterMode != ParameterMode.IN && javaType != null && !Holder JavaDoc.class.isAssignableFrom(javaType))
1682         javaType = JavaUtils.getHolderType(javaType);
1683
1684      addParameter(paramName, xmlType, javaType, parameterMode, inHeader, outHeader);
1685   }
1686
1687   /**
1688    * The default implementation simply returns the java operation name.
1689    * A ws4ee implementation would take the jaxrpc-mapping file into consideration
1690    * and return the corresponding wsdl operation name
1691    */

1692   protected String JavaDoc getWsdlOpName(String JavaDoc javaOpName)
1693   {
1694      return javaOpName;
1695   }
1696
1697   /**
1698    * prefill as much info from the WSDL as it can.
1699    * Right now it's target URL, SOAPAction, Parameter types,
1700    * and return type of the Web Service.
1701    * <p/>
1702    * If wsdl is not present, this function set port name and operation name
1703    * and does not modify target endpoint address.
1704    * <p/>
1705    * Note: Not part of JAX-RPC specification.
1706    *
1707    * @param portName PortName in the WSDL doc to search for
1708    * @param opName Operation(method) that's going to be invoked
1709    */

1710   public void setOperation(QName JavaDoc portName, String JavaDoc opName)
1711   {
1712      if (service == null)
1713         throw new JAXRPCException JavaDoc(Messages.getMessage("noService04"));
1714
1715      // Make sure we're making a fresh start.
1716
this.setPortName(portName);
1717      this.setOperationName(opName);
1718      this.setEncodingStyle(null);
1719      this.setReturnType(null);
1720      this.removeAllParameters();
1721
1722      javax.wsdl.Service wsdlService = service.getWSDLService();
1723      // Nothing to do is the WSDL is not already set.
1724
if (wsdlService == null)
1725         return;
1726
1727      // we reinitialize target endpoint only if we have wsdl
1728
this.setTargetEndpointAddress((URL JavaDoc)null);
1729
1730      Port port = wsdlService.getPort(portName.getLocalPart());
1731      if (port == null)
1732         throw new JAXRPCException JavaDoc(Messages.getMessage("noPort00", "" +
1733                 portName));
1734
1735      Binding binding = port.getBinding();
1736      PortType portType = binding.getPortType();
1737      if (portType == null)
1738         throw new JAXRPCException JavaDoc(Messages.getMessage("noPortType00", "" +
1739                 portName));
1740
1741      // Get the URL
1742
////////////////////////////////////////////////////////////////////
1743
List JavaDoc list = port.getExtensibilityElements();
1744      for (int i = 0; list != null && i < list.size(); i++)
1745      {
1746         Object JavaDoc obj = list.get(i);
1747         if (obj instanceof SOAPAddress)
1748         {
1749            try
1750            {
1751               SOAPAddress addr = (SOAPAddress)obj;
1752               URL JavaDoc url = new URL JavaDoc(addr.getLocationURI());
1753               this.setTargetEndpointAddress(url);
1754            }
1755            catch (Exception JavaDoc exp)
1756            {
1757               throw new JAXRPCException JavaDoc(Messages.getMessage("cantSetURI00", "" + exp));
1758            }
1759         }
1760      }
1761
1762      // Get the SOAPAction
1763
////////////////////////////////////////////////////////////////////
1764
BindingOperation bop = binding.getBindingOperation(opName,
1765              null, null);
1766      if (bop == null)
1767         throw new JAXRPCException JavaDoc(Messages.getMessage("noOperation02",
1768                 opName));
1769      list = bop.getExtensibilityElements();
1770      for (int i = 0; list != null && i < list.size(); i++)
1771      {
1772         Object JavaDoc obj = list.get(i);
1773         if (obj instanceof SOAPOperation)
1774         {
1775            SOAPOperation sop = (SOAPOperation)obj;
1776            String JavaDoc action = sop.getSoapActionURI();
1777            if (action != null)
1778            {
1779               setUseSOAPAction(true);
1780               setSOAPActionURI(action);
1781            }
1782            else
1783            {
1784               setUseSOAPAction(false);
1785               setSOAPActionURI(null);
1786            }
1787            break;
1788         }
1789      }
1790      setOperation(opName);
1791   }
1792
1793   /**
1794    * Returns the fully qualified name of the port for this Call object
1795    * (if there is one).
1796    *
1797    * @return QName Fully qualified name of the port (or null if not set)
1798    */

1799   public QName JavaDoc getPortName()
1800   {
1801      return (portName);
1802   } // getPortName
1803

1804   /**
1805    * Sets the port name of this Call object. This call will not set
1806    * any additional fields, nor will it do any checking to verify that
1807    * this port name is actually defined in the WSDL - for now anyway.
1808    *
1809    * @param portName Fully qualified name of the port
1810    */

1811   public void setPortName(QName JavaDoc portName)
1812   {
1813      this.portName = portName;
1814   } // setPortName
1815

1816   /**
1817    * Returns the fully qualified name of the port for this Call object
1818    * (if there is one).
1819    *
1820    * @return QName Fully qualified name of the port
1821    * @deprecated This is really the service's port name, not portType name.
1822    * Use getPortName instead.
1823    */

1824   public QName JavaDoc getPortTypeName()
1825   {
1826      return portName == null ? new QName JavaDoc("") : portName;
1827   }
1828
1829   /**
1830    * Sets the port name of this Call object. This call will not set
1831    * any additional fields, nor will it do any checking to verify that
1832    * this port type is actually defined in the WSDL - for now anyway.
1833    *
1834    * @param portType Fully qualified name of the portType
1835    * @deprecated This is really the service's port name, not portType name.
1836    * Use setPortName instead.
1837    */

1838   public void setPortTypeName(QName JavaDoc portType)
1839   {
1840      setPortName(portType);
1841   }
1842
1843   /**
1844    * Allow the user to set the default SOAP version. For SOAP 1.2, pass
1845    * SOAPConstants.SOAP12_CONSTANTS.
1846    *
1847    * @param soapConstants the SOAPConstants object representing the correct
1848    * version
1849    */

1850   public void setSOAPVersion(SOAPConstants soapConstants)
1851   {
1852      getMessageContext().setSOAPConstants(soapConstants);
1853   }
1854
1855   /**
1856    * Invokes a specific operation using a synchronous request-response interaction mode. The invoke method takes
1857    * as parameters the object values corresponding to these defined parameter types. Implementation of the invoke
1858    * method must check whether the passed parameter values correspond to the number, order and types of parameters
1859    * specified in the corresponding operation specification.
1860    *
1861    * @param operationName - Name of the operation to invoke
1862    * @param params - Parameters for this invocation
1863    * @return the value returned from the other end.
1864    * @throws java.rmi.RemoteException - if there is any error in the remote method invocation or if the Call
1865    * object is not configured properly.
1866    */

1867   public Object JavaDoc invoke(QName JavaDoc operationName, Object JavaDoc[] params)
1868           throws java.rmi.RemoteException JavaDoc
1869   {
1870      QName JavaDoc origOpName = this.operationName;
1871      this.operationName = operationName;
1872      try
1873      {
1874         return this.invoke(params);
1875      }
1876      catch (AxisFault af)
1877      {
1878         this.operationName = origOpName;
1879         if (af.detail != null && af.detail instanceof RemoteException JavaDoc)
1880         {
1881            throw ((RemoteException JavaDoc)af.detail);
1882         }
1883         throw af;
1884      }
1885      catch (java.rmi.RemoteException JavaDoc re)
1886      {
1887         this.operationName = origOpName;
1888         throw re;
1889      }
1890      catch (RuntimeException JavaDoc re)
1891      {
1892         this.operationName = origOpName;
1893         throw re;
1894      }
1895      catch (Error JavaDoc e)
1896      {
1897         this.operationName = origOpName;
1898         throw e;
1899      }
1900   } // invoke
1901

1902   /**
1903    * Invokes the operation associated with this Call object using the
1904    * passed in parameters as the arguments to the method.
1905    * <p/>
1906    * For Messaging (ie. non-RPC) the params argument should be an array
1907    * of SOAPBodyElements. <b>All</b> of them need to be SOAPBodyElements,
1908    * if any of them are not this method will default back to RPC. In the
1909    * Messaging case the return value will be a vector of SOAPBodyElements.
1910    *
1911    * @param params Array of parameters to invoke the Web Service with
1912    * @return Object Return value of the operation/method - or null
1913    * @throws java.rmi.RemoteException if there's an error
1914    */

1915   public Object JavaDoc invoke(Object JavaDoc[] params) throws java.rmi.RemoteException JavaDoc
1916   {
1917      return invokeInternal(params);
1918   }
1919
1920   private Object JavaDoc invokeInternal(Object JavaDoc[] params) throws java.rmi.RemoteException JavaDoc
1921   {
1922      long t0 = 0, t1 = 0;
1923      if (tlog.isDebugEnabled())
1924      {
1925         t0 = System.currentTimeMillis();
1926      }
1927      /* First see if we're dealing with Messaging instead of RPC. */
1928      /* If ALL of the params are SOAPBodyElements then we're doing */
1929      /* Messaging, otherwise just fall through to normal RPC processing. */
1930      /********************************************************************/
1931      SOAPEnvelopeAxisImpl env = null;
1932
1933      boolean isSOAPBodyElement = (params != null && params.length == 1 && params[0] instanceof SOAPBodyElementAxisImpl);
1934      if (isSOAPBodyElement)
1935      {
1936         /* ok, we're doing Messaging, so build up the message */
1937         /******************************************************/
1938         isMsg = true;
1939
1940         SOAPBodyElementAxisImpl sbElement = (SOAPBodyElementAxisImpl)params[0];
1941         if (sbElement.getParentElement() != null && sbElement.getParentElement().getParentElement() != null)
1942         {
1943            env = (SOAPEnvelopeAxisImpl)sbElement.getParentElement().getParentElement();
1944         }
1945         else
1946         {
1947            env = new SOAPEnvelopeAxisImpl(getMessageContext().getSOAPConstants(), getMessageContext().getSchemaVersion());
1948            env.addBodyElement(sbElement);
1949         }
1950
1951         Message msg = new Message(env);
1952         setRequestMessage(msg);
1953
1954         invoke();
1955
1956         msg = getMessageContext().getResponseMessage();
1957         if (msg == null)
1958         {
1959            if (FAULT_ON_NO_RESPONSE)
1960            {
1961               throw new AxisFault(Messages.getMessage("nullResponse00"));
1962            }
1963            else
1964            {
1965               return null;
1966            }
1967         }
1968
1969         env = msg.getSOAPEnvelope();
1970         Vector JavaDoc bodyElements = env.getBodyElements();
1971         return (bodyElements.size() > 0 ? bodyElements.get(0) : null);
1972      }
1973
1974
1975      if (operationName == null)
1976         throw new AxisFault(Messages.getMessage("noOperation00"));
1977      try
1978      {
1979         Object JavaDoc res = this.invoke(operationName.getNamespaceURI(),
1980                 operationName.getLocalPart(), params);
1981         if (tlog.isDebugEnabled())
1982         {
1983            t1 = System.currentTimeMillis();
1984            tlog.debug("axis.Call.invoke: " + (t1 - t0) + " " + operationName);
1985         }
1986         return res;
1987      }
1988      catch (AxisFault af)
1989      {
1990         if (af.detail != null && af.detail instanceof RemoteException JavaDoc)
1991         {
1992            throw ((RemoteException JavaDoc)af.detail);
1993         }
1994         throw af;
1995      }
1996      catch (RuntimeException JavaDoc ex)
1997      {
1998         throw ex;
1999      }
2000      catch (Exception JavaDoc exp)
2001      {
2002         log.debug(Messages.getMessage("toAxisFault00"), exp);
2003         throw new AxisFault(Messages.getMessage("errorInvoking00", "\n" + exp));
2004      }
2005   }
2006
2007   /**
2008    * Invokes the operation associated with this Call object using the passed
2009    * in parameters as the arguments to the method. This will return
2010    * immediately rather than waiting for the server to complete its
2011    * processing.
2012    * <p/>
2013    * NOTE: the return immediately part isn't implemented yet
2014    *
2015    * @param params Array of parameters to invoke the Web Service with
2016    * @throws JAXRPCException is there's an error
2017    */

2018   public void invokeOneWay(Object JavaDoc[] params)
2019   {
2020      try
2021      {
2022         invokeOneWay = true;
2023         invokeInternal(params);
2024      }
2025      catch (Exception JavaDoc exp)
2026      {
2027         throw new JAXRPCException JavaDoc(exp.toString());
2028      }
2029      finally
2030      {
2031         invokeOneWay = false;
2032      }
2033   }
2034
2035   /************************************************************************/
2036   /* End of core JAX-RPC stuff */
2037   /************************************************************************/
2038
2039   /**
2040    * Invoke the service with a custom SOAPEnvelope.
2041    * <p/>
2042    * Note: Not part of JAX-RPC specification.
2043    *
2044    * @param env a SOAPEnvelope to send.
2045    * @throws AxisFault
2046    */

2047   public SOAPEnvelopeAxisImpl invoke(SOAPEnvelopeAxisImpl env, MimeHeaders JavaDoc headers)
2048           throws java.rmi.RemoteException JavaDoc
2049   {
2050      try
2051      {
2052         Message msg = null;
2053
2054         msg = new Message(env, false, headers);
2055         setRequestMessage(msg);
2056         invoke();
2057         msg = getMessageContext().getResponseMessage();
2058         if (msg == null)
2059         {
2060            if (FAULT_ON_NO_RESPONSE)
2061            {
2062               throw new AxisFault(Messages.getMessage("nullResponse00"));
2063            }
2064            else
2065            {
2066               return null;
2067            }
2068         }
2069         return (msg.getSOAPEnvelope());
2070      }
2071      catch (AxisFault fault)
2072      {
2073         throw (AxisFault)fault;
2074      }
2075      catch (Exception JavaDoc ex)
2076      {
2077         log.error(Messages.getMessage("toAxisFault00"), ex);
2078         throw AxisFault.makeFault(ex);
2079      }
2080   }
2081
2082
2083   /**
2084    * Register a Transport that should be used for URLs of the specified
2085    * protocol.
2086    * <p/>
2087    * Note: Not part of JAX-RPC specification.
2088    *
2089    * @param protocol the URL protocol (i.e. "tcp" for "tcp://" urls)
2090    * @param transportClass the class of a Transport type which will be used
2091    * for matching URLs.
2092    */

2093   public static void setTransportForProtocol(String JavaDoc protocol,
2094                                              Class JavaDoc transportClass)
2095   {
2096      if (Transport.class.isAssignableFrom(transportClass))
2097         transports.put(protocol, transportClass);
2098      else
2099         throw new InternalException(transportClass.toString());
2100   }
2101
2102   /**
2103    * Set up the default transport URL mappings.
2104    * <p/>
2105    * This must be called BEFORE doing non-standard URL parsing (i.e. if you
2106    * want the system to accept a "local:" URL). This is why the Options class
2107    * calls it before parsing the command-line URL argument.
2108    * <p/>
2109    * Note: Not part of JAX-RPC specification.
2110    */

2111   public static synchronized void initialize()
2112   {
2113      addTransportPackage("transport");
2114
2115      setTransportForProtocol("java", JavaTransport.class);
2116      setTransportForProtocol("local", LocalTransport.class);
2117      setTransportForProtocol("http", HTTPTransport.class);
2118      setTransportForProtocol("https", HTTPTransport.class);
2119   }
2120
2121   /**
2122    * Cache of transport packages we've already added to the system
2123    * property.
2124    */

2125   private static ArrayList JavaDoc transportPackages = null;
2126
2127   /**
2128    * Add a package to the system protocol handler search path. This
2129    * enables users to create their own URLStreamHandler classes, and thus
2130    * allow custom protocols to be used in Axis (typically on the client
2131    * command line).
2132    * <p/>
2133    * For instance, if you add "samples.transport" to the packages property,
2134    * and have a class samples.transport.tcp.Handler, the system will be able
2135    * to parse URLs of the form "tcp://host:port..."
2136    * <p/>
2137    * Note: Not part of JAX-RPC specification.
2138    *
2139    * @param packageName the package in which to search for protocol names.
2140    */

2141   public static synchronized void addTransportPackage(String JavaDoc packageName)
2142   {
2143      if (transportPackages == null)
2144      {
2145         transportPackages = new ArrayList JavaDoc();
2146         String JavaDoc currentPackages =
2147                 AxisProperties.getProperty(TRANSPORT_PROPERTY);
2148         if (currentPackages != null)
2149         {
2150            StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(currentPackages,
2151                    "|");
2152            while (tok.hasMoreTokens())
2153            {
2154               transportPackages.add(tok.nextToken());
2155            }
2156         }
2157      }
2158
2159      if (transportPackages.contains(packageName))
2160         return;
2161
2162      transportPackages.add(packageName);
2163
2164      StringBuffer JavaDoc currentPackages = new StringBuffer JavaDoc();
2165      for (Iterator JavaDoc i = transportPackages.iterator(); i.hasNext();)
2166      {
2167         String JavaDoc thisPackage = (String JavaDoc)i.next();
2168         currentPackages.append(thisPackage);
2169         currentPackages.append('|');
2170      }
2171
2172      System.setProperty(TRANSPORT_PROPERTY, currentPackages.toString());
2173   }
2174
2175   /**
2176    * Convert the list of objects into RPCParam's based on the paramNames,
2177    * paramXMLTypes and paramModes variables. If those aren't set then just
2178    * return what was passed in.
2179    *
2180    * @param params Array of parameters to pass into the operation/method
2181    * @return Object[] Array of parameters to pass to invoke()
2182    */

2183   private Object JavaDoc[] getParamList(Object JavaDoc[] params)
2184   {
2185      int numParams = 0;
2186
2187      // If we never set-up any names... then just return what was passed in
2188
//////////////////////////////////////////////////////////////////////
2189
if (log.isDebugEnabled())
2190      {
2191         log.debug("operation=" + operation);
2192      }
2193      if (operation == null || operation.getNumParams() == 0)
2194         return (params);
2195
2196      // Count the number of IN and INOUT params, this needs to match the
2197
// number of params passed in - if not throw an error
2198
/////////////////////////////////////////////////////////////////////
2199
numParams = operation.getNumInParams();
2200
2201      // [TDI] Workaround for document style operations that don't have a parameter
2202
// http://jira.jboss.com/jira/browse/JBWS-70
2203
if (operation.getStyle() == Style.DOCUMENT && params == null && numParams == 1)
2204      {
2205         ParameterDesc param = operation.getParameter(0);
2206         Class JavaDoc javaType = param.getJavaType();
2207         if (javaType != null)
2208         {
2209            try
2210            {
2211               Object JavaDoc obj = javaType.newInstance();
2212               params = new Object JavaDoc[]{obj};
2213            }
2214            catch (Exception JavaDoc e)
2215            {
2216               log.warn("Cannot instanciate: " + javaType);
2217            }
2218         }
2219      }
2220
2221      if (params == null || numParams != params.length)
2222         throw new JAXRPCException JavaDoc("Parameter count mismatch: " + numParams);
2223
2224      log.debug("getParamList number of params: " + params.length);
2225
2226      // All ok - so now produce an array of RPCParams
2227
//////////////////////////////////////////////////
2228
Vector JavaDoc result = new Vector JavaDoc();
2229      int j = 0;
2230      ArrayList JavaDoc parameters = operation.getParameters();
2231
2232      for (int i = 0; i < parameters.size(); i++)
2233      {
2234         ParameterDesc param = (ParameterDesc)parameters.get(i);
2235         if (param.getMode() != ParameterDesc.OUT)
2236         {
2237            QName JavaDoc paramQName = param.getQName();
2238
2239            // Create an RPCParam if param isn't already an RPCParam.
2240
RPCParam rpcParam = null;
2241            Object JavaDoc p = params[j++];
2242            if (p instanceof RPCParam)
2243            {
2244               rpcParam = (RPCParam)p;
2245            }
2246            else
2247            {
2248               rpcParam = new RPCParam(paramQName.getNamespaceURI(),
2249                       paramQName.getLocalPart(),
2250                       p);
2251            }
2252            // Attach the ParameterDescription to the RPCParam
2253
// so that the serializer can use the (javaType, xmlType)
2254
// information.
2255
rpcParam.setParamDesc(param);
2256
2257            // Add the param to the header or vector depending
2258
// on whether it belongs in the header or body.
2259
if (param.isInHeader())
2260            {
2261               addHeader(new RPCHeaderParam(rpcParam));
2262            }
2263            else
2264            {
2265               result.add(rpcParam);
2266            }
2267         }
2268      }
2269      return (result.toArray());
2270   }
2271
2272   /**
2273    * Set the Transport
2274    * <p/>
2275    * Note: Not part of JAX-RPC specification.
2276    *
2277    * @param trans the Transport object we'll use to set up
2278    * MessageContext properties.
2279    */

2280   public void setTransport(Transport trans)
2281   {
2282      transport = trans;
2283      if (log.isDebugEnabled())
2284         log.debug(Messages.getMessage("transport00", "" + transport));
2285   }
2286
2287   public Object JavaDoc getTransportOption(String JavaDoc name)
2288   {
2289      return getMessageContext().getTransportOption(name);
2290   }
2291
2292   public void setTransportOption(String JavaDoc name, Object JavaDoc value)
2293   {
2294      getMessageContext().setTransportOption(name, value);
2295   }
2296
2297   /**
2298    * Get the Transport registered for the given protocol.
2299    * <p/>
2300    * Note: Not part of JAX-RPC specification.
2301    *
2302    * @param protocol a protocol such as "http" or "local" which may
2303    * have a Transport object associated with it.
2304    * @return the Transport registered for this protocol, or null if none.
2305    */

2306   public Transport getTransportForProtocol(String JavaDoc protocol)
2307   {
2308      Class JavaDoc transportClass = (Class JavaDoc)transports.get(protocol);
2309      Transport ret = null;
2310      if (transportClass != null)
2311      {
2312         try
2313         {
2314            ret = (Transport)transportClass.newInstance();
2315         }
2316         catch (InstantiationException JavaDoc e)
2317         {
2318         }
2319         catch (IllegalAccessException JavaDoc e)
2320         {
2321         }
2322      }
2323      return ret;
2324   }
2325
2326   /**
2327    * Directly set the request message in our MessageContext.
2328    * <p/>
2329    * This allows custom message creation.
2330    * <p/>
2331    * Note: Not part of JAX-RPC specification.
2332    *
2333    * @param msg the new request message.
2334    */

2335   public void setRequestMessage(Message msg)
2336   {
2337      addAttachmentParts(msg);
2338      getMessageContext().setRequestMessage(msg);
2339   }
2340
2341   /** Stub out to allow ws4ee layer to add attachments to the message
2342    */

2343   protected void addAttachmentParts(Message msg)
2344   {
2345      String JavaDoc attachformat = (String JavaDoc)getProperty(ATTACHMENT_ENCAPSULATION_FORMAT);
2346      if (attachformat != null)
2347      {
2348         Attachments attachments = msg.getAttachmentsImpl();
2349         if (attachments != null)
2350         {
2351            if (attachformat.equals(ATTACHMENT_ENCAPSULATION_FORMAT_MIME))
2352               attachments.setSendType(Attachments.SEND_TYPE_MIME);
2353            else if (attachformat.equals(ATTACHMENT_ENCAPSULATION_FORMAT_DIME))
2354               attachments.setSendType(Attachments.SEND_TYPE_DIME);
2355         }
2356      }
2357
2358      if (attachmentParts.isEmpty() == false)
2359      {
2360         try
2361         {
2362            Attachments attachments = msg.getAttachmentsImpl();
2363            if (attachments != null)
2364               attachments.setAttachmentParts(attachmentParts);
2365         }
2366         catch (AxisFault ex)
2367         {
2368            log.info(Messages.getMessage("axisFault00"), ex);
2369            throw new RuntimeException JavaDoc(ex.getMessage());
2370         }
2371      }
2372      attachmentParts.clear();
2373   }
2374
2375   /**
2376    * Directly get the response message in our MessageContext.
2377    * <p/>
2378    * Shortcut for having to go thru the msgContext
2379    * <p/>
2380    * Note: Not part of JAX-RPC specification.
2381    *
2382    * @return the response Message object in the msgContext
2383    */

2384   public Message getResponseMessage()
2385   {
2386      return getMessageContext().getResponseMessage();
2387   }
2388
2389   /**
2390    * Obtain a reference to our MessageContext.
2391    * <p/>
2392    * Note: Not part of JAX-RPC specification.
2393    *
2394    * @return the MessageContext.
2395    */

2396   public MessageContext getMessageContext()
2397   {
2398      if (msgContext == null)
2399         msgContext = new MessageContext(service.getEngine());
2400
2401      return msgContext;
2402   }
2403
2404   /**
2405    * Add a header which should be inserted into each outgoing message
2406    * we generate.
2407    * <p/>
2408    * Note: Not part of JAX-RPC specification.
2409    *
2410    * @param header a SOAPHeaderElement to be inserted into messages
2411    */

2412   public void addHeader(SOAPHeaderElementAxisImpl header)
2413   {
2414      if (headers == null)
2415      {
2416         headers = new Vector JavaDoc();
2417      }
2418      headers.add(header);
2419   }
2420
2421   /**
2422    * Clear the list of headers which we insert into each message
2423    * <p/>
2424    * Note: Not part of JAX-RPC specification.
2425    */

2426   public void clearHeaders()
2427   {
2428      headers = null;
2429   }
2430
2431   public TypeMapping getTypeMapping()
2432   {
2433      // Get the TypeMappingRegistry
2434
TypeMappingRegistry tmr = getMessageContext().getTypeMappingRegistry();
2435
2436      // If a TypeMapping is not available, add one.
2437
return tmr.getOrMakeTypeMapping(getEncodingStyle());
2438   }
2439
2440   /**
2441    * Register type mapping information for serialization/deserialization
2442    * <p/>
2443    * Note: Not part of JAX-RPC specification.
2444    *
2445    * @param javaType is the Java class of the data type.
2446    * @param xmlType the xsi:type QName of the associated XML type.
2447    * @param sf/df are the factories (or the Class objects of the factory).
2448    */

2449   public void registerTypeMapping(Class JavaDoc javaType, QName JavaDoc xmlType,
2450                                   SerializerFactory sf,
2451                                   DeserializerFactory df)
2452   {
2453      registerTypeMapping(javaType, xmlType, sf, df, true);
2454   }
2455
2456   /**
2457    * Register type mapping information for serialization/deserialization
2458    * <p/>
2459    * Note: Not part of JAX-RPC specification.
2460    *
2461    * @param javaType is the Java class of the data type.
2462    * @param xmlType the xsi:type QName of the associated XML type.
2463    * @param sf/df are the factories (or the Class objects of the factory).
2464    * @param force Indicates whether to add the information if already registered.
2465    */

2466   public void registerTypeMapping(Class JavaDoc javaType, QName JavaDoc xmlType,
2467                                   SerializerFactory sf,
2468                                   DeserializerFactory df,
2469                                   boolean force)
2470   {
2471      TypeMapping tm = getTypeMapping();
2472      if (!force && tm.isRegistered(javaType, xmlType))
2473         return;
2474
2475      // Register the information
2476
tm.register(javaType, xmlType, sf, df);
2477   }
2478
2479   public void registerTypeMapping(Class JavaDoc javaType, QName JavaDoc xmlType,
2480                                   Class JavaDoc sfClass, Class JavaDoc dfClass)
2481   {
2482      registerTypeMapping(javaType, xmlType, sfClass, dfClass, true);
2483   }
2484
2485   public void registerTypeMapping(Class JavaDoc javaType,
2486                                   QName JavaDoc xmlType,
2487                                   Class JavaDoc sfClass,
2488                                   Class JavaDoc dfClass,
2489                                   boolean force)
2490   {
2491      // Instantiate the factory using introspection.
2492
SerializerFactory sf =
2493              BaseSerializerFactory.createFactory(sfClass, javaType, xmlType);
2494      DeserializerFactory df =
2495              BaseDeserializerFactory.createFactory(dfClass,
2496                      javaType,
2497                      xmlType);
2498      if (sf != null || df != null)
2499      {
2500         registerTypeMapping(javaType, xmlType, sf, df, force);
2501      }
2502   }
2503
2504   /************************************************
2505    * Invocation
2506    */

2507
2508   /**
2509    * Invoke an RPC service with a method name and arguments.
2510    * <p/>
2511    * This will call the service, serializing all the arguments, and
2512    * then deserialize the return value.
2513    * <p/>
2514    * Note: Not part of JAX-RPC specification.
2515    *
2516    * @param namespace the desired namespace URI of the method element
2517    * @param method the method name
2518    * @param args an array of Objects representing the arguments to the
2519    * invoked method. If any of these objects are RPCParams,
2520    * Axis will use the embedded name of the RPCParam as the
2521    * name of the parameter. Otherwise, we will serialize
2522    * each argument as an XML element called "arg<n>".
2523    * @return a deserialized Java Object containing the return value
2524    * @throws AxisFault
2525    */

2526   public Object JavaDoc invoke(String JavaDoc namespace, String JavaDoc method, Object JavaDoc[] args)
2527           throws AxisFault
2528   {
2529
2530      if (log.isDebugEnabled())
2531      {
2532         log.debug("Enter: Call::invoke(ns, meth, args)");
2533      }
2534
2535      /**
2536       * Since JAX-RPC requires us to specify all or nothing, if setReturnType
2537       * was called (returnType != null) and we have args but addParameter
2538       * wasn't called (paramXMLTypes == null), then toss a fault.
2539       */

2540      if (getReturnType() != null && args != null && args.length != 0
2541              && operation.getNumParams() == 0)
2542      {
2543         throw new AxisFault(Messages.getMessage("mustSpecifyParms"));
2544      }
2545
2546      RPCElement body = new RPCElement(namespace, method, getParamList(args));
2547
2548      Object JavaDoc ret = invoke(body);
2549
2550      if (log.isDebugEnabled())
2551      {
2552         log.debug("Exit: Call::invoke(ns, meth, args)");
2553      }
2554
2555      return ret;
2556   }
2557
2558   /**
2559    * Convenience method to invoke a method with a default (empty)
2560    * namespace. Calls invoke() above.
2561    * <p/>
2562    * Note: Not part of JAX-RPC specification.
2563    *
2564    * @param method the method name
2565    * @param args an array of Objects representing the arguments to the
2566    * invoked method. If any of these objects are RPCParams,
2567    * Axis will use the embedded name of the RPCParam as the
2568    * name of the parameter. Otherwise, we will serialize
2569    * each argument as an XML element called "arg<n>".
2570    * @return a deserialized Java Object containing the return value
2571    * @throws AxisFault
2572    */

2573   public Object JavaDoc invoke(String JavaDoc method, Object JavaDoc[] args) throws AxisFault
2574   {
2575      return invoke("", method, args);
2576   }
2577
2578   /**
2579    * Invoke an RPC service with a pre-constructed RPCElement.
2580    * <p/>
2581    * Note: Not part of JAX-RPC specification.
2582    *
2583    * @param body an RPCElement containing all the information about
2584    * this call.
2585    * @return a deserialized Java Object containing the return value
2586    * @throws AxisFault
2587    */

2588   public Object JavaDoc invoke(RPCElement body) throws AxisFault
2589   {
2590
2591      if (log.isDebugEnabled())
2592      {
2593         log.debug("Enter: Call::invoke(RPCElement)");
2594      }
2595
2596      /**
2597       * Since JAX-RPC requires us to specify a return type if we've set
2598       * parameter types, check for this case right now and toss a fault
2599       * if things don't look right.
2600       */

2601      if (!invokeOneWay && operation != null &&
2602              operation.getNumParams() > 0 && getReturnType() == null)
2603      {
2604         // TCK:
2605
// Issue an error if the return type was not set, but continue processing.
2606
//throw new AxisFault(Messages.getMessage("mustSpecifyReturnType"));
2607
log.error(Messages.getMessage("mustSpecifyReturnType"));
2608      }
2609
2610      SOAPEnvelopeAxisImpl reqEnv =
2611              new SOAPEnvelopeAxisImpl(getMessageContext().getSOAPConstants(),
2612                      getMessageContext().getSchemaVersion());
2613      SOAPEnvelopeAxisImpl resEnv = null;
2614      Message reqMsg = new Message(reqEnv);
2615      Message resMsg = null;
2616      Vector JavaDoc resArgs = null;
2617      Object JavaDoc result = null;
2618
2619      try
2620      {
2621         // Set the encoding style - in contradiction to BP-1.0/R1005
2622
// s1as interop tests expect this to be set in the <env:Body>
2623
// [TDI 11-Sep-2004]
2624
String JavaDoc encodingStyle = getEncodingStyle();
2625         String JavaDoc bodyEncStyle = reqEnv.getBody().getEncodingStyle();
2626         if (bodyEncStyle.equals(encodingStyle) == false)
2627         {
2628            if (bodyEncStyle.equals(""))
2629               reqEnv.getBody().setEncodingStyle(encodingStyle);
2630            else
2631               log.warn("Mixed encoding styles are not supported: " + bodyEncStyle + "!=" + encodingStyle);
2632         }
2633
2634         setRequestMessage(reqMsg);
2635
2636         reqEnv.addBodyElement(body);
2637         reqEnv.setMessageType(Message.REQUEST);
2638
2639         invoke();
2640      }
2641      catch (Exception JavaDoc e)
2642      {
2643         log.debug(Messages.getMessage("toAxisFault00"), e);
2644         throw AxisFault.makeFault(e);
2645      }
2646
2647      resMsg = getMessageContext().getResponseMessage();
2648
2649      if (resMsg == null)
2650      {
2651         if (FAULT_ON_NO_RESPONSE)
2652         {
2653            throw new AxisFault(Messages.getMessage("nullResponse00"));
2654         }
2655         else
2656         {
2657            return null;
2658         }
2659      }
2660
2661      resEnv = resMsg.getSOAPEnvelope();
2662      SOAPBodyElementAxisImpl bodyEl = resEnv.getFirstBody();
2663      if (bodyEl == null)
2664      {
2665         return null;
2666      }
2667
2668      if (bodyEl instanceof RPCElement)
2669      {
2670         try
2671         {
2672            resArgs = ((RPCElement)bodyEl).getParams();
2673         }
2674         catch (Exception JavaDoc e)
2675         {
2676            log.error(Messages.getMessage("exception00"), e);
2677            throw AxisFault.makeFault(e);
2678         }
2679
2680         if (resArgs != null && resArgs.size() > 0)
2681         {
2682
2683            // If there is no return, then we start at index 0 to create the outParams Map.
2684
// If there IS a return, then we start with 1.
2685
int outParamStart = 0;
2686
2687            // If we have resArgs and the returnType is specified, then the first
2688
// resArgs is the return. If we have resArgs and neither returnType
2689
// nor paramXMLTypes are specified, then we assume that the caller is
2690
// following the non-JAX-RPC AXIS shortcut of not having to specify
2691
// the return, in which case we again assume the first resArgs is
2692
// the return.
2693
// NOTE 1: the non-JAX-RPC AXIS shortcut allows a potential error
2694
// to escape notice. If the caller IS NOT following the non-JAX-RPC
2695
// shortcut but instead intentionally leaves returnType and params
2696
// null (ie., a method that takes no parameters and returns nothing)
2697
// then, if we DO receive something it should be an error, but this
2698
// code passes it through. The ideal solution here is to require
2699
// this caller to set the returnType to void, but there's no void
2700
// type in XML.
2701
// NOTE 2: we should probably verify that the resArgs element
2702
// types match the expected returnType and paramXMLTypes, but I'm not
2703
// sure how to do that since the resArgs value is a Java Object
2704
// and the returnType and paramXMLTypes are QNames.
2705

2706            // GD 03/15/02 : We're now checking for invalid metadata
2707
// config at the top of this method, so don't need to do it
2708
// here. Check for void return, though.
2709

2710            boolean findReturnParam = false;
2711            QName JavaDoc returnParamQName = null;
2712            if (operation != null)
2713               returnParamQName = operation.getReturnQName();
2714
2715            if (!XMLType.AXIS_VOID.equals(getReturnType()))
2716            {
2717               if (returnParamQName == null)
2718               {
2719                  // Assume the first param is the return
2720
RPCParam param = (RPCParam)resArgs.get(0);
2721                  result = param.getValue();
2722                  outParamStart = 1;
2723               }
2724               else
2725               {
2726                  // If the QName of the return value was given to us, look
2727
// through the result arguments to find the right name
2728
findReturnParam = true;
2729               }
2730            }
2731
2732            // The following loop looks at the resargs and
2733
// converts the value to the appropriate return/out parameter
2734
// value. If the return value is found, is value is
2735
// placed in result. The remaining resargs are
2736
// placed in the outParams list (note that if a resArg
2737
// is found that does not match a operation parameter qname,
2738
// it is still placed in the outParms list).
2739
for (int i = outParamStart; i < resArgs.size(); i++)
2740            {
2741               RPCParam param = (RPCParam)resArgs.get(i);
2742
2743               Class JavaDoc javaType = getJavaTypeForQName(param.getQName());
2744               Object JavaDoc value = param.getValue();
2745
2746               // Convert type if needed
2747
if (javaType != null && value != null &&
2748                       !javaType.isAssignableFrom(value.getClass()))
2749               {
2750                  value = JavaUtils.convert(value, javaType);
2751               }
2752
2753               //Convert in to proper array type if elements all of same
2754
if (javaType == null && value != null)
2755               {
2756
2757                  //This is a hack due to the array type of unknown types being Object[]
2758
if (value.getClass().isArray())
2759                  {
2760                     if (!value.getClass().getComponentType().isPrimitive())
2761                     {
2762                        int len = java.lang.reflect.Array.getLength(value);
2763                        Class JavaDoc type = null;
2764                        for (int x = 0; x < len; x++)
2765                        {
2766                           Object JavaDoc o = java.lang.reflect.Array.get(value, x);
2767                           if (o != null)
2768                           {
2769                              if (type == null)
2770                              {
2771                                 //TODO - if this works, need to then add code to handle arrays of arrays
2772
type = o.getClass();
2773                              }
2774                              else
2775                              {
2776                                 if (!type.getName().equals(o.getClass().getName()))
2777                                 {
2778                                    type = null;
2779                                    break;
2780                                 }
2781                              }
2782                           }
2783                        }
2784                        // did we find that all elements were of same type
2785
if (type != null)
2786                        {
2787                           Object JavaDoc convertedArray = java.lang.reflect.Array.newInstance(type, len);
2788                           System.arraycopy(value, 0, convertedArray, 0, len);
2789                           value = convertedArray;
2790                        }
2791                     }
2792                  }
2793               }
2794
2795               // Check if this parameter is our return
2796
// otherwise just add it to our outputs
2797
if (findReturnParam && returnParamQName.equals(param.getQName()))
2798               {
2799                  // found it!
2800
result = value;
2801                  findReturnParam = false;
2802               }
2803               else
2804               {
2805                  outParams.put(param.getQName(), value);
2806                  outParamsList.add(value);
2807               }
2808            }
2809
2810            // added by scheu:
2811
// If the return param is still not found, that means
2812
// the returned value did not have the expected qname.
2813
// The soap specification indicates that this should be
2814
// accepted (and we also fail interop tests if we are strict here).
2815
// Look through the outParms and find one that
2816
// does not match one of the operation parameters.
2817
if (findReturnParam)
2818            {
2819               Iterator JavaDoc it = outParams.keySet().iterator();
2820               while (it.hasNext() && findReturnParam)
2821               {
2822                  QName JavaDoc qname = (QName JavaDoc)it.next();
2823                  ParameterDesc paramDesc = operation.getOutputParamByQName(qname);
2824                  if (paramDesc == null)
2825                  {
2826                     // Doesn't match a paramter, so use this for the return
2827
findReturnParam = false;
2828                     result = outParams.remove(qname);
2829                  }
2830               }
2831            }
2832
2833            // If we were looking for a particular QName for the return and
2834
// still didn't find it, throw an exception
2835
if (findReturnParam)
2836            {
2837               String JavaDoc returnParamName = returnParamQName.toString();
2838               throw new AxisFault(Messages.getMessage("noReturnParam",
2839                       returnParamName));
2840            }
2841         }
2842      }
2843      else
2844      {
2845         // This is a SOAPBodyElement, try to treat it like a return value
2846
try
2847         {
2848            result = bodyEl.getValueAsType(getReturnType());
2849         }
2850         catch (Exception JavaDoc e)
2851         {
2852            // just return the SOAPElement
2853
result = bodyEl;
2854         }
2855
2856      }
2857
2858      if (log.isDebugEnabled())
2859      {
2860         log.debug("Exit: Call::invoke(RPCElement)");
2861      }
2862
2863      // Convert type if needed
2864
if (operation != null && operation.getReturnClass() != null)
2865      {
2866         result = JavaUtils.convert(result, operation.getReturnClass());
2867      }
2868
2869      return (result);
2870   }
2871
2872   /**
2873    * Get the javaType for a given parameter.
2874    */

2875   private Class JavaDoc getJavaTypeForQName(QName JavaDoc name)
2876   {
2877
2878      if (operation == null) return null;
2879
2880      Class JavaDoc javaType = null;
2881
2882      ParameterDesc param = operation.getOutputParamByQName(name);
2883      if (param != null)
2884      {
2885         javaType = param.getJavaType();
2886         log.debug("getJavaTypeForQName: " + name + " -> " + javaType);
2887      }
2888      else
2889      {
2890         log.debug("No output parameter for name: " + name);
2891      }
2892
2893      return javaType;
2894   }
2895
2896   /**
2897    * Set engine option.
2898    * <p/>
2899    * Note: Not part of JAX-RPC specification.
2900    */

2901   public void setOption(String JavaDoc name, Object JavaDoc value)
2902   {
2903      service.getEngine().setOption(name, value);
2904   }
2905
2906   /**
2907    * Invoke this Call with its established MessageContext
2908    * (perhaps because you called this.setRequestMessage())
2909    * <p/>
2910    * Note: Not part of JAX-RPC specification.
2911    *
2912    * @throws AxisFault
2913    */

2914   public void invoke() throws AxisFault
2915   {
2916      if (log.isDebugEnabled())
2917      {
2918         log.debug("Enter: Call::invoke()");
2919      }
2920
2921      // Clear the output params
2922
outParams = new HashMap JavaDoc();
2923      outParamsList = new ArrayList JavaDoc();
2924
2925      Message reqMsg = null;
2926      SOAPEnvelopeAxisImpl reqEnv = null;
2927
2928      getMessageContext().reset();
2929      getMessageContext().setResponseMessage(null);
2930      getMessageContext().setProperty(MessageContext.CALL, this);
2931      getMessageContext().setProperty(WSDL_SERVICE, service);
2932      getMessageContext().setProperty(WSDL_PORT_NAME, getPortName());
2933      if (isMsg)
2934         getMessageContext().setProperty(MessageContext.IS_MSG, "true");
2935
2936      if (username != null)
2937      {
2938         getMessageContext().setUsername(username);
2939      }
2940      if (password != null)
2941      {
2942         getMessageContext().setPassword(password);
2943      }
2944      getMessageContext().setMaintainSession(maintainSession);
2945
2946      if (operation != null)
2947      {
2948         getMessageContext().setOperation(operation);
2949
2950         operation.setStyle(getOperationStyle());
2951         operation.setUse(getOperationUse());
2952      }
2953
2954      if (useSOAPAction)
2955      {
2956         getMessageContext().setUseSOAPAction(true);
2957      }
2958      if (SOAPActionURI != null)
2959      {
2960         getMessageContext().setSOAPActionURI(SOAPActionURI);
2961      }
2962      if (timeout != null)
2963      {
2964         getMessageContext().setTimeout(timeout.intValue());
2965      }
2966
2967      // Determine client target service
2968
if (myService != null)
2969      {
2970         // If we have a SOAPService kicking around, use that directly
2971
getMessageContext().setService(myService);
2972      }
2973      else
2974      {
2975         if (portName != null)
2976         {
2977            // No explicit service. If we have a target service name,
2978
// try that.
2979
getMessageContext().setTargetService(portName.getLocalPart());
2980         }
2981         else
2982         {
2983            // No direct config, so try the namespace of the first body.
2984
reqMsg = getMessageContext().getRequestMessage();
2985
2986            if (reqMsg != null)
2987            {
2988               reqEnv = reqMsg.getSOAPEnvelope();
2989
2990               SOAPBodyElementAxisImpl body = reqEnv.getFirstBody();
2991
2992               if (body != null)
2993               {
2994                  if (body.getNamespaceURI() == null)
2995                  {
2996                     throw new AxisFault("Call.invoke",
2997                             Messages.getMessage("cantInvoke00", body.getName()),
2998                             null, null);
2999                  }
3000                  else
3001                  {
3002                     getMessageContext().setTargetService(body.getNamespaceURI());
3003                  }
3004               }
3005            }
3006         }
3007
3008         SOAPService svc = getMessageContext().getService();
3009         if (svc != null)
3010         {
3011            svc.setPropertyParent(myProperties);
3012         }
3013         else
3014         {
3015            getMessageContext().setPropertyParent(myProperties);
3016         }
3017      }
3018      if (log.isDebugEnabled())
3019      {
3020         log.debug(Messages.getMessage("targetService",
3021                 getMessageContext().getTargetService()));
3022      }
3023
3024      Message requestMessage = getMessageContext().getRequestMessage();
3025      if (requestMessage != null)
3026      {
3027         reqEnv = requestMessage.getSOAPEnvelope();
3028
3029         // If we have headers to insert, do so now.
3030
for (int i = 0; headers != null && i < headers.size(); i++)
3031         {
3032            SOAPHeaderElementAxisImpl header = (SOAPHeaderElementAxisImpl)headers.get(i);
3033            reqEnv.addHeader(header);
3034         }
3035      }
3036
3037      // set up transport if there is one
3038
if (transport != null)
3039      {
3040         transport.setupMessageContext(msgContext, this, service.getEngine());
3041      }
3042      else
3043      {
3044         getMessageContext().setTransportName(transportName);
3045      }
3046
3047      if (!invokeOneWay)
3048      {
3049         invokeEngine(msgContext);
3050      }
3051      else
3052      {
3053         invokeEngineOneWay(msgContext);
3054      }
3055
3056      if (log.isDebugEnabled())
3057      {
3058         log.debug("Exit: Call::invoke()");
3059      }
3060   }
3061
3062   private void invokeEngine(MessageContext msgContext) throws AxisFault
3063   {
3064      service.getEngine().invoke(msgContext);
3065
3066      if (transport != null)
3067         transport.processReturnedMessageContext(msgContext);
3068
3069      Message resMsg = getMessageContext().getResponseMessage();
3070
3071      if (resMsg == null)
3072      {
3073         if (FAULT_ON_NO_RESPONSE)
3074         {
3075            throw new AxisFault(Messages.getMessage("nullResponse00"));
3076         }
3077         else
3078         {
3079            return;
3080         }
3081      }
3082
3083      /** This must happen before deserialization...
3084       */

3085      resMsg.setMessageType(Message.RESPONSE);
3086
3087      SOAPEnvelopeAxisImpl resEnv = resMsg.getSOAPEnvelope();
3088
3089      SOAPBodyElementAxisImpl respBody = resEnv.getFirstBody();
3090      if (respBody instanceof SOAPFaultImpl)
3091      {
3092         if (operation == null ||
3093                 operation.getReturnClass() == null ||
3094                 operation.getReturnClass() !=
3095                 javax.xml.soap.SOAPMessage JavaDoc.class)
3096            throw ((SOAPFaultImpl)respBody).getFault();
3097      }
3098   }
3099
3100   private void invokeEngineOneWay(final MessageContext msgContext)
3101   {
3102      Runnable JavaDoc runnable = new Runnable JavaDoc()
3103      {
3104         public void run()
3105         {
3106            try
3107            {
3108               service.getEngine().invoke(msgContext);
3109            }
3110            catch (AxisFault af)
3111            {
3112               log.debug(Messages.getMessage("exceptionPrinting"), af);
3113            }
3114         }
3115      };
3116      Thread JavaDoc thread = new Thread JavaDoc(runnable);
3117      thread.start();
3118   }
3119
3120   /**
3121    * Get the output parameters (if any) from the last invocation.
3122    * <p/>
3123    * NOTE that the params returned are all RPCParams, containing
3124    * name and value - if you want the value, you'll need to call
3125    * param.getValue().
3126    *
3127    * @return Vector of RPCParams
3128    */

3129   public Map JavaDoc getOutputParams()
3130   {
3131      if (outParams != null)
3132      {
3133         return outParams;
3134      }
3135      else
3136      {
3137         // per 8.2.4.1 section of JSR 101 (JAXRPC 1.1), version 1.1 spec
3138
throw new JAXRPCException JavaDoc("Cannot get output parameters before invoke is called.");
3139      }
3140   }
3141
3142   /**
3143    * Returns a List values for the output parameters of the last
3144    * invoked operation.
3145    *
3146    * @return Values for the output parameters. An empty List is
3147    * returned if there are no output values.
3148    * @throws JAXRPCException - If this method is invoked for a
3149    * one-way operation or is invoked
3150    * before any invoke method has been called.
3151    */

3152   public List JavaDoc getOutputValues()
3153   {
3154      return outParamsList;
3155   }
3156
3157   /**
3158    * Get the Service object associated with this Call object.
3159    * <p/>
3160    * Note: Not part of JAX-RPC specification.
3161    *
3162    * @return Service the Service object this Call object is associated with
3163    */

3164   public Service getService()
3165   {
3166      return this.service;
3167   }
3168
3169   private SOAPService myService = null;
3170
3171   /**
3172    *
3173    */

3174   public void setSOAPService(SOAPService service)
3175   {
3176      myService = service;
3177      if (service != null)
3178      {
3179         // Set the service so that it defers missing property gets to the
3180
// Call. So when client-side Handlers get at the MessageContext,
3181
// the property scoping will be MC -> SOAPService -> Call
3182
service.setPropertyParent(myProperties);
3183         service.setEngine(this.service.getAxisClient());
3184      }
3185   }
3186
3187   /**
3188    * Sets the client-side request and response Handlers. This is handy
3189    * for programatically setting up client-side work without deploying
3190    * via WSDD or the EngineConfiguration mechanism.
3191    */

3192   public void setClientHandlers(Handler reqHandler, Handler respHandler)
3193   {
3194      // Create a SOAPService which will be used as the client-side service
3195
// handler.
3196
setSOAPService(new SOAPService(reqHandler, null, respHandler));
3197   }
3198
3199   /**
3200    * This method adds an attachment.
3201    * <p/>
3202    * Note: Not part of JAX-RPC specification.
3203    *
3204    * @throws RuntimeException if there is no support for attachments.
3205    */

3206   public void addAttachmentPart(Object JavaDoc attachment)
3207   {
3208      attachmentParts.add(attachment);
3209   }
3210
3211   /**
3212    * Add a fault for this operation
3213    * <p/>
3214    * Note: Not part of JAX-RPC specificaion
3215    */

3216   public void addFault(QName JavaDoc qname, Class JavaDoc cls,
3217                        QName JavaDoc xmlType, boolean isComplex)
3218   {
3219      if (operationSetManually)
3220      {
3221         throw new RuntimeException JavaDoc(Messages.getMessage("operationAlreadySet"));
3222      }
3223
3224      if (operation == null)
3225         operation = new OperationDesc();
3226
3227      FaultDesc fault = new FaultDesc();
3228      fault.setQName(qname);
3229      fault.setClassName(cls.getName());
3230      fault.setXmlType(xmlType);
3231      fault.setComplex(isComplex);
3232      operation.addFault(fault);
3233   }
3234
3235   /**
3236    * Hand a complete OperationDesc to the Call, and note that this was
3237    * done so that others don't try to mess with it by calling addParameter,
3238    * setReturnType, etc.
3239    *
3240    * @param operation the OperationDesc to associate with this call.
3241    */

3242   public void setOperation(OperationDesc operation)
3243   {
3244      this.operation = operation;
3245      operationSetManually = true;
3246   }
3247
3248   public OperationDesc getOperation()
3249   {
3250      return operation;
3251   }
3252
3253   public void clearOperation()
3254   {
3255      operation = null;
3256      operationSetManually = false;
3257   }
3258}
3259
Popular Tags