Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/axis/client/Call.java


1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.axis.client ;
18  
19  import org.apache.axis.AxisFault;
20  import org.apache.axis.AxisProperties;
21  import org.apache.axis.Constants;
22  import org.apache.axis.Handler;
23  import org.apache.axis.InternalException;
24  import org.apache.axis.Message;
25  import org.apache.axis.MessageContext;
26  import org.apache.axis.AxisEngine;
27  import org.apache.axis.SOAPPart;
28  import org.apache.axis.attachments.Attachments;
29  import org.apache.axis.components.logger.LogFactory;
30  import org.apache.axis.description.FaultDesc;
31  import org.apache.axis.description.OperationDesc;
32  import org.apache.axis.description.ParameterDesc;
33  import org.apache.axis.encoding.DeserializerFactory;
34  import org.apache.axis.encoding.SerializationContext;
35  import org.apache.axis.encoding.SerializerFactory;
36  import org.apache.axis.encoding.TypeMapping;
37  import org.apache.axis.encoding.TypeMappingRegistry;
38  import org.apache.axis.encoding.XMLType;
39  import org.apache.axis.encoding.ser.BaseDeserializerFactory;
40  import org.apache.axis.encoding.ser.BaseSerializerFactory;
41  import org.apache.axis.constants.Style;
42  import org.apache.axis.constants.Use;
43  import org.apache.axis.handlers.soap.SOAPService;
44  import org.apache.axis.message.RPCElement;
45  import org.apache.axis.message.RPCHeaderParam;
46  import org.apache.axis.message.RPCParam;
47  import org.apache.axis.message.SOAPBodyElement;
48  import org.apache.axis.message.SOAPEnvelope;
49  import org.apache.axis.message.SOAPFault;
50  import org.apache.axis.message.SOAPHeaderElement;
51  import org.apache.axis.soap.SOAPConstants;
52  import org.apache.axis.transport.http.HTTPTransport;
53  import org.apache.axis.utils.ClassUtils;
54  import org.apache.axis.utils.JavaUtils;
55  import org.apache.axis.utils.Messages;
56  import org.apache.axis.utils.LockableHashtable;
57  import org.apache.axis.wsdl.symbolTable.BindingEntry;
58  import org.apache.axis.wsdl.symbolTable.Parameter;
59  import org.apache.axis.wsdl.symbolTable.Parameters;
60  import org.apache.axis.wsdl.symbolTable.SymbolTable;
61  import org.apache.axis.wsdl.symbolTable.FaultInfo;
62  import org.apache.axis.wsdl.toJava.Utils;
63  import org.apache.commons.logging.Log;
64  
65  import javax.wsdl.Binding;
66  import javax.wsdl.BindingInput;
67  import javax.wsdl.BindingOperation;
68  import javax.wsdl.Operation;
69  import javax.wsdl.extensions.mime.MIMEPart;
70  import javax.wsdl.extensions.mime.MIMEMultipartRelated;
71  import javax.wsdl.Part;
72  import javax.wsdl.Port;
73  import javax.wsdl.PortType;
74  import javax.wsdl.extensions.soap.SOAPAddress;
75  import javax.wsdl.extensions.soap.SOAPBody;
76  import javax.wsdl.extensions.soap.SOAPOperation;
77  import javax.xml.namespace.QName;
78  import javax.xml.rpc.JAXRPCException;
79  import javax.xml.rpc.ParameterMode;
80  import javax.xml.soap.SOAPException;
81  import javax.xml.soap.SOAPMessage;
82  
83  import java.io.StringWriter;
84  import java.net.MalformedURLException;
85  import java.net.URL;
86  import java.util.ArrayList;
87  import java.util.HashMap;
88  import java.util.Hashtable;
89  import java.util.Iterator;
90  import java.util.List;
91  import java.util.Map;
92  import java.util.StringTokenizer;
93  import java.util.Vector;
94  import java.rmi.RemoteException;
95  
96  /**
97   * Axis' JAXRPC Dynamic Invocation Interface implementation of the Call
98   * interface.  This class should be used to actually invoke the Web Service.
99   * It can be prefilled by a WSDL document (on the constructor to the Service
100  * object) or you can fill in the data yourself.
101  * <pre>
102  * Standard properties defined by in JAX-RPC's javax..xml.rpc.Call interface:
103  *     USERNAME_PROPERTY        - User name for authentication
104  *     PASSWORD_PROPERTY        - Password for authentication
105  *     SESSION_PROPERTY         - Participate in a session with the endpoint?
106  *     OPERATION_STYLE_PROPERTY - "rpc" or "document"
107  *     SOAPACTION_USE_PROPERTY  - Should SOAPAction be used?
108  *     SOAPACTION_URI_PROPERTY  - If SOAPAction is used, this is that action
109  *     ENCODING_STYLE_PROPERTY  - Default is SOAP 1.1:  "http://schemas.xmlsoap.org/soap/encoding/"
110  *
111  * AXIS properties:
112  *     SEND_TYPE_ATTR - Should we send the XSI type attributes (true/false)
113  *     TIMEOUT        - Timeout used by transport sender in milliseconds
114  *     TRANSPORT_NAME - Name of transport handler to use
115  *     ATTACHMENT_ENCAPSULATION_FORMAT- Send attachments as MIME the default, or DIME.
116  *     CHARACTER_SET_ENCODING - Character set encoding to use for request
117  * </pre>
118  *
119  * @author Doug Davis (dug@us.ibm.com)
120  * @author Steve Loughran
121  */
122 
123 public class Call implements javax.xml.rpc.Call {
124     protected static Log log =
125         LogFactory.getLog(Call.class.getName());
126     private static Log tlog =
127         LogFactory.getLog(Constants.TIME_LOG_CATEGORY);
128 
129     // The enterprise category is for stuff that an enterprise product might
130     // want to track, but in a simple environment (like the AXIS build) would
131     // be nothing more than a nuisance.
132     protected static Log entLog =
133         LogFactory.getLog(Constants.ENTERPRISE_LOG_CATEGORY);
134 
135     private boolean            parmAndRetReq   = true ;
136     private Service            service         = null ;
137     private QName              portName        = null;
138     private QName              portTypeName    = null;
139     private QName              operationName   = null ;
140 
141     private MessageContext     msgContext      = null ;
142 
143     // Collection of properties to store and put in MessageContext at
144     // invoke() time.  Known ones are stored in actual variables for
145     // efficiency/type-consistency.  Unknown ones are in myProperties.
146     private LockableHashtable  myProperties    = new LockableHashtable();
147     private String             username        = null;
148     private String             password        = null;
149     private boolean            maintainSession = false;
150     private boolean            useSOAPAction   = false;
151     private String             SOAPActionURI   = null;
152     private Integer            timeout         = null;
153     private boolean            useStreaming    = false;
154 
155     /** Metadata for the operation associated with this Call */
156     private OperationDesc      operation       = null;
157     /** This will be true if an OperationDesc is handed to us whole */
158     private boolean operationSetManually       = false;
159 
160     // Is this a one-way call?
161     private boolean invokeOneWay               = false;
162     private boolean isMsg                      = false;
163 
164     // Our Transport, if any
165     private Transport          transport       = null ;
166     private String             transportName   = null ;
167 
168     // A couple places to store output parameters.
169     // As a HashMap, retrievable via QName (for getOutputParams).
170     private HashMap            outParams       = null;
171     // As a list, retrievable by index (for getOutputValues).
172     private ArrayList          outParamsList   = null;
173 
174     // A place to store any client-specified headers
175     private Vector             myHeaders       = null;
176 
177     public static final String SEND_TYPE_ATTR    = AxisEngine.PROP_SEND_XSI;
178 
179     /**
180      * This is the name of a property to set the transport of the message
181      *
182      * @see #setProperty
183      */
184     public static final String TRANSPORT_NAME    = "transport_name" ;
185 
186     /**
187      * This is the character set encoding to use for the message
188      *
189      * @see #setProperty
190      */
191     public static final String CHARACTER_SET_ENCODING = SOAPMessage.CHARACTER_SET_ENCODING;
192 
193     /**
194      * This is not the name of a property that can be set with
195      * setProperty, despite its name.
196      */
197     public static final String TRANSPORT_PROPERTY= "java.protocol.handler.pkgs";
198 
199     /**
200      * this is a property set in the message context when the invocation
201      * process begins, for the benefit of handlers
202      */
203     public static final String WSDL_SERVICE      = "wsdl.service";
204 
205     /**
206      * this is a property set in the message context when the invocation
207      * process begins, for the benefit of handlers
208      */
209     public static final String WSDL_PORT_NAME    = "wsdl.portName";
210 
211     /**
212      * @deprecated use WSDL_SERVICE instead.
213      */
214     public static final String JAXRPC_SERVICE    = WSDL_SERVICE;
215 
216     /**
217      * @deprecated use WSDL_PORT_NAME instead.
218      */
219     public static final String JAXRPC_PORTTYPE_NAME = WSDL_PORT_NAME;
220 
221     /**
222      * If this property is true, the code will throw a fault if there is no
223      * response message from the server.  Otherwise, the
224      * invoke method will return a null.
225      */
226     public static final String FAULT_ON_NO_RESPONSE = "call.FaultOnNoResponse";
227 
228     /**
229      * If this property is true, code will enforce must understand check on both
230      * the request and the response paths.
231      */ 
232     public static final String CHECK_MUST_UNDERSTAND = "call.CheckMustUnderstand";
233     
234     /**
235      * Property for setting attachment format.
236      * Can be set to either DIME or MIME (default)
237      * @see #setProperty
238      * @see #ATTACHMENT_ENCAPSULATION_FORMAT_DIME
239      * @see #ATTACHMENT_ENCAPSULATION_FORMAT_MIME
240      */
241     public static final String ATTACHMENT_ENCAPSULATION_FORMAT=
242       "attachment_encapsulation_format";
243     /**
244      * Property value for setting attachment format as MIME.
245      */
246     public static final String ATTACHMENT_ENCAPSULATION_FORMAT_MIME=
247       "axis.attachment.style.mime";
248     /**
249      * Property value for setting attachment format as DIME.
250      */
251     public static final String ATTACHMENT_ENCAPSULATION_FORMAT_DIME=
252       "axis.attachment.style.dime";
253 
254     /**
255      * Timeout property: should be accompanies by an integer
256      * @see #setProperty
257      */
258     public static final String CONNECTION_TIMEOUT_PROPERTY =
259             "axis.connection.timeout";
260 
261     /**
262      * Streaming property: should be accompanied by an boolean
263      * (i.e. NO high-fidelity recording, deserialize on the fly)
264      * @see #setProperty
265      */
266     public static final String STREAMING_PROPERTY =
267             "axis.streaming";
268     
269     /**
270      * Internal property to indicate a one way call.
271      * That will disable processing of response handlers.
272      */
273     protected static final String ONE_WAY =
274         "axis.one.way";
275 
276     /**
277      * A Hashtable mapping protocols (Strings) to Transports (classes)
278      */
279     private static Hashtable transports  = new Hashtable();
280 
281     static ParameterMode [] modes = new ParameterMode [] { null,
282                                             ParameterMode.IN,
283                                             ParameterMode.OUT,
284                                             ParameterMode.INOUT };
285 
286     /** This is true when someone has called setEncodingStyle() */
287     private boolean encodingStyleExplicitlySet = false;
288     /** This is true when someone has called setOperationUse() */
289     private boolean useExplicitlySet = false;
290 
291     /**
292      * the name of a SOAP service that the call is bound to
293      */
294     private SOAPService myService = null;
295 
296     /**
297      * these are our attachments
298      */
299     protected java.util.Vector attachmentParts = new java.util.Vector();
300 
301     /** This is false when invoke() is called. */
302     private boolean isNeverInvoked  = true;     
303 
304     static {
305         initialize();
306     }
307 
308     /************************************************************************/
309     /* Start of core JAX-RPC stuff                                          */
310     /************************************************************************/
311 
312     /**
313      * Default constructor - not much else to say.
314      *
315      * @param service  the <code>Service</code> this <code>Call</code> will
316      *              work with
317      */
318     public Call(Service service) {
319         this.service = service ;
320         AxisEngine engine = service.getEngine();
321         msgContext = new MessageContext( engine );
322         myProperties.setParent(engine.getOptions());
323         maintainSession = service.getMaintainSession();
324     }
325 
326     /**
327      * Build a call from a URL string.
328      *
329      * This is handy so that you don't have to manually call Call.initialize()
330      * in order to register custom transports.  In other words, whereas doing
331      * a new URL("local:...") would fail, new Call("local:...") works because
332      * we do the initialization of our own and any configured custom protocols. 
333      *
334      * @param url the target endpoint URL
335      * @exception MalformedURLException
336      */
337     public Call(String url) throws MalformedURLException {
338         this(new Service());
339         setTargetEndpointAddress(new URL(url));
340     }
341 
342     /**
343      * Build a call from a URL.
344      *
345      * @param url the target endpoint URL
346      */
347     public Call(URL url) {
348         this(new Service());
349         setTargetEndpointAddress(url);
350     }
351 
352     ////////////////////////////
353     //
354     // Properties and the shortcuts for common ones.
355     //
356 
357     /**
358      * Allows you to set a named property to the passed in value.
359      * There are a few known properties (like username, password, etc)
360      * that are variables in Call.  The rest of the properties are
361      * stored in a Hashtable.  These common properties should be
362      * accessed via the accessors for speed/type safety, but they may
363      * still be obtained via this method.  It's up to one of the
364      * Handlers (or the Axis engine itself) to go looking for
365      * one of them.
366      *
367      * There are various well defined properties defined in the
368      * JAX-RPC specification and declared in the Call and Stub classes.
369      * It is not possible to set any other properties beginning in java. or
370      * javax. that are not in the specification.
371      * @see javax.xml.rpc.Stub
372      * @see javax.xml.rpc.Call
373      *
374      * There are other properties implemented in this class above and
375      * beyond those of the JAX-RPC spec
376      * Specifically, ATTACHMENT_ENCAPSULATION_FORMAT, CONNECTION_TIMEOUT_PROPERTY,
377      * and TRANSPORT_NAME.
378      *
379      * It is intended that all future Axis-specific properties will begin
380      * with axis. or apache. To ensure integration with future versions Axis,
381      * use different prefixes for your own properties.
382      *
383      * Axis developers: keep this in sync with propertyNames below
384      * @see #ATTACHMENT_ENCAPSULATION_FORMAT
385      * @see #TRANSPORT_NAME
386      * @see #CONNECTION_TIMEOUT_PROPERTY
387      * @param name  Name of the property
388      * @param value Value of the property
389      */
390     public void setProperty(String name, Object value) {
391         if (name == null || value == null) {
392             throw new JAXRPCException(
393                     Messages.getMessage(name == null ?
394                                          "badProp03" : "badProp04"));
395         }
396         else if (name.equals(USERNAME_PROPERTY)) {
397             verifyStringProperty(name, value);
398             setUsername((String) value);
399         }
400         else if (name.equals(PASSWORD_PROPERTY)) {
401             verifyStringProperty(name, value);
402             setPassword((String) value);
403         }
404         else if (name.equals(SESSION_MAINTAIN_PROPERTY)) {
405             verifyBooleanProperty(name, value);
406             setMaintainSession(((Boolean) value).booleanValue());
407         }
408         else if (name.equals(OPERATION_STYLE_PROPERTY)) {
409             verifyStringProperty(name, value);
410             setOperationStyle((String) value);
411             if (getOperationStyle() == Style.DOCUMENT ||
412                 getOperationStyle() == Style.WRAPPED) {
413                 setOperationUse(Use.LITERAL_STR);
414             } else if (getOperationStyle() == Style.RPC) {
415                 setOperationUse(Use.ENCODED_STR);
416             }
417         }
418         else if (name.equals(SOAPACTION_USE_PROPERTY)) {
419             verifyBooleanProperty(name, value);
420             setUseSOAPAction(((Boolean) value).booleanValue());
421         }
422         else if (name.equals(SOAPACTION_URI_PROPERTY)) {
423             verifyStringProperty(name, value);
424             setSOAPActionURI((String) value);
425         }
426         else if (name.equals(ENCODINGSTYLE_URI_PROPERTY)) {
427             verifyStringProperty(name, value);
428             setEncodingStyle((String) value);
429         }
430         else if (name.equals(Stub.ENDPOINT_ADDRESS_PROPERTY)) {
431             verifyStringProperty(name, value);
432             setTargetEndpointAddress((String) value);
433         }
434         else if ( name.equals(TRANSPORT_NAME) ) {
435             verifyStringProperty(name, value);
436             transportName = (String) value ;
437             if (transport != null) {
438                 transport.setTransportName((String) value);
439             }
440         }
441         else if ( name.equals(ATTACHMENT_ENCAPSULATION_FORMAT) ) {
442             verifyStringProperty(name, value);
443             if(!value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_MIME ) &&
444                !value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_DIME ))
445                 throw new JAXRPCException(
446                         Messages.getMessage("badattachmenttypeerr", new String[] {
447                         (String) value, ATTACHMENT_ENCAPSULATION_FORMAT_MIME + " "
448                         +ATTACHMENT_ENCAPSULATION_FORMAT_DIME  }));
449         }
450         else if (name.equals(CONNECTION_TIMEOUT_PROPERTY)) {
451             verifyIntegerProperty(name,value);
452             setTimeout((Integer)value);
453         }
454         else if (name.equals(STREAMING_PROPERTY)) {
455             verifyBooleanProperty(name, value);
456             setStreaming(((Boolean) value).booleanValue());
457         }
458         else if (name.equals(CHARACTER_SET_ENCODING)) {
459             verifyStringProperty(name, value);
460         }
461         else if (name.startsWith("java.") || name.startsWith("javax.")) {
462             throw new JAXRPCException(
463                     Messages.getMessage("badProp05", name));
464         }
465         myProperties.put(name, value);
466     } // setProperty
467 
468     /**
469      * Verify that the type of the object is a String, and throw
470      * an i18n-ized exception if not
471      * @param name
472      * @param value
473      * @throws JAXRPCException if value is not a String
474      */
475     private void verifyStringProperty(String name, Object value) {
476         if (!(value instanceof String)) {
477             throw new JAXRPCException(
478                     Messages.getMessage("badProp00", new String[]
479                     {name,
480                     "java.lang.String",
481                     value.getClass().getName()}));
482         }
483     }
484 
485     /**
486      * Verify that the type of the object is a Boolean, and throw
487      * an i18n-ized exception if not
488      * @param name
489      * @param value
490      * @throws JAXRPCException if value is not a Boolean
491      */
492     private void verifyBooleanProperty(String name, Object value) {
493         if (!(value instanceof Boolean)) {
494             throw new JAXRPCException(
495                     Messages.getMessage("badProp00", new String[]
496                     {name,
497                     "java.lang.Boolean",
498                     value.getClass().getName()}));
499         }
500     }
501 
502     /**
503      * Verify that the type of the object is an Integer, and throw
504      * an i18n-ized exception if not
505      * @param name
506      * @param value
507      * @throws JAXRPCException if value is not an Integer
508      */
509     private void verifyIntegerProperty(String name, Object value) {
510         if (!(value instanceof Integer)) {
511             throw new JAXRPCException(
512                     Messages.getMessage("badProp00", new String[]
513                     {name,
514                      "java.lang.Integer",
515                      value.getClass().getName()}));
516         }
517     }
518 
519     /**
520      * Returns the value associated with the named property.
521      *
522      * @param name the name of the property
523      * @return Object value of the property or null if the property is not set
524      * @throws JAXRPCException if the requested property is not a supported property
525      */
526     public Object getProperty(String name) {
527         if (name == null || !isPropertySupported(name)) {
528             throw new JAXRPCException(name == null ?
529                   Messages.getMessage("badProp03") :
530                   Messages.getMessage("badProp05", name));
531         }
532         return myProperties.get(name);
533     } // getProperty
534 
535     /**
536       * Removes (if set) the named property.
537       *
538       * @param name name of the property to remove
539       */
540      public void removeProperty(String name) {
541          if (name == null || !isPropertySupported(name)) {
542             throw new JAXRPCException(name == null ?
543                   Messages.getMessage("badProp03") :
544                   Messages.getMessage("badProp05", name));
545          }
546          myProperties.remove(name);
547      } // removeProperty
548 
549     /**
550      * Configurable properties supported by this Call object.
551      */
552     private static ArrayList propertyNames = new ArrayList();
553     static {
554         propertyNames.add(USERNAME_PROPERTY);
555         propertyNames.add(PASSWORD_PROPERTY);
556         propertyNames.add(SESSION_MAINTAIN_PROPERTY);
557         propertyNames.add(OPERATION_STYLE_PROPERTY);
558         propertyNames.add(SOAPACTION_USE_PROPERTY);
559         propertyNames.add(SOAPACTION_URI_PROPERTY);
560         propertyNames.add(ENCODINGSTYLE_URI_PROPERTY);
561         propertyNames.add(Stub.ENDPOINT_ADDRESS_PROPERTY);
562         propertyNames.add(TRANSPORT_NAME);
563         propertyNames.add(ATTACHMENT_ENCAPSULATION_FORMAT);
564         propertyNames.add(CONNECTION_TIMEOUT_PROPERTY);
565         propertyNames.add(CHARACTER_SET_ENCODING);
566     }
567 
568     public Iterator getPropertyNames() {
569         return propertyNames.iterator();
570     }
571 
572     public boolean isPropertySupported(String name) {
573         return propertyNames.contains(name) || (!name.startsWith("java.")
574                && !name.startsWith("javax."));
575     }
576 
577     /**
578      * Set the username.
579      *
580      * @param username  the new user name
581      */
582     public void setUsername(String username) {
583         this.username = username;
584     } // setUsername
585 
586     /**
587      * Get the user name.
588      *
589      * @return the user name
590      */
591     public String getUsername() {
592         return username;
593     } // getUsername
594 
595     /**
596      * Set the password.
597      *
598      * @param password  plain-text copy of the password
599      */
600     public void setPassword(String password) {
601         this.password = password;
602     } // setPassword
603 
604     /**
605      * Get the password.
606      *
607      * @return a plain-text copy of the password
608      */
609     public String getPassword() {
610         return password;
611     } // getPassword
612 
613     /**
614      * Determine whether we'd like to track sessions or not.  This
615      * overrides the default setting from the service.
616      * This just passes through the value into the MessageContext.
617      * Note: Not part of JAX-RPC specification.
618      *
619      * @param yesno true if session state is desired, false if not.
620      */
621     public void setMaintainSession(boolean yesno) {
622         maintainSession = yesno;
623     }
624 
625     /**
626      * Get the value of maintainSession flag.
627      *
628      * @return true if session is maintained, false otherwise
629      */
630     public boolean getMaintainSession() {
631         return maintainSession;
632     }
633 
634     /**
635      * Set the operation style: "document", "rpc"
636      * @param operationStyle string designating style
637      */
638     public void setOperationStyle(String operationStyle) {
639         Style style = Style.getStyle(operationStyle, Style.DEFAULT);
640         setOperationStyle(style);
641     } // setOperationStyle
642 
643     /**
644      * Set the operation style
645      *
646      * @param operationStyle
647      */
648     public void setOperationStyle(Style operationStyle) {
649         if (operation == null) {
650             operation = new OperationDesc();
651         }
652 
653         operation.setStyle(operationStyle);
654 
655         // If no one has explicitly set the use, we should track
656         // the style.  If it's non-RPC, default to LITERAL.
657         if (!useExplicitlySet) {
658             if (operationStyle != Style.RPC) {
659                 operation.setUse(Use.LITERAL);
660             }
661         }
662 
663         // If no one has explicitly set the encodingStyle, we should
664         // track the style.  If it's RPC, default to SOAP-ENC, otherwise
665         // default to "".
666         if (!encodingStyleExplicitlySet) {
667             String encStyle = "";
668             if (operationStyle == Style.RPC) {
669                 // RPC style defaults to encoded, otherwise default to literal
670                 encStyle = msgContext.getSOAPConstants().getEncodingURI();
671             }
672             msgContext.setEncodingStyle(encStyle);
673         }
674     }
675 
676     /**
677      * Get the operation style.
678      *
679      * @return the <code>Style</code> of the operation
680      */
681     public Style getOperationStyle() {
682         if (operation != null) {
683             return operation.getStyle();
684         }
685         return Style.DEFAULT;
686     } // getOperationStyle
687 
688     /**
689      * Set the operation use: "literal", "encoded"
690      * @param operationUse string designating use
691      */
692     public void setOperationUse(String operationUse) {
693         Use use = Use.getUse(operationUse, Use.DEFAULT);
694         setOperationUse(use);
695     } // setOperationUse
696 
697     /**
698      * Set the operation use
699      * @param operationUse
700      */
701     public void setOperationUse(Use operationUse) {
702         useExplicitlySet = true;
703 
704         if (operation == null) {
705             operation = new OperationDesc();
706         }
707 
708         operation.setUse(operationUse);
709         if (!encodingStyleExplicitlySet) {
710             String encStyle = "";
711             if (operationUse == Use.ENCODED) {
712                 // RPC style defaults to encoded, otherwise default to literal
713                 encStyle = msgContext.getSOAPConstants().getEncodingURI();
714             }
715             msgContext.setEncodingStyle(encStyle);
716         }
717     }
718 
719     /**
720      * Get the operation use.
721      *
722      * @return the <code>Use</code> of the operation
723      */
724     public Use getOperationUse() {
725         if (operation != null) {
726             return operation.getUse();
727         }
728         return Use.DEFAULT;
729     } // getOperationStyle
730 
731     /**
732      * Flag to indicate if soapAction should be used.
733      *
734      * @param useSOAPAction  true if the soapAction header is to be used to
735      *              help find the method to invoke, false otherwise
736      */
737     public void setUseSOAPAction(boolean useSOAPAction) {
738         this.useSOAPAction = useSOAPAction;
739     } // setUseSOAPAction
740 
741     /**
742      * Discover if soapAction is being used.
743      *
744      * @return true if it is, false otherwise
745      */
746     public boolean useSOAPAction() {
747         return useSOAPAction;
748     } // useSOAPAction
749 
750     /**
751      * Set the soapAction URI.
752      *
753      * @param SOAPActionURI  the new SOAP action URI
754      */
755     public void setSOAPActionURI(String SOAPActionURI) {
756         useSOAPAction = true;
757         this.SOAPActionURI = SOAPActionURI;
758     } // setSOAPActionURI
759 
760     /**
761      * Get the soapAction URI.
762      *
763      * @return the curretn SOAP action URI
764      */
765     public String getSOAPActionURI() {
766         return SOAPActionURI;
767     } // getSOAPActionURI
768 
769     /**
770      * Sets the encoding style to the URL passed in.
771      *
772      * @param namespaceURI URI of the encoding to use.
773      */
774     public void setEncodingStyle(String namespaceURI) {
775         encodingStyleExplicitlySet = true;
776         msgContext.setEncodingStyle(namespaceURI);
777     }
778 
779     /**
780      * Returns the encoding style as a URI that should be used for the SOAP
781      * message.
782      *
783      * @return String URI of the encoding style to use
784      */
785     public String getEncodingStyle() {
786         return msgContext.getEncodingStyle();
787     }
788 
789     /**
790      * Sets the endpoint address of the target service port. This address must
791      * correspond to the transport specified in the binding for this Call
792      * instance.
793      *
794      * @param address - Endpoint address of the target service port; specified
795      *                  as URI
796      */
797     public void setTargetEndpointAddress(String address) {
798         URL urlAddress;
799         try {
800             urlAddress = new URL(address);
801         }
802         catch (MalformedURLException mue) {
803             throw new JAXRPCException(mue);
804         }
805         setTargetEndpointAddress(urlAddress);
806     }
807 
808     /**
809      * Sets the URL of the target Web Service.
810      *
811      * Note: Not part of JAX-RPC specification.
812      *
813      * @param address URL of the target Web Service
814      */
815     public void setTargetEndpointAddress(java.net.URL address) {
816         try {
817             if ( address == null ) {
818                 setTransport(null);
819                 return ;
820             }
821 
822             String protocol = address.getProtocol();
823 
824             // Handle the case where the protocol is the same but we
825             // just want to change the URL - if so just set the URL,
826             // creating a new Transport object will drop all session
827             // data - and we want that stuff to persist between invoke()s.
828             // Technically the session data should be in the message
829             // context so that it can be persistent across transports
830             // as well, but for now the data is in the Transport object.
831             ////////////////////////////////////////////////////////////////
832             if ( this.transport != null ) {
833                 String oldAddr = this.transport.getUrl();
834                 if ( oldAddr != null && !oldAddr.equals("") ) {
835                     URL     tmpURL   = new URL( oldAddr );
836                     String  oldProto = tmpURL.getProtocol();
837                     if ( protocol.equals(oldProto) ) {
838                         this.transport.setUrl( address.toString() );
839                         return ;
840                     }
841                 }
842             }
843 
844             // Do we already have a transport for this address?
845             Transport transport = service.getTransportForURL(address);
846             if (transport != null) {
847                 setTransport(transport);
848             }
849             else {
850             // We don't already have a transport for this address.  Create one.
851                 transport = getTransportForProtocol(protocol);
852                 if (transport == null)
853                     throw new AxisFault("Call.setTargetEndpointAddress",
854                                  Messages.getMessage("noTransport01",
855                                  protocol), null, null);
856                 transport.setUrl(address.toString());
857                 setTransport(transport);
858                 service.registerTransportForURL(address, transport);
859             }
860         }
861         catch( Exception exp ) {
862             log.error(Messages.getMessage("exception00"), exp);
863             // do what?
864             // throw new AxisFault("Call.setTargetEndpointAddress",
865             //"Malformed URL Exception: " + e.getMessage(), null, null);
866         }
867     }
868 
869     /**
870      * Returns the URL of the target Web Service.
871      *
872      * @return URL URL of the target Web Service
873      */
874     public String getTargetEndpointAddress() {
875         try {
876             if ( transport == null ) return( null );
877             return( transport.getUrl() );
878         }
879         catch( Exception exp ) {
880             return( null );
881         }
882     }
883 
884     public Integer getTimeout() {
885         return timeout;
886     }
887 
888     public void setTimeout(Integer timeout) {
889         this.timeout = timeout;
890     }
891 
892     public boolean getStreaming() {
893         return useStreaming;
894     }
895 
896     public void setStreaming(boolean useStreaming) {
897         this.useStreaming = useStreaming;
898     }
899     //
900     // end properties code.
901     //
902     ////////////////////////////
903 
904     /**
905      * Is the caller required to provide the parameter and return type
906      * specification?
907      * If true, then
908      *  addParameter and setReturnType MUST be called to provide the meta data.
909      * If false, then
910      *  addParameter and setReturnType SHOULD NOT be called because the
911      *  Call object already has the meta data describing the
912      *  parameters and return type. If addParameter is called, the specified
913      *  parameter is added to the end of the list of parameters.
914      */
915     public boolean isParameterAndReturnSpecRequired(QName operationName) {
916         return parmAndRetReq;
917     } // isParameterAndReturnSpecRequired
918 
919     /**
920      * Adds the specified parameter to the list of parameters for the
921      * operation associated with this Call object.
922      *
923      * Note: Not part of JAX-RPC specification.
924      *
925      * @param paramName Name that will be used for the parameter in the XML
926      * @param xmlType XMLType of the parameter
927      * @param parameterMode one of IN, OUT or INOUT
928      */
929     public void addParameter(QName paramName, QName xmlType,
930             ParameterMode parameterMode) {
931         Class javaType = null;
932         TypeMapping tm = getTypeMapping();
933         if (tm != null) {
934             javaType = tm.getClassForQName(xmlType);
935         }
936         addParameter(paramName, xmlType, javaType, parameterMode);
937     }
938 
939     /**
940      * Adds the specified parameter to the list of parameters for the
941      * operation associated with this Call object.
942      *
943      *
944      * Note: Not part of JAX-RPC specification.
945      *
946      * @param paramName Name that will be used for the parameter in the XML
947      * @param xmlType XMLType of the parameter
948      * @param javaType The Java class of the parameter
949      * @param parameterMode one of IN, OUT or INOUT
950      */
951     public void addParameter(QName paramName, QName xmlType,
952             Class javaType, ParameterMode parameterMode) {
953 
954         if (operationSetManually) {
955             throw new RuntimeException(
956                     Messages.getMessage("operationAlreadySet"));
957         }
958 
959         if (operation == null)
960             operation = new OperationDesc();
961 
962         ParameterDesc param = new ParameterDesc();
963         byte mode = ParameterDesc.IN;
964         if (parameterMode == ParameterMode.INOUT) {
965             mode = ParameterDesc.INOUT;
966             param.setIsReturn(true);
967         } else if (parameterMode == ParameterMode.OUT) {
968             mode = ParameterDesc.OUT;
969             param.setIsReturn(true);
970         }
971         param.setMode(mode);
972         param.setQName(new QName(paramName.getNamespaceURI(),Utils.getLastLocalPart(paramName.getLocalPart())));
973         param.setTypeQName( xmlType );
974         param.setJavaType( javaType );
975 
976         operation.addParameter(param);
977         parmAndRetReq = true;
978     }
979 
980     /**
981      * Adds the specified parameter to the list of parameters for the
982      * operation associated with this Call object.
983      *
984      * @param paramName      Name that will be used for the parameter in the XML
985      * @param xmlType      XMLType of the parameter
986      * @param parameterMode  one of IN, OUT or INOUT
987      */
988     public void addParameter(String paramName, QName xmlType,
989             ParameterMode parameterMode) {
990         Class javaType = null;
991         TypeMapping tm = getTypeMapping();
992         if (tm != null) {
993             javaType = tm.getClassForQName(xmlType);
994         }
995         addParameter(new QName("", paramName), xmlType,
996                      javaType, parameterMode);
997     }
998 
999     /**
1000     * Adds a parameter type and mode for a specific operation. Note that the
1001     * client code is not required to call any addParameter and setReturnType
1002     * methods before calling the invoke method. A Call implementation class
1003     * can determine the parameter types by using the Java reflection and
1004     * configured type mapping registry.
1005     *
1006     * @param paramName - Name of the parameter
1007     * @param xmlType - XML datatype of the parameter
1008     * @param javaType - The Java class of the parameter
1009     * @param parameterMode - Mode of the parameter-whether IN, OUT or INOUT
1010     * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns
1011     *                              false, then addParameter MAY throw
1012     *                              JAXRPCException....actually Axis allows
1013     *                              modification in such cases
1014     */
1015    public void addParameter(String paramName, QName xmlType,
1016                             Class javaType, ParameterMode parameterMode) {
1017        addParameter(new QName("", paramName), xmlType,
1018                     javaType, parameterMode);
1019    }
1020
1021    /**
1022     * Adds a parameter type as a soap:header.
1023     *
1024     * @param paramName     - Name of the parameter
1025     * @param xmlType       - XML datatype of the parameter
1026     * @param parameterMode - Mode of the parameter-whether IN, OUT or INOUT
1027     * @param headerMode    - Mode of the header. Even if this is an INOUT
1028     *                      parameter, it need not be in the header in both
1029     *                      directions.
1030     * @throws JAXRPCException - if isParameterAndReturnSpecRequired returns
1031     *                         false, then addParameter MAY throw
1032     *                         JAXRPCException....actually Axis allows
1033     *                         modification in such cases
1034     */
1035    public void addParameterAsHeader(QName paramName, QName xmlType,
1036                                     ParameterMode parameterMode,
1037                                     ParameterMode headerMode) {
1038        Class javaType = null;
1039        TypeMapping tm = getTypeMapping();
1040        if (tm != null) {
1041            javaType = tm.getClassForQName(xmlType);
1042        }
1043        addParameterAsHeader(paramName, xmlType, javaType,
1044                parameterMode, headerMode);
1045    }
1046     
1047    /**
1048
1049     * Adds a parameter type as a soap:header.
1050     * @param paramName - Name of the parameter
1051     * @param xmlType - XML datatype of the parameter
1052     * @param javaType - The Java class of the parameter
1053     * @param parameterMode - Mode of the parameter-whether IN, OUT or INOUT
1054     * @param headerMode - Mode of the header.  Even if this is an INOUT
1055     *                     parameter, it need not be in the header in both
1056     *                     directions.
1057     * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns
1058     *                              false, then addParameter MAY throw
1059     *                              JAXRPCException....actually Axis allows
1060     *                              modification in such cases
1061     */
1062    public void addParameterAsHeader(QName paramName, QName xmlType,
1063            Class javaType, ParameterMode parameterMode,
1064            ParameterMode headerMode) {
1065        if (operationSetManually) {
1066            throw new RuntimeException(
1067                    Messages.getMessage("operationAlreadySet"));
1068        }
1069
1070        if (operation == null)
1071            operation = new OperationDesc();
1072
1073        ParameterDesc param = new ParameterDesc();
1074        param.setQName(new QName(paramName.getNamespaceURI(),Utils.getLastLocalPart(paramName.getLocalPart())));
1075        param.setTypeQName(xmlType);
1076        param.setJavaType(javaType);
1077        if (parameterMode == ParameterMode.IN) {
1078            param.setMode(ParameterDesc.IN);
1079        }
1080        else if (parameterMode == ParameterMode.INOUT) {
1081            param.setMode(ParameterDesc.INOUT);
1082        }
1083        else if (parameterMode == ParameterMode.OUT) {
1084            param.setMode(ParameterDesc.OUT);
1085        }
1086        if (headerMode == ParameterMode.IN) {
1087            param.setInHeader(true);
1088        }
1089        else if (headerMode == ParameterMode.INOUT) {
1090            param.setInHeader(true);
1091            param.setOutHeader(true);
1092        }
1093        else if (headerMode == ParameterMode.OUT) {
1094            param.setOutHeader(true);
1095        }
1096        operation.addParameter(param);
1097        parmAndRetReq = true;
1098    } // addParameterAsHeader
1099
1100    /**
1101     * Return the QName of the type of the parameters with the given name.
1102     *
1103     * @param  paramName  name of the parameter to return
1104     * @return XMLType    XMLType of paramName, or null if not found.
1105     */
1106    public QName getParameterTypeByName(String paramName) {
1107        QName paramQName = new QName("", paramName);
1108
1109        return getParameterTypeByQName(paramQName);
1110    }
1111
1112    /**
1113     * Return the QName of the type of the parameters with the given name.
1114     *
1115     * Note: Not part of JAX-RPC specification.
1116     *
1117     * @param  paramQName  QName of the parameter to return
1118     * @return XMLType    XMLType of paramQName, or null if not found.
1119     */
1120    public QName getParameterTypeByQName(QName paramQName) {
1121        ParameterDesc param = operation.getParamByQName(paramQName);
1122        if (param != null) {
1123            return param.getTypeQName();
1124        }
1125        return( null );
1126    }
1127
1128    /**
1129     * Sets the return type of the operation associated with this Call object.
1130     *
1131     * @param type QName of the return value type.
1132     */
1133    public void setReturnType(QName type) {
1134        if (operationSetManually) {
1135            throw new RuntimeException(
1136                    Messages.getMessage("operationAlreadySet"));
1137        }
1138
1139        if (operation == null)
1140            operation = new OperationDesc();
1141
1142        // In order to allow any Call to be re-used, Axis
1143        // chooses to allow setReturnType to be changed when
1144        // parmAndRetReq==false.  This does not conflict with
1145        // JSR 101 which indicates an exception MAY be thrown.
1146
1147        //if (parmAndRetReq) {
1148        operation.setReturnType(type);
1149        TypeMapping tm = getTypeMapping();
1150        operation.setReturnClass(tm.getClassForQName(type));
1151        parmAndRetReq = true;
1152        //}
1153        //else {
1154        //throw new JAXRPCException(Messages.getMessage("noParmAndRetReq"));
1155        //}
1156    }
1157
1158    /**
1159     * Sets the return type for a specific operation.
1160     *
1161     * @param xmlType - QName of the data type of the return value
1162     * @param javaType - Java class of the return value
1163     * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns
1164     * false, then setReturnType MAY throw JAXRPCException...Axis allows
1165     * modification without throwing the exception.
1166     */
1167    public void setReturnType(QName xmlType, Class javaType) {
1168        setReturnType(xmlType);
1169        // Use specified type as the operation return
1170        operation.setReturnClass(javaType);
1171    }
1172
1173    /**
1174     * Set the return type as a header
1175     */
1176    public void setReturnTypeAsHeader(QName xmlType) {
1177        setReturnType(xmlType);
1178        operation.setReturnHeader(true);
1179    } // setReturnTypeAsHeader
1180
1181    /**
1182     * Set the return type as a header
1183     */
1184    public void setReturnTypeAsHeader(QName xmlType, Class javaType) {
1185        setReturnType(xmlType, javaType);
1186        operation.setReturnHeader(true);
1187    } // setReturnTypeAsHeader
1188
1189    /**
1190     * Returns the QName of the type of the return value of this Call - or null
1191     * if not set.
1192     *
1193     * Note: Not part of JAX-RPC specification.
1194     *
1195     * @return the XMLType specified for this Call (or null).
1196     */
1197    public QName getReturnType() {
1198        if (operation != null)
1199            return operation.getReturnType();
1200
1201        return null;
1202    }
1203
1204    /**
1205     * Set the QName of the return element
1206     *
1207     * NOT part of JAX-RPC
1208     */
1209    public void setReturnQName(QName qname) {
1210        if (operationSetManually) {
1211            throw new RuntimeException(
1212                    Messages.getMessage("operationAlreadySet"));
1213        }
1214
1215        if (operation == null)
1216            operation = new OperationDesc();
1217
1218        operation.setReturnQName(qname);
1219    }
1220    /**
1221     * Sets the desired return Java Class.  This is a convenience method
1222     * which will cause the Call to automatically convert return values
1223     * into a desired class if possible.  For instance, we return object
1224     * arrays by default now for SOAP arrays - you could specify:
1225     *
1226     * setReturnClass(Vector.class)
1227     *
1228     * and you'd get a Vector back from invoke() instead of having to do
1229     * the conversion yourself.
1230     *
1231     * Note: Not part of JAX-RPC specification.  To be JAX-RPC compliant,
1232     *       use setReturnType(QName, Class).
1233     *
1234     * @param cls the desired return class.
1235     */
1236    public void setReturnClass(Class cls) {
1237        if (operationSetManually) {
1238            throw new RuntimeException(
1239                    Messages.getMessage("operationAlreadySet"));
1240        }
1241
1242        if (operation == null)
1243            operation = new OperationDesc();
1244
1245        operation.setReturnClass(cls);
1246        TypeMapping tm = getTypeMapping();
1247        operation.setReturnType(tm.getTypeQName(cls));
1248        parmAndRetReq = true;
1249    }
1250
1251    /**
1252     * Clears the list of parameters.
1253     * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns
1254     *  false, then removeAllParameters MAY throw JAXRPCException...Axis allows
1255     *  modification to the Call object without throwing an exception.
1256     */
1257    public void removeAllParameters() {
1258        //if (parmAndRetReq) {
1259        operation = new OperationDesc();
1260        operationSetManually = false;
1261        parmAndRetReq = true;
1262        //}
1263        //else {
1264        //throw new JAXRPCException(Messages.getMessage("noParmAndRetReq"));
1265        //}
1266    }
1267
1268    /**
1269     * Returns the operation name associated with this Call object.
1270     *
1271     * @return String Name of the operation or null if not set.
1272     */
1273    public QName getOperationName() {
1274        return( operationName );
1275    }
1276
1277    /**
1278     * Sets the operation name associated with this Call object.  This will
1279     * not check the WSDL (if there is WSDL) to make sure that it's a valid
1280     * operation name.
1281     *
1282     * @param opName Name of the operation.
1283     */
1284    public void setOperationName(QName opName) {
1285        operationName = opName ;
1286    }
1287
1288    /**
1289     * This is a convenience method.  If the user doesn't care about the QName
1290     * of the operation, the user can call this method, which converts a String
1291     * operation name to a QName.
1292     */
1293    public void setOperationName(String opName) {
1294        operationName = new QName(opName);
1295    }
1296
1297    /**
1298     * Prefill as much info from the WSDL as it can.
1299     * Right now it's SOAPAction, operation qname, parameter types
1300     * and return type of the Web Service.
1301     *
1302     * This methods considers that port name and target endpoint address have
1303     * already been set. This is useful when you want to use the same Call
1304     * instance for several calls on the same Port
1305     *
1306     * Note: Not part of JAX-RPC specification.
1307     *
1308     * @param  opName          Operation(method) that's going to be invoked
1309     * @throws JAXRPCException
1310     */
1311    public void setOperation(String opName) {
1312        if ( service == null ) {
1313            throw new JAXRPCException( Messages.getMessage("noService04") );
1314        }
1315
1316        // remove all settings concerning an operation
1317        // leave portName and targetEndPoint as they are
1318        this.setOperationName( opName );
1319        this.setEncodingStyle( null );
1320        this.setReturnType( null );
1321        this.removeAllParameters();
1322
1323        javax.wsdl.Service wsdlService = service.getWSDLService();
1324        // Nothing to do is the WSDL is not already set.
1325        if(wsdlService == null) {
1326            return;
1327        }
1328
1329        Port port = wsdlService.getPort( portName.getLocalPart() );
1330        if ( port == null ) {
1331            throw new JAXRPCException( Messages.getMessage("noPort00", "" +
1332                                                           portName) );
1333        }
1334
1335        Binding   binding  = port.getBinding();
1336        PortType  portType = binding.getPortType();
1337        if ( portType == null ) {
1338            throw new JAXRPCException( Messages.getMessage("noPortType00", "" +
1339                                                           portName) );
1340        }
1341        this.setPortTypeName(portType.getQName());
1342        
1343        List operations = portType.getOperations();
1344        if ( operations == null ) {
1345            throw new JAXRPCException( Messages.getMessage("noOperation01",
1346                                                           opName) );
1347        }
1348
1349        Operation op = null ;
1350        for ( int i = 0 ; i < operations.size() ; i++, op=null ) {
1351            op = (Operation) operations.get( i );
1352            if ( opName.equals( op.getName() ) ) {
1353                break ;
1354            }
1355        }
1356        if ( op == null ) {
1357            throw new