KickJava   Java API By Example, From Geeks To Geeks.

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


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 JavaDoc;
78 import javax.xml.rpc.JAXRPCException JavaDoc;
79 import javax.xml.rpc.ParameterMode JavaDoc;
80 import javax.xml.soap.SOAPException JavaDoc;
81 import javax.xml.soap.SOAPMessage JavaDoc;
82
83 import java.io.StringWriter JavaDoc;
84 import java.net.MalformedURLException JavaDoc;
85 import java.net.URL JavaDoc;
86 import java.util.ArrayList JavaDoc;
87 import java.util.HashMap JavaDoc;
88 import java.util.Hashtable JavaDoc;
89 import java.util.Iterator JavaDoc;
90 import java.util.List JavaDoc;
91 import java.util.Map JavaDoc;
92 import java.util.StringTokenizer JavaDoc;
93 import java.util.Vector JavaDoc;
94 import java.rmi.RemoteException JavaDoc;
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 JavaDoc {
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 JavaDoc portName = null;
138     private QName JavaDoc portTypeName = null;
139     private QName JavaDoc 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 JavaDoc username = null;
148     private String JavaDoc password = null;
149     private boolean maintainSession = false;
150     private boolean useSOAPAction = false;
151     private String JavaDoc SOAPActionURI = null;
152     private Integer JavaDoc 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 JavaDoc transportName = null ;
167
168     // A couple places to store output parameters.
169
// As a HashMap, retrievable via QName (for getOutputParams).
170
private HashMap JavaDoc outParams = null;
171     // As a list, retrievable by index (for getOutputValues).
172
private ArrayList JavaDoc outParamsList = null;
173
174     // A place to store any client-specified headers
175
private Vector JavaDoc myHeaders = null;
176
177     public static final String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc WSDL_PORT_NAME = "wsdl.portName";
210
211     /**
212      * @deprecated use WSDL_SERVICE instead.
213      */

214     public static final String JavaDoc JAXRPC_SERVICE = WSDL_SERVICE;
215
216     /**
217      * @deprecated use WSDL_PORT_NAME instead.
218      */

219     public static final String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc ATTACHMENT_ENCAPSULATION_FORMAT=
242       "attachment_encapsulation_format";
243     /**
244      * Property value for setting attachment format as MIME.
245      */

246     public static final String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc [] modes = new ParameterMode JavaDoc [] { 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 JavaDoc attachmentParts = new java.util.Vector JavaDoc();
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 JavaDoc url) throws MalformedURLException JavaDoc {
338         this(new Service());
339         setTargetEndpointAddress(new URL JavaDoc(url));
340     }
341
342     /**
343      * Build a call from a URL.
344      *
345      * @param url the target endpoint URL
346      */

347     public Call(URL JavaDoc 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 JavaDoc name, Object JavaDoc value) {
391         if (name == null || value == null) {
392             throw new JAXRPCException JavaDoc(
393                     Messages.getMessage(name == null ?
394                                          "badProp03" : "badProp04"));
395         }
396         else if (name.equals(USERNAME_PROPERTY)) {
397             verifyStringProperty(name, value);
398             setUsername((String JavaDoc) value);
399         }
400         else if (name.equals(PASSWORD_PROPERTY)) {
401             verifyStringProperty(name, value);
402             setPassword((String JavaDoc) value);
403         }
404         else if (name.equals(SESSION_MAINTAIN_PROPERTY)) {
405             verifyBooleanProperty(name, value);
406             setMaintainSession(((Boolean JavaDoc) value).booleanValue());
407         }
408         else if (name.equals(OPERATION_STYLE_PROPERTY)) {
409             verifyStringProperty(name, value);
410             setOperationStyle((String JavaDoc) 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 JavaDoc) value).booleanValue());
421         }
422         else if (name.equals(SOAPACTION_URI_PROPERTY)) {
423             verifyStringProperty(name, value);
424             setSOAPActionURI((String JavaDoc) value);
425         }
426         else if (name.equals(ENCODINGSTYLE_URI_PROPERTY)) {
427             verifyStringProperty(name, value);
428             setEncodingStyle((String JavaDoc) value);
429         }
430         else if (name.equals(Stub.ENDPOINT_ADDRESS_PROPERTY)) {
431             verifyStringProperty(name, value);
432             setTargetEndpointAddress((String JavaDoc) value);
433         }
434         else if ( name.equals(TRANSPORT_NAME) ) {
435             verifyStringProperty(name, value);
436             transportName = (String JavaDoc) value ;
437             if (transport != null) {
438                 transport.setTransportName((String JavaDoc) 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 JavaDoc(
446                         Messages.getMessage("badattachmenttypeerr", new String JavaDoc[] {
447                         (String JavaDoc) 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 JavaDoc)value);
453         }
454         else if (name.equals(STREAMING_PROPERTY)) {
455             verifyBooleanProperty(name, value);
456             setStreaming(((Boolean JavaDoc) 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 JavaDoc(
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 JavaDoc name, Object JavaDoc value) {
476         if (!(value instanceof String JavaDoc)) {
477             throw new JAXRPCException JavaDoc(
478                     Messages.getMessage("badProp00", new String JavaDoc[]
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 JavaDoc name, Object JavaDoc value) {
493         if (!(value instanceof Boolean JavaDoc)) {
494             throw new JAXRPCException JavaDoc(
495                     Messages.getMessage("badProp00", new String JavaDoc[]
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 JavaDoc name, Object JavaDoc value) {
510         if (!(value instanceof Integer JavaDoc)) {
511             throw new JAXRPCException JavaDoc(
512                     Messages.getMessage("badProp00", new String JavaDoc[]
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 JavaDoc getProperty(String JavaDoc name) {
527         if (name == null || !isPropertySupported(name)) {
528             throw new JAXRPCException JavaDoc(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 JavaDoc name) {
541          if (name == null || !isPropertySupported(name)) {
542             throw new JAXRPCException JavaDoc(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 JavaDoc propertyNames = new ArrayList JavaDoc();
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 JavaDoc getPropertyNames() {
569         return propertyNames.iterator();
570     }
571
572     public boolean isPropertySupported(String JavaDoc 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 JavaDoc username) {
583         this.username = username;
584     } // setUsername
585

586     /**
587      * Get the user name.
588      *
589      * @return the user name
590      */

591     public String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc address) {
798         URL JavaDoc urlAddress;
799         try {
800             urlAddress = new URL JavaDoc(address);
801         }
802         catch (MalformedURLException JavaDoc mue) {
803             throw new JAXRPCException JavaDoc(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 JavaDoc address) {
816         try {
817             if ( address == null ) {
818                 setTransport(null);
819                 return ;
820             }
821
822             String JavaDoc 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 JavaDoc oldAddr = this.transport.getUrl();
834                 if ( oldAddr != null && !oldAddr.equals("") ) {
835                     URL JavaDoc tmpURL = new URL JavaDoc( oldAddr );
836                     String JavaDoc 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 JavaDoc 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 JavaDoc getTargetEndpointAddress() {
875         try {
876             if ( transport == null ) return( null );
877             return( transport.getUrl() );
878         }
879         catch( Exception JavaDoc exp ) {
880             return( null );
881         }
882     }
883
884     public Integer JavaDoc getTimeout() {
885         return timeout;
886     }
887
888     public void setTimeout(Integer JavaDoc 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 JavaDoc 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 JavaDoc paramName, QName JavaDoc xmlType,
930             ParameterMode JavaDoc parameterMode) {
931         Class JavaDoc 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 JavaDoc paramName, QName JavaDoc xmlType,
952             Class JavaDoc javaType, ParameterMode JavaDoc parameterMode) {
953
954         if (operationSetManually) {
955             throw new RuntimeException JavaDoc(
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 JavaDoc(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 JavaDoc paramName, QName JavaDoc xmlType,
989             ParameterMode JavaDoc parameterMode) {
990         Class JavaDoc javaType = null;
991         TypeMapping tm = getTypeMapping();
992         if (tm != null) {
993             javaType = tm.getClassForQName(xmlType);
994         }
995         addParameter(new QName JavaDoc("", 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 JavaDoc paramName, QName JavaDoc xmlType,
1016                             Class JavaDoc javaType, ParameterMode JavaDoc parameterMode) {
1017        addParameter(new QName JavaDoc("", 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 JavaDoc paramName, QName JavaDoc xmlType,
1036                                     ParameterMode JavaDoc parameterMode,
1037                                     ParameterMode JavaDoc headerMode) {
1038        Class JavaDoc 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 JavaDoc paramName, QName JavaDoc xmlType,
1063            Class JavaDoc javaType, ParameterMode JavaDoc parameterMode,
1064            ParameterMode JavaDoc headerMode) {
1065        if (operationSetManually) {
1066            throw new RuntimeException JavaDoc(
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 JavaDoc(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 JavaDoc getParameterTypeByName(String JavaDoc paramName) {
1107        QName JavaDoc paramQName = new QName JavaDoc("", 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 JavaDoc getParameterTypeByQName(QName JavaDoc 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 JavaDoc type) {
1134        if (operationSetManually) {
1135            throw new RuntimeException JavaDoc(
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 JavaDoc xmlType, Class JavaDoc 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 JavaDoc 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 JavaDoc xmlType, Class JavaDoc 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 JavaDoc 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 JavaDoc qname) {
1210        if (operationSetManually) {
1211            throw new RuntimeException JavaDoc(
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 JavaDoc cls) {
1237        if (operationSetManually) {
1238            throw new RuntimeException JavaDoc(
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 JavaDoc 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 JavaDoc 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 JavaDoc opName) {
1294        operationName = new QName JavaDoc(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 JavaDoc opName) {
1312        if ( service == null ) {
1313            throw new JAXRPCException JavaDoc( 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 JavaDoc( 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 JavaDoc( Messages.getMessage("noPortType00", "" +
1339                                                           portName) );
1340        }
1341        this.setPortTypeName(portType.getQName());
1342        
1343        List JavaDoc operations = portType.getOperations();
1344        if ( operations == null ) {
1345            throw new JAXRPCException JavaDoc( 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 JAXRPCException JavaDoc( Messages.getMessage("noOperation01",
1358                                                           opName) );
1359        }
1360
1361        // Get the SOAPAction
1362
////////////////////////////////////////////////////////////////////
1363
List JavaDoc list = port.getExtensibilityElements();
1364        String JavaDoc opStyle = null;
1365        BindingOperation bop = binding.getBindingOperation(opName,
1366                                                           null, null);
1367        if ( bop == null ) {
1368            throw new JAXRPCException JavaDoc( Messages.getMessage("noOperation02",
1369                                                            opName ));
1370        }
1371        list = bop.getExtensibilityElements();
1372        for ( int i = 0 ; list != null && i < list.size() ; i++ ) {
1373            Object JavaDoc obj = list.get(i);
1374            if ( obj instanceof SOAPOperation ) {
1375                SOAPOperation sop = (SOAPOperation) obj ;
1376                opStyle = ((SOAPOperation) obj).getStyle();
1377                String JavaDoc action = sop.getSoapActionURI();
1378                if ( action != null ) {
1379                    setUseSOAPAction(true);
1380                    setSOAPActionURI(action);
1381                }
1382                else {
1383                    setUseSOAPAction(false);
1384                    setSOAPActionURI(null);
1385                }
1386                break ;
1387            }
1388        }
1389
1390        // Get the body's namespace URI and encoding style
1391
////////////////////////////////////////////////////////////////////
1392
BindingInput bIn = bop.getBindingInput();
1393        if ( bIn != null ) {
1394            list = bIn.getExtensibilityElements();
1395            for ( int i = 0 ; list != null && i < list.size() ; i++ ) {
1396                Object JavaDoc obj = list.get(i);
1397                if( obj instanceof MIMEMultipartRelated){
1398                  MIMEMultipartRelated mpr=(MIMEMultipartRelated) obj;
1399                  Object JavaDoc part= null;
1400                  List JavaDoc l= mpr.getMIMEParts();
1401                  for(int j=0; l!= null && j< l.size() && part== null; j++){
1402                     MIMEPart mp = (MIMEPart)l.get(j);
1403                     List JavaDoc ll= mp.getExtensibilityElements();
1404                     for(int k=0; ll != null && k < ll.size() && part == null;
1405                           k++){
1406                       part= ll.get(k);
1407                       if ( !(part instanceof SOAPBody)) {
1408                           part = null;
1409                       }
1410                     }
1411                  }
1412                  if(null != part) {
1413                      obj= part;
1414                  }
1415                }
1416
1417                if ( obj instanceof SOAPBody ) {
1418                    SOAPBody sBody = (SOAPBody) obj ;
1419                    list = sBody.getEncodingStyles();
1420                    if ( list != null && list.size() > 0 ) {
1421                        this.setEncodingStyle( (String JavaDoc) list.get(0) );
1422                    }
1423                    String JavaDoc ns = sBody.getNamespaceURI();
1424                    if (ns != null && !ns.equals("")) {
1425                      setOperationName( new QName JavaDoc( ns, opName ) );
1426                    }
1427                    break ;
1428                }
1429            }
1430        }
1431
1432        Service service = this.getService();
1433        SymbolTable symbolTable = service.getWSDLParser().getSymbolTable();
1434        BindingEntry bEntry = symbolTable.getBindingEntry(binding.getQName());
1435        Parameters parameters = bEntry.getParameters(bop.getOperation());
1436
1437        // loop over paramters and set up in/out params
1438
for (int j = 0; j < parameters.list.size(); ++j) {
1439            Parameter p = (Parameter) parameters.list.get(j);
1440            // Get the QName representing the parameter type
1441
QName JavaDoc paramType = Utils.getXSIType(p);
1442
1443            // checks whether p is an IN or OUT header
1444
// and adds it as a header parameter else
1445
// add it to the body
1446
ParameterMode JavaDoc mode = modes[p.getMode()];
1447            if (p.isInHeader() || p.isOutHeader()) {
1448                this.addParameterAsHeader(p.getQName(), paramType,
1449                        mode, mode);
1450            } else {
1451                this.addParameter(p.getQName(), paramType, mode);
1452            }
1453        }
1454
1455        Map JavaDoc faultMap = bEntry.getFaults();
1456        // Get the list of faults for this operation
1457
ArrayList JavaDoc faults = (ArrayList JavaDoc) faultMap.get(bop);
1458
1459        // check for no faults
1460
if (faults == null) {
1461            return;
1462        }
1463        // For each fault, register its information
1464
for (Iterator JavaDoc faultIt = faults.iterator(); faultIt.hasNext();) {
1465            FaultInfo info = (FaultInfo) faultIt.next();
1466            QName JavaDoc qname = info.getQName();
1467            info.getMessage();
1468
1469            // if no parts in fault, skip it!
1470
if (qname == null) {
1471                continue;
1472            }
1473
1474            QName JavaDoc xmlType = info.getXMLType();
1475            Class JavaDoc clazz = getTypeMapping().getClassForQName(xmlType);
1476            if (clazz != null) {
1477                addFault(qname, clazz, xmlType, true);
1478            } else {
1479                //we cannot map from the info to a java class
1480
//In Axis1.1 and before this was silently swallowed. Now we log it
1481

1482                log.debug(Messages.getMessage("clientNoTypemapping", xmlType.toString()));
1483            }
1484        }
1485
1486        // set output type
1487
if (parameters.returnParam != null) {
1488            // Get the QName for the return Type
1489
QName JavaDoc returnType = Utils.getXSIType(parameters.returnParam);
1490            QName JavaDoc returnQName = parameters.returnParam.getQName();
1491
1492            // Get the javaType
1493
String JavaDoc javaType = null;
1494            if (parameters.returnParam.getMIMEInfo() != null) {
1495                javaType = "javax.activation.DataHandler";
1496            }
1497            else {
1498                javaType = parameters.returnParam.getType().getName();
1499            }
1500            if (javaType == null) {
1501                javaType = "";
1502            }
1503            else {
1504                javaType = javaType + ".class";
1505            }
1506            this.setReturnType(returnType);
1507            try {
1508                Class JavaDoc clazz = ClassUtils.forName(javaType);
1509                this.setReturnClass(clazz);
1510            } catch (ClassNotFoundException JavaDoc swallowedException) {
1511                //log that this lookup failed,
1512
log.debug(Messages.getMessage("clientNoReturnClass",
1513                        javaType));
1514            }
1515            this.setReturnQName(returnQName);
1516        }
1517        else {
1518            this.setReturnType(org.apache.axis.encoding.XMLType.AXIS_VOID);
1519        }
1520
1521        boolean hasMIME = Utils.hasMIME(bEntry, bop);
1522        Use use = bEntry.getInputBodyType(bop.getOperation());
1523        setOperationUse(use);
1524        if (use == Use.LITERAL) {
1525            // Turn off encoding
1526
setEncodingStyle(null);
1527            // turn off XSI types
1528
setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
1529        }
1530        if (hasMIME || use == Use.LITERAL) {
1531            // If it is literal, turn off multirefs.
1532
//
1533
// If there are any MIME types, turn off multirefs.
1534
// I don't know enough about the guts to know why
1535
// attachments don't work with multirefs, but they don't.
1536
setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
1537        }
1538
1539        Style style = Style.getStyle(opStyle, bEntry.getBindingStyle());
1540        if (style == Style.DOCUMENT && symbolTable.isWrapped()) {
1541            style = Style.WRAPPED;
1542        }
1543        setOperationStyle(style);
1544
1545        // Operation name
1546
if (style == Style.WRAPPED) {
1547            // We need to make sure the operation name, which is what we
1548
// wrap the elements in, matches the Qname of the parameter
1549
// element.
1550
Map JavaDoc partsMap = bop.getOperation().getInput().getMessage().getParts();
1551            Part p = (Part)partsMap.values().iterator().next();
1552            QName JavaDoc q = p.getElementName();
1553            setOperationName(q);
1554        } else {
1555            QName JavaDoc elementQName =
1556                Utils.getOperationQName(bop, bEntry, symbolTable);
1557            if (elementQName != null) {
1558                setOperationName(elementQName);
1559            }
1560        }
1561
1562        // Indicate that the parameters and return no longer
1563
// need to be specified with addParameter calls.
1564
parmAndRetReq = false;
1565        return;
1566
1567    }
1568
1569
1570    /**
1571     * prefill as much info from the WSDL as it can.
1572     * Right now it's target URL, SOAPAction, Parameter types,
1573     * and return type of the Web Service.
1574     *
1575     * If wsdl is not present, this function set port name and operation name
1576     * and does not modify target endpoint address.
1577     *
1578     * Note: Not part of JAX-RPC specification.
1579     *
1580     * @param portName PortName in the WSDL doc to search for
1581     * @param opName Operation(method) that's going to be invoked
1582     */

1583    public void setOperation(QName JavaDoc portName, String JavaDoc opName) {
1584        setOperation(portName, new QName JavaDoc(opName));
1585    }
1586
1587    
1588    /**
1589     * prefill as much info from the WSDL as it can.
1590     * Right now it's target URL, SOAPAction, Parameter types,
1591     * and return type of the Web Service.
1592     *
1593     * If wsdl is not present, this function set port name and operation name
1594     * and does not modify target endpoint address.
1595     *
1596     * Note: Not part of JAX-RPC specification.
1597     *
1598     * @param portName PortName in the WSDL doc to search for
1599     * @param opName Operation(method) that's going to be invoked
1600     */

1601    public void setOperation(QName JavaDoc portName, QName JavaDoc opName) {
1602        if ( service == null )
1603            throw new JAXRPCException JavaDoc( Messages.getMessage("noService04") );
1604
1605        // Make sure we're making a fresh start.
1606
this.setPortName( portName );
1607        this.setOperationName( opName );
1608        this.setReturnType( null );
1609        this.removeAllParameters();
1610
1611        javax.wsdl.Service wsdlService = service.getWSDLService();
1612        // Nothing to do is the WSDL is not already set.
1613
if(wsdlService == null) {
1614            return;
1615        }
1616
1617        // we reinitialize target endpoint only if we have wsdl
1618
this.setTargetEndpointAddress( (URL JavaDoc) null );
1619
1620        Port port = wsdlService.getPort( portName.getLocalPart() );
1621        if ( port == null ) {
1622            throw new JAXRPCException JavaDoc( Messages.getMessage("noPort00", "" +
1623                                                           portName) );
1624        }
1625
1626        // Get the URL
1627
////////////////////////////////////////////////////////////////////
1628
List JavaDoc list = port.getExtensibilityElements();
1629        for ( int i = 0 ; list != null && i < list.size() ; i++ ) {
1630            Object JavaDoc obj = list.get(i);
1631            if ( obj instanceof SOAPAddress ) {
1632                try {
1633                    SOAPAddress addr = (SOAPAddress) obj ;
1634                    URL JavaDoc url = new URL JavaDoc(addr.getLocationURI());
1635                    this.setTargetEndpointAddress(url);
1636                }
1637                catch(Exception JavaDoc exp) {
1638                    throw new JAXRPCException JavaDoc(
1639                            Messages.getMessage("cantSetURI00", "" + exp) );
1640                }
1641            }
1642        }
1643
1644        setOperation(opName.getLocalPart());
1645    }
1646
1647    /**
1648     * Returns the fully qualified name of the port for this Call object
1649     * (if there is one).
1650     *
1651     * @return QName Fully qualified name of the port (or null if not set)
1652     */

1653    public QName JavaDoc getPortName() {
1654        return( portName );
1655    } // getPortName
1656

1657    /**
1658     * Sets the port name of this Call object. This call will not set
1659     * any additional fields, nor will it do any checking to verify that
1660     * this port name is actually defined in the WSDL - for now anyway.
1661     *
1662     * @param portName Fully qualified name of the port
1663     */

1664    public void setPortName(QName JavaDoc portName) {
1665        this.portName = portName;
1666    } // setPortName
1667

1668    /**
1669     * Returns the fully qualified name of the port type for this Call object
1670     * (if there is one).
1671     *
1672     * @return QName Fully qualified name of the port type
1673     */

1674    public QName JavaDoc getPortTypeName() {
1675        return portTypeName == null ? new QName JavaDoc("") : portTypeName;
1676    }
1677
1678    /**
1679     * Sets the port type name of this Call object. This call will not set
1680     * any additional fields, nor will it do any checking to verify that
1681     * this port type is actually defined in the WSDL - for now anyway.
1682     *
1683     * @param portType Fully qualified name of the portType
1684     */

1685    public void setPortTypeName(QName JavaDoc portType) {
1686        this.portTypeName = portType;
1687    }
1688
1689    /**
1690     * Allow the user to set the default SOAP version. For SOAP 1.2, pass
1691     * SOAPConstants.SOAP12_CONSTANTS.
1692     *
1693     * @param soapConstants the SOAPConstants object representing the correct
1694     * version
1695     */

1696    public void setSOAPVersion(SOAPConstants soapConstants) {
1697        msgContext.setSOAPConstants(soapConstants);
1698    }
1699
1700    /**
1701     * Invokes a specific operation using a synchronous request-response interaction mode. The invoke method takes
1702     * as parameters the object values corresponding to these defined parameter types. Implementation of the invoke
1703     * method must check whether the passed parameter values correspond to the number, order and types of parameters
1704     * specified in the corresponding operation specification.
1705     *
1706     * @param operationName - Name of the operation to invoke
1707     * @param params - Parameters for this invocation
1708     *
1709     * @return the value returned from the other end.
1710     *
1711     * @throws java.rmi.RemoteException - if there is any error in the remote method invocation or if the Call
1712     * object is not configured properly.
1713     */

1714    public Object JavaDoc invoke(QName JavaDoc operationName, Object JavaDoc[] params)
1715      throws java.rmi.RemoteException JavaDoc {
1716        QName JavaDoc origOpName = this.operationName;
1717        this.operationName = operationName;
1718        try {
1719            return this.invoke(params);
1720        }
1721        catch (AxisFault af) {
1722            this.operationName = origOpName;
1723            if(af.detail != null && af.detail instanceof RemoteException JavaDoc) {
1724                throw ((RemoteException JavaDoc)af.detail);
1725            }
1726            throw af;
1727        }
1728        catch (java.rmi.RemoteException JavaDoc re) {
1729            this.operationName = origOpName;
1730            throw re;
1731        }
1732        catch (RuntimeException JavaDoc re) {
1733            this.operationName = origOpName;
1734            throw re;
1735        }
1736        catch (Error JavaDoc e) {
1737            this.operationName = origOpName;
1738            throw e;
1739        }
1740    } // invoke
1741

1742    /**
1743     * Invokes the operation associated with this Call object using the
1744     * passed in parameters as the arguments to the method.
1745     *
1746     * For Messaging (ie. non-RPC) the params argument should be an array
1747     * of SOAPBodyElements. <b>All</b> of them need to be SOAPBodyElements,
1748     * if any of them are not this method will default back to RPC. In the
1749     * Messaging case the return value will be a vector of SOAPBodyElements.
1750     *
1751     * @param params Array of parameters to invoke the Web Service with
1752     * @return Object Return value of the operation/method - or null
1753     * @throws java.rmi.RemoteException if there's an error
1754     */

1755    public Object JavaDoc invoke(Object JavaDoc[] params) throws java.rmi.RemoteException JavaDoc {
1756        long t0=0, t1=0;
1757        if( tlog.isDebugEnabled() ) {
1758            t0=System.currentTimeMillis();
1759        }
1760        /* First see if we're dealing with Messaging instead of RPC. */
1761        /* If ALL of the params are SOAPBodyElements then we're doing */
1762        /* Messaging, otherwise just fall through to normal RPC processing. */
1763        /********************************************************************/
1764        SOAPEnvelope env = null ;
1765        int i ;
1766
1767        for ( i = 0 ; params != null && i < params.length ; i++ )
1768            if ( !(params[i] instanceof SOAPBodyElement) ) break ;
1769
1770        if ( params != null && params.length > 0 && i == params.length ) {
1771            /* ok, we're doing Messaging, so build up the message */
1772            /******************************************************/
1773            isMsg = true ;
1774            env = new SOAPEnvelope(msgContext.getSOAPConstants(),
1775                                   msgContext.getSchemaVersion());
1776
1777            for (i = 0; i < params.length; i++) {
1778                env.addBodyElement((SOAPBodyElement) params[i]);
1779            }
1780
1781            Message msg = new Message( env );
1782            setRequestMessage(msg);
1783
1784            invoke();
1785
1786            msg = msgContext.getResponseMessage();
1787            if (msg == null) {
1788              if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) {
1789                throw new AxisFault(Messages.getMessage("nullResponse00"));
1790              } else {
1791                return null;
1792              }
1793            }
1794
1795            env = msg.getSOAPEnvelope();
1796            return( env.getBodyElements() );
1797        }
1798
1799
1800        if ( operationName == null ) {
1801            throw new AxisFault( Messages.getMessage("noOperation00") );
1802        }
1803        try {
1804            Object JavaDoc res=this.invoke(operationName.getNamespaceURI(),
1805                    operationName.getLocalPart(), params);
1806            if( tlog.isDebugEnabled() ) {
1807                t1=System.currentTimeMillis();
1808                tlog.debug("axis.Call.invoke: " + (t1-t0) + " " + operationName);
1809            }
1810            return res;
1811        }
1812        catch( AxisFault af) {
1813            if(af.detail != null && af.detail instanceof RemoteException JavaDoc) {
1814                throw ((RemoteException JavaDoc)af.detail);
1815            }
1816            throw af;
1817        }
1818        catch( Exception JavaDoc exp ) {
1819            entLog.debug(Messages.getMessage("toAxisFault00"), exp);
1820            throw AxisFault.makeFault(exp);
1821        }
1822    }
1823
1824    /**
1825     * Invokes the operation associated with this Call object using the passed
1826     * in parameters as the arguments to the method. This will return
1827     * immediately rather than waiting for the server to complete its
1828     * processing.
1829     *
1830     * NOTE: the return immediately part isn't implemented yet
1831     *
1832     * @param params Array of parameters to invoke the Web Service with
1833     * @throws JAXRPCException is there's an error
1834     */

1835    public void invokeOneWay(Object JavaDoc[] params) {
1836        try {
1837            invokeOneWay = true;
1838            invoke( params );
1839        } catch( Exception JavaDoc exp ) {
1840            throw new JAXRPCException JavaDoc( exp.toString() );
1841        } finally {
1842            invokeOneWay = false;
1843        }
1844    }
1845
1846    /************************************************************************/
1847    /* End of core JAX-RPC stuff */
1848    /************************************************************************/
1849
1850    /**
1851     * Invoke the service with a custom Message.
1852     * This method simplifies invoke(SOAPEnvelope).
1853     * <p>
1854     * Note: Not part of JAX-RPC specification.
1855     *
1856     * @param msg a Message to send
1857     * @throws AxisFault if there is any failure
1858     */

1859    public SOAPEnvelope invoke(Message msg) throws AxisFault {
1860        try {
1861            setRequestMessage( msg );
1862            invoke();
1863            msg = msgContext.getResponseMessage();
1864            if (msg == null) {
1865                if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) {
1866                    throw new AxisFault(Messages.getMessage("nullResponse00"));
1867                } else {
1868                    return null;
1869                }
1870            }
1871            SOAPEnvelope res = null;
1872            res = msg.getSOAPEnvelope();
1873            return res;
1874        }
1875        catch (Exception JavaDoc exp) {
1876            if (exp instanceof AxisFault) {
1877                throw (AxisFault) exp ;
1878            }
1879            entLog.debug(Messages.getMessage("toAxisFault00"), exp);
1880            throw new AxisFault(
1881                    Messages.getMessage("errorInvoking00", "\n" + exp));
1882        }
1883    }
1884
1885    /**
1886     * Invoke the service with a custom SOAPEnvelope.
1887     * <p>
1888     * Note: Not part of JAX-RPC specification.
1889     *
1890     * @param env a SOAPEnvelope to send
1891     * @throws AxisFault if there is any failure
1892     */

1893    public SOAPEnvelope invoke(SOAPEnvelope env) throws AxisFault {
1894        try {
1895            Message msg = new Message( env );
1896            if (getProperty(CHARACTER_SET_ENCODING) != null) {
1897                msg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, getProperty(CHARACTER_SET_ENCODING));
1898            } else if (msgContext.getProperty(CHARACTER_SET_ENCODING) != null) {
1899                msg.setProperty(CHARACTER_SET_ENCODING, msgContext.getProperty(CHARACTER_SET_ENCODING));
1900            }
1901            setRequestMessage( msg );
1902            invoke();
1903            msg = msgContext.getResponseMessage();
1904            if (msg == null) {
1905              if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) {
1906                throw new AxisFault(Messages.getMessage("nullResponse00"));
1907              } else {
1908                return null;
1909              }
1910            }
1911            return( msg.getSOAPEnvelope() );
1912        }
1913        catch( Exception JavaDoc exp ) {
1914            if ( exp instanceof AxisFault ) {
1915                throw (AxisFault) exp ;
1916            }
1917
1918            entLog.debug(Messages.getMessage("toAxisFault00"), exp);
1919            throw AxisFault.makeFault(exp);
1920        }
1921    }
1922
1923
1924    /** Register a Transport that should be used for URLs of the specified
1925     * protocol.
1926     *
1927     * Note: Not part of JAX-RPC specification.
1928     *
1929     * @param protocol the URL protocol (i.e. "tcp" for "tcp://" urls)
1930     * @param transportClass the class of a Transport type which will be used
1931     * for matching URLs.
1932     */

1933    public static void setTransportForProtocol(String JavaDoc protocol,
1934                                               Class JavaDoc transportClass) {
1935        if (Transport.class.isAssignableFrom(transportClass)) {
1936            transports.put(protocol, transportClass);
1937        }
1938        else {
1939            throw new InternalException(transportClass.toString());
1940        }
1941    }
1942
1943    /**
1944     * Set up the default transport URL mappings.
1945     *
1946     * This must be called BEFORE doing non-standard URL parsing (i.e. if you
1947     * want the system to accept a "local:" URL). This is why the Options class
1948     * calls it before parsing the command-line URL argument.
1949     *
1950     * Note: Not part of JAX-RPC specification.
1951     */

1952    public static synchronized void initialize() {
1953        addTransportPackage("org.apache.axis.transport");
1954
1955        setTransportForProtocol("java",
1956                org.apache.axis.transport.java.JavaTransport.class);
1957        setTransportForProtocol("local",
1958                org.apache.axis.transport.local.LocalTransport.class);
1959        setTransportForProtocol("http", HTTPTransport.class);
1960        setTransportForProtocol("https", HTTPTransport.class);
1961    }
1962
1963    /**
1964     * Cache of transport packages we've already added to the system
1965     * property.
1966     */

1967    private static ArrayList JavaDoc transportPackages = null;
1968
1969    /** Add a package to the system protocol handler search path. This
1970     * enables users to create their own URLStreamHandler classes, and thus
1971     * allow custom protocols to be used in Axis (typically on the client
1972     * command line).
1973     *
1974     * For instance, if you add "samples.transport" to the packages property,
1975     * and have a class samples.transport.tcp.Handler, the system will be able
1976     * to parse URLs of the form "tcp://host:port..."
1977     *
1978     * Note: Not part of JAX-RPC specification.
1979     *
1980     * @param packageName the package in which to search for protocol names.
1981     */

1982    public static synchronized void addTransportPackage(String JavaDoc packageName) {
1983        if (transportPackages == null) {
1984            transportPackages = new ArrayList JavaDoc();
1985            String JavaDoc currentPackages =
1986                    AxisProperties.getProperty(TRANSPORT_PROPERTY);
1987            if (currentPackages != null) {
1988                StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(currentPackages,
1989                                                          "|");
1990                while (tok.hasMoreTokens()) {
1991                    transportPackages.add(tok.nextToken());
1992                }
1993            }
1994        }
1995
1996        if (transportPackages.contains(packageName)) {
1997            return;
1998        }
1999
2000        transportPackages.add(packageName);
2001
2002        StringBuffer JavaDoc currentPackages = new StringBuffer JavaDoc();
2003        for (Iterator JavaDoc i = transportPackages.iterator(); i.hasNext();) {
2004            String JavaDoc thisPackage = (String JavaDoc) i.next();
2005            currentPackages.append(thisPackage);
2006            currentPackages.append('|');
2007        }
2008
2009        System.setProperty(TRANSPORT_PROPERTY, currentPackages.toString());
2010    }
2011
2012    /**
2013     * Convert the list of objects into RPCParam's based on the paramNames,
2014     * paramXMLTypes and paramModes variables. If those aren't set then just
2015     * return what was passed in.
2016     *
2017     * @param params Array of parameters to pass into the operation/method
2018     * @return Object[] Array of parameters to pass to invoke()
2019     */

2020    private Object JavaDoc[] getParamList(Object JavaDoc[] params) {
2021        int numParams = 0 ;
2022
2023        // If we never set-up any names... then just return what was passed in
2024
//////////////////////////////////////////////////////////////////////
2025
if (log.isDebugEnabled()) {
2026            log.debug( "operation=" + operation);
2027            if (operation != null) {
2028                log.debug("operation.getNumParams()=" +
2029                          operation.getNumParams());
2030            }
2031        }
2032        if ( operation == null || operation.getNumParams() == 0 ) {
2033            return( params );
2034        }
2035
2036        // Count the number of IN and INOUT params, this needs to match the
2037
// number of params passed in - if not throw an error
2038
/////////////////////////////////////////////////////////////////////
2039
numParams = operation.getNumInParams();
2040
2041        if ( params == null || numParams != params.length ) {
2042            throw new JAXRPCException JavaDoc(
2043                    Messages.getMessage(
2044                              "parmMismatch00",
2045                              (params == null) ? "no params" : "" + params.length,
2046                              "" + numParams
2047                   )
2048           );
2049        }
2050
2051        log.debug( "getParamList number of params: " + params.length);
2052
2053        // All ok - so now produce an array of RPCParams
2054
//////////////////////////////////////////////////
2055
Vector JavaDoc result = new Vector JavaDoc();
2056        int j = 0 ;
2057        ArrayList JavaDoc parameters = operation.getParameters();
2058
2059        for (int i = 0; i < parameters.size(); i++) {
2060            ParameterDesc param = (ParameterDesc)parameters.get(i);
2061            if (param.getMode() != ParameterDesc.OUT) {
2062                QName JavaDoc paramQName = param.getQName();
2063
2064                // Create an RPCParam if param isn't already an RPCParam.
2065
RPCParam rpcParam = null;
2066                Object JavaDoc p = params[j++];
2067                if(p instanceof RPCParam) {
2068                    rpcParam = (RPCParam)p;
2069                } else {
2070                    rpcParam = new RPCParam(paramQName.getNamespaceURI(),
2071                                            paramQName.getLocalPart(),
2072                                            p);
2073                }
2074                // Attach the ParameterDescription to the RPCParam
2075
// so that the serializer can use the (javaType, xmlType)
2076
// information.
2077
rpcParam.setParamDesc(param);
2078
2079                // Add the param to the header or vector depending
2080
// on whether it belongs in the header or body.
2081
if (param.isInHeader()) {
2082                    addHeader(new RPCHeaderParam(rpcParam));
2083                } else {
2084                    result.add(rpcParam);
2085                }
2086            }
2087        }
2088        return( result.toArray() );
2089    }
2090
2091    /**
2092     * Set the Transport
2093     *
2094     * Note: Not part of JAX-RPC specification.
2095     *
2096     * @param trans the Transport object we'll use to set up
2097     * MessageContext properties.
2098     */

2099    public void setTransport(Transport trans) {
2100        transport = trans;
2101        if (log.isDebugEnabled())
2102            log.debug(Messages.getMessage("transport00", "" + transport));
2103    }
2104
2105    /** Get the Transport registered for the given protocol.
2106     *
2107     * Note: Not part of JAX-RPC specification.
2108     *
2109     * @param protocol a protocol such as "http" or "local" which may
2110     * have a Transport object associated with it.
2111     * @return the Transport registered for this protocol, or null if none.
2112     */

2113    public Transport getTransportForProtocol(String JavaDoc protocol)
2114    {
2115        Class JavaDoc transportClass = (Class JavaDoc)transports.get(protocol);
2116        Transport ret = null;
2117        if (transportClass != null) {
2118            try {
2119                ret = (Transport)transportClass.newInstance();
2120            } catch (InstantiationException JavaDoc e) {
2121            } catch (IllegalAccessException JavaDoc e) {
2122            }
2123        }
2124        return ret;
2125    }
2126
2127    /**
2128     * Directly set the request message in our MessageContext.
2129     *
2130     * This allows custom message creation.
2131     *
2132     * Note: Not part of JAX-RPC specification.
2133     *
2134     * @param msg the new request message.
2135     * @throws RuntimeException containing the text of an AxisFault, if any
2136     * AxisFault was thrown
2137     */

2138    public void setRequestMessage(Message msg) {
2139         String JavaDoc attachformat= (String JavaDoc)getProperty(
2140           ATTACHMENT_ENCAPSULATION_FORMAT);
2141
2142         if(null != attachformat) {
2143              Attachments attachments=msg.getAttachmentsImpl();
2144              if(null != attachments) {
2145                  if( ATTACHMENT_ENCAPSULATION_FORMAT_MIME.equals(attachformat)) {
2146                    attachments.setSendType(Attachments.SEND_TYPE_MIME);
2147                  } else if ( ATTACHMENT_ENCAPSULATION_FORMAT_DIME.equals(attachformat)) {
2148                    attachments.setSendType(Attachments.SEND_TYPE_DIME);
2149                  }
2150              }
2151         }
2152
2153        if(null != attachmentParts && !attachmentParts.isEmpty()){
2154            try{
2155                Attachments attachments= msg.getAttachmentsImpl();
2156                if(null == attachments) {
2157                  throw new RuntimeException JavaDoc(
2158                          Messages.getMessage("noAttachments"));
2159                }
2160
2161                attachments.setAttachmentParts(attachmentParts);
2162            }catch(AxisFault ex){
2163              log.info(Messages.getMessage("axisFault00"), ex);
2164              throw new RuntimeException JavaDoc(ex.getMessage());
2165            }
2166        }
2167
2168        msgContext.setRequestMessage(msg);
2169        attachmentParts.clear();
2170    }
2171
2172    /**
2173     * Directly get the response message in our MessageContext.
2174     *
2175     * Shortcut for having to go thru the msgContext
2176     *
2177     * Note: Not part of JAX-RPC specification.
2178     *
2179     * @return the response Message object in the msgContext
2180     */

2181    public Message getResponseMessage() {
2182        return msgContext.getResponseMessage();
2183    }
2184
2185    /**
2186     * Obtain a reference to our MessageContext.
2187     *
2188     * Note: Not part of JAX-RPC specification.
2189     *
2190     * @return the MessageContext.
2191     */

2192    public MessageContext getMessageContext () {
2193        return msgContext;
2194    }
2195
2196    /**
2197     * Add a header which should be inserted into each outgoing message
2198     * we generate.
2199     *
2200     * Note: Not part of JAX-RPC specification.
2201     *
2202     * @param header a SOAPHeaderElement to be inserted into messages
2203     */

2204    public void addHeader(SOAPHeaderElement header)
2205    {
2206        if (myHeaders == null) {
2207            myHeaders = new Vector JavaDoc();
2208        }
2209        myHeaders.add(header);
2210    }
2211
2212    /**
2213     * Clear the list of headers which we insert into each message
2214     *
2215     * Note: Not part of JAX-RPC specification.
2216     */

2217    public void clearHeaders()
2218    {
2219        myHeaders = null;
2220    }
2221
2222    public TypeMapping getTypeMapping()
2223    {
2224        // Get the TypeMappingRegistry
2225
TypeMappingRegistry tmr = msgContext.getTypeMappingRegistry();
2226
2227        // If a TypeMapping is not available, add one.
2228
return tmr.getOrMakeTypeMapping(getEncodingStyle());
2229    }
2230
2231    /**
2232     * Register type mapping information for serialization/deserialization
2233     *
2234     * Note: Not part of JAX-RPC specification.
2235     *
2236     * @param javaType is the Java class of the data type.
2237     * @param xmlType the xsi:type QName of the associated XML type.
2238     * @param sf/df are the factories (or the Class objects of the factory).
2239     */

2240    public void registerTypeMapping(Class JavaDoc javaType, QName JavaDoc xmlType,
2241                                    SerializerFactory sf,
2242                                    DeserializerFactory df) {
2243        registerTypeMapping(javaType, xmlType, sf, df, true);
2244    }
2245
2246    /**
2247     * Register type mapping information for serialization/deserialization
2248     *
2249     * Note: Not part of JAX-RPC specification.
2250     *
2251     * @param javaType is the Java class of the data type.
2252     * @param xmlType the xsi:type QName of the associated XML type.
2253     * @param sf/df are the factories (or the Class objects of the factory).
2254     * @param force Indicates whether to add the information if already registered.
2255     */

2256    public void registerTypeMapping(Class JavaDoc javaType, QName JavaDoc xmlType,
2257                                    SerializerFactory sf,
2258                                    DeserializerFactory df,
2259                                    boolean force) {
2260        TypeMapping tm = getTypeMapping();
2261        if (!force && tm.isRegistered(javaType, xmlType)) {
2262            return;
2263        }
2264
2265        // Register the information
2266
tm.register(javaType, xmlType, sf, df);
2267    }
2268
2269    /**
2270     * register this type matting
2271     * @param javaType
2272     * @param xmlType
2273     * @param sfClass
2274     * @param dfClass
2275     */

2276    public void registerTypeMapping(Class JavaDoc javaType, QName JavaDoc xmlType,
2277                                    Class JavaDoc sfClass, Class JavaDoc dfClass) {
2278        registerTypeMapping(javaType, xmlType, sfClass, dfClass, true);
2279    }
2280
2281    /**
2282     * register a type. This only takes place if either the serializer or
2283     * deserializer factory could be created.
2284     * @param javaType java type to handle
2285     * @param xmlType XML mapping
2286     * @param sfClass class of serializer factory
2287     * @param dfClass class of deserializer factory
2288     * @param force
2289     */

2290    public void registerTypeMapping(Class JavaDoc javaType,
2291                                    QName JavaDoc xmlType,
2292                                    Class JavaDoc sfClass,
2293                                    Class JavaDoc dfClass,
2294                                    boolean force) {
2295        // Instantiate the factory using introspection.
2296
SerializerFactory sf =
2297                BaseSerializerFactory.createFactory(sfClass, javaType, xmlType);
2298        DeserializerFactory df =
2299                BaseDeserializerFactory.createFactory(dfClass,
2300                                                      javaType,
2301                                                      xmlType);
2302        if (sf != null || df != null) {
2303            registerTypeMapping(javaType, xmlType, sf, df, force);
2304        }
2305    }
2306
2307    /************************************************
2308     * Invocation
2309     */

2310
2311    /** Invoke an RPC service with a method name and arguments.
2312     *
2313     * This will call the service, serializing all the arguments, and
2314     * then deserialize the return value.
2315     *
2316     * Note: Not part of JAX-RPC specification.
2317     *
2318     * @param namespace the desired namespace URI of the method element
2319     * @param method the method name
2320     * @param args an array of Objects representing the arguments to the
2321     * invoked method. If any of these objects are RPCParams,
2322     * Axis will use the embedded name of the RPCParam as the
2323     * name of the parameter. Otherwise, we will serialize
2324     * each argument as an XML element called "arg<n>".
2325     * @return a deserialized Java Object containing the return value
2326     * @exception AxisFault
2327     */

2328    public Object JavaDoc invoke(String JavaDoc namespace, String JavaDoc method, Object JavaDoc[] args)
2329                    throws AxisFault {
2330
2331        if (log.isDebugEnabled()) {
2332            log.debug("Enter: Call::invoke(ns, meth, args)");
2333        }
2334
2335        /**
2336         * Since JAX-RPC requires us to specify all or nothing, if setReturnType
2337         * was called (returnType != null) and we have args but addParameter
2338         * wasn't called (paramXMLTypes == null), then toss a fault.
2339         */

2340        if (getReturnType() != null && args != null && args.length != 0
2341                && operation.getNumParams() == 0) {
2342            throw new AxisFault(Messages.getMessage("mustSpecifyParms"));
2343        }
2344
2345        RPCElement body = new RPCElement(namespace, method, getParamList(args));
2346
2347        Object JavaDoc ret = invoke( body );
2348
2349        if (log.isDebugEnabled()) {
2350            log.debug("Exit: Call::invoke(ns, meth, args)");
2351        }
2352
2353        return ret;
2354    }
2355
2356    /** Convenience method to invoke a method with a default (empty)
2357     * namespace. Calls invoke() above.
2358     *
2359     * Note: Not part of JAX-RPC specification.
2360     *
2361     * @param method the method name
2362     * @param args an array of Objects representing the arguments to the
2363     * invoked method. If any of these objects are RPCParams,
2364     * Axis will use the embedded name of the RPCParam as the
2365     * name of the parameter. Otherwise, we will serialize
2366     * each argument as an XML element called "arg<n>".
2367     * @return a deserialized Java Object containing the return value
2368     * @exception AxisFault
2369     */

2370    public Object JavaDoc invoke( String JavaDoc method, Object JavaDoc [] args ) throws AxisFault
2371    {
2372        return invoke("", method, args);
2373    }
2374
2375    /** Invoke an RPC service with a pre-constructed RPCElement.
2376     *
2377     * Note: Not part of JAX-RPC specification.
2378     *
2379     * @param body an RPCElement containing all the information about
2380     * this call.
2381     * @return a deserialized Java Object containing the return value
2382     * @exception AxisFault
2383     */

2384    public Object JavaDoc invoke( RPCElement body ) throws AxisFault {
2385        if (log.isDebugEnabled()) {
2386            log.debug("Enter: Call::invoke(RPCElement)");
2387        }
2388
2389        /**
2390         * Since JAX-RPC requires us to specify a return type if we've set
2391         * parameter types, check for this case right now and toss a fault
2392         * if things don't look right.
2393         */

2394        if (!invokeOneWay && operation != null &&
2395                operation.getNumParams() > 0 && getReturnType() == null) {
2396            // TCK:
2397
// Issue an error if the return type was not set, but continue processing.
2398
//throw new AxisFault(Messages.getMessage("mustSpecifyReturnType"));
2399
log.error(Messages.getMessage("mustSpecifyReturnType"));
2400        }
2401
2402        SOAPEnvelope reqEnv =
2403                new SOAPEnvelope(msgContext.getSOAPConstants(),
2404                                 msgContext.getSchemaVersion());
2405        SOAPEnvelope resEnv = null ;
2406        Message reqMsg = new Message( reqEnv );
2407        Message resMsg = null ;
2408        Vector JavaDoc resArgs = null ;
2409        Object JavaDoc result = null ;
2410
2411        // Clear the output params
2412
outParams = new HashMap JavaDoc();
2413        outParamsList = new ArrayList JavaDoc();
2414
2415        // Set both the envelope and the RPCElement encoding styles
2416
try {
2417            body.setEncodingStyle(getEncodingStyle());
2418
2419            setRequestMessage(reqMsg);
2420
2421            reqEnv.addBodyElement(body);
2422            reqEnv.setMessageType(Message.REQUEST);
2423
2424            invoke();
2425        } catch (Exception JavaDoc e) {
2426            entLog.debug(Messages.getMessage("toAxisFault00"), e);
2427            throw AxisFault.makeFault(e);
2428        }
2429
2430        resMsg = msgContext.getResponseMessage();
2431
2432        if (resMsg == null) {
2433          if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) {
2434            throw new AxisFault(Messages.getMessage("nullResponse00"));
2435          } else {
2436            return null;
2437          }
2438        }
2439
2440        resEnv = resMsg.getSOAPEnvelope();
2441        SOAPBodyElement bodyEl = resEnv.getFirstBody();
2442        if (bodyEl == null) {
2443            return null;
2444        }
2445
2446        if (bodyEl instanceof RPCElement) {
2447            try {
2448                resArgs = ((RPCElement) bodyEl).getParams();
2449            } catch (Exception JavaDoc e) {
2450                log.error(Messages.getMessage("exception00"), e);
2451                throw AxisFault.makeFault(e);
2452            }
2453
2454            if (resArgs != null && resArgs.size() > 0) {
2455
2456                // If there is no return, then we start at index 0 to create the outParams Map.
2457
// If there IS a return, then we start with 1.
2458
int outParamStart = 0;
2459
2460                // If we have resArgs and the returnType is specified, then the first
2461
// resArgs is the return. If we have resArgs and neither returnType
2462
// nor paramXMLTypes are specified, then we assume that the caller is
2463
// following the non-JAX-RPC AXIS shortcut of not having to specify
2464
// the return, in which case we again assume the first resArgs is
2465
// the return.
2466
// NOTE 1: the non-JAX-RPC AXIS shortcut allows a potential error
2467
// to escape notice. If the caller IS NOT following the non-JAX-RPC
2468
// shortcut but instead intentionally leaves returnType and params
2469
// null (ie., a method that takes no parameters and returns nothing)
2470
// then, if we DO receive something it should be an error, but this
2471
// code passes it through. The ideal solution here is to require
2472
// this caller to set the returnType to void, but there's no void
2473
// type in XML.
2474
// NOTE 2: we should probably verify that the resArgs element
2475
// types match the expected returnType and paramXMLTypes, but I'm not
2476
// sure how to do that since the resArgs value is a Java Object
2477
// and the returnType and paramXMLTypes are QNames.
2478

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

2483                boolean findReturnParam = false;
2484                QName JavaDoc returnParamQName = null;
2485                if (operation != null) {
2486                    returnParamQName = operation.getReturnQName();
2487                }
2488
2489                if (!XMLType.AXIS_VOID.equals(getReturnType())) {
2490                    if (returnParamQName == null) {
2491                        // Assume the first param is the return
2492
RPCParam param = (RPCParam)resArgs.get(0);
2493                        result = param.getObjectValue();
2494                        outParamStart = 1;
2495                    } else {
2496                        // If the QName of the return value was given to us, look
2497
// through the result arguments to find the right name
2498
findReturnParam = true;
2499                    }
2500                }
2501
2502                // The following loop looks at the resargs and
2503
// converts the value to the appropriate return/out parameter
2504
// value. If the return value is found, is value is
2505
// placed in result. The remaining resargs are
2506
// placed in the outParams list (note that if a resArg
2507
// is found that does not match a operation parameter qname,
2508
// it is still placed in the outParms list).
2509
for (int i = outParamStart; i < resArgs.size(); i++) {
2510                    RPCParam param = (RPCParam) resArgs.get(i);
2511
2512                    Class JavaDoc javaType = getJavaTypeForQName(param.getQName());
2513                    Object JavaDoc value = param.getObjectValue();
2514
2515                    // Convert type if needed
2516
if (javaType != null && value != null &&
2517                           !javaType.isAssignableFrom(value.getClass())) {
2518                        value = JavaUtils.convert(value, javaType);
2519                    }
2520
2521                    // Check if this parameter is our return
2522
// otherwise just add it to our outputs
2523
if (findReturnParam &&
2524                          returnParamQName.equals(param.getQName())) {
2525                        // found it!
2526
result = value;
2527                        findReturnParam = false;
2528                    } else {
2529                        outParams.put(param.getQName(), value);
2530                        outParamsList.add(value);
2531                    }
2532                }
2533
2534                // added by scheu:
2535
// If the return param is still not found, that means
2536
// the returned value did not have the expected qname.
2537
// The soap specification indicates that this should be
2538
// accepted (and we also fail interop tests if we are strict here).
2539
// Look through the outParms and find one that
2540
// does not match one of the operation parameters.
2541
if (findReturnParam) {
2542                    Iterator JavaDoc it = outParams.keySet().iterator();
2543                    while (it.hasNext() && findReturnParam) {
2544                        QName JavaDoc qname = (QName JavaDoc) it.next();
2545                        ParameterDesc paramDesc =
2546                            operation.getOutputParamByQName(qname);
2547                        if (paramDesc == null) {
2548                            // Doesn't match a paramter, so use this for the return
2549
findReturnParam = false;
2550                            result = outParams.remove(qname);
2551                        }
2552                    }
2553                }
2554
2555                // If we were looking for a particular QName for the return and
2556
// still didn't find it, throw an exception
2557
if (findReturnParam) {
2558                    String JavaDoc returnParamName = returnParamQName.toString();
2559                    throw new AxisFault(Messages.getMessage("noReturnParam",
2560                                                            returnParamName));
2561                }
2562            }
2563        } else {
2564            // This is a SOAPBodyElement, try to treat it like a return value
2565
try {
2566                result = bodyEl.getValueAsType(getReturnType());
2567            } catch (Exception JavaDoc e) {
2568                // just return the SOAPElement
2569
result = bodyEl;
2570            }
2571
2572        }
2573
2574        if (log.isDebugEnabled()) {
2575            log.debug("Exit: Call::invoke(RPCElement)");
2576        }
2577
2578        // Convert type if needed
2579
if (operation != null && operation.getReturnClass() != null) {
2580            result = JavaUtils.convert(result, operation.getReturnClass());
2581        }
2582
2583        return( result );
2584    }
2585
2586    /**
2587     * Get the javaType for a given parameter.
2588     *
2589     * @param name the QName of the parameter
2590     * @return the class associated with that parameter
2591     */

2592    private Class JavaDoc getJavaTypeForQName(QName JavaDoc name) {
2593        if (operation == null) {
2594            return null;
2595        }
2596        ParameterDesc param = operation.getOutputParamByQName(name);
2597        return param == null ? null : param.getJavaType();
2598    }
2599
2600    /**
2601     * Set engine option.
2602     *
2603     * Note: Not part of JAX-RPC specification.
2604     */

2605    public void setOption(String JavaDoc name, Object JavaDoc value) {
2606        service.getEngine().setOption(name, value);
2607    }
2608
2609    /**
2610     * Invoke this Call with its established MessageContext
2611     * (perhaps because you called this.setRequestMessage())
2612     *
2613     * Note: Not part of JAX-RPC specification.
2614     *
2615     * @exception AxisFault
2616     */

2617    public void invoke() throws AxisFault {
2618        if (log.isDebugEnabled()) {
2619            log.debug("Enter: Call::invoke()");
2620        }
2621
2622        isNeverInvoked = false;
2623
2624        Message reqMsg = null ;
2625        SOAPEnvelope reqEnv = null ;
2626
2627        msgContext.reset();
2628        msgContext.setResponseMessage(null);
2629        msgContext.setProperty( MessageContext.CALL, this );
2630        msgContext.setProperty( WSDL_SERVICE, service );
2631        msgContext.setProperty( WSDL_PORT_NAME, getPortName() );
2632        if ( isMsg ) {
2633            msgContext.setProperty( MessageContext.IS_MSG, "true" );
2634        }
2635
2636        if (username != null) {
2637            msgContext.setUsername(username);
2638        }
2639        if (password != null) {
2640            msgContext.setPassword(password);
2641        }
2642        msgContext.setMaintainSession(maintainSession);
2643
2644        if (operation != null) {
2645            msgContext.setOperation(operation);
2646            operation.setStyle(getOperationStyle());
2647            operation.setUse(getOperationUse());
2648        }
2649
2650        if (useSOAPAction) {
2651            msgContext.setUseSOAPAction(true);
2652        }
2653        if (SOAPActionURI != null) {
2654            msgContext.setSOAPActionURI(SOAPActionURI);
2655        } else {
2656            msgContext.setSOAPActionURI(null);
2657        }
2658        if (timeout != null) {
2659            msgContext.setTimeout(timeout.intValue());
2660        }
2661        msgContext.setHighFidelity(!useStreaming);
2662
2663        // Determine client target service
2664
if (myService != null) {
2665            // If we have a SOAPService kicking around, use that directly
2666
msgContext.setService(myService);
2667        } else {
2668            if (portName != null) {
2669                // No explicit service. If we have a target service name,
2670
// try that.
2671
msgContext.setTargetService(portName.getLocalPart());
2672            } else {
2673                // No direct config, so try the namespace of the first body.
2674
reqMsg = msgContext.getRequestMessage();
2675                
2676                boolean isStream = ((SOAPPart)reqMsg.getSOAPPart()).isBodyStream();
2677                
2678                if (reqMsg != null && !isStream) {
2679                    reqEnv = reqMsg.getSOAPEnvelope();
2680
2681                    SOAPBodyElement body = reqEnv.getFirstBody();
2682
2683                    if (body != null) {
2684                        if ( body.getNamespaceURI() == null ) {
2685                            throw new AxisFault("Call.invoke",
2686                                                Messages.getMessage("cantInvoke00", body.getName()),
2687                                                null, null);
2688                        } else {
2689                            msgContext.setTargetService(body.getNamespaceURI());
2690                        }
2691                    }
2692                }
2693            }
2694        }
2695        if (log.isDebugEnabled()) {
2696            log.debug(Messages.getMessage("targetService",
2697                    msgContext.getTargetService()));
2698        }
2699
2700        Message requestMessage = msgContext.getRequestMessage();
2701        if (requestMessage != null) {
2702            try {
2703                msgContext.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, requestMessage.getProperty(SOAPMessage.CHARACTER_SET_ENCODING));
2704            } catch (SOAPException JavaDoc e) {
2705            }
2706            
2707            if(myHeaders != null) {
2708                reqEnv = requestMessage.getSOAPEnvelope();
2709    
2710                // If we have headers to insert, do so now.
2711
for (int i = 0 ; myHeaders != null && i < myHeaders.size() ; i++ ) {
2712                    reqEnv.addHeader((SOAPHeaderElement)myHeaders.get(i));
2713                }
2714            }
2715        }
2716
2717        // set up transport if there is one
2718
if (transport != null) {
2719            transport.setupMessageContext(msgContext, this, service.getEngine());
2720        }
2721        else {
2722            msgContext.setTransportName( transportName );
2723        }
2724
2725        SOAPService svc = msgContext.getService();
2726        if (svc != null) {
2727            svc.setPropertyParent(myProperties);
2728        } else {
2729            msgContext.setPropertyParent(myProperties);
2730        }
2731
2732        // For debugging - print request message
2733
if (log.isDebugEnabled()) {
2734            StringWriter JavaDoc writer = new StringWriter JavaDoc();
2735            try {
2736                SerializationContext ctx = new SerializationContext(writer,
2737                                                                   msgContext);
2738                requestMessage.getSOAPEnvelope().output(ctx);
2739                writer.close();
2740            } catch (Exception JavaDoc e) {
2741                throw AxisFault.makeFault(e);
2742            } finally {
2743                log.debug(writer.getBuffer().toString());
2744            }
2745        }
2746
2747        if(!invokeOneWay) {
2748            invokeEngine(msgContext);
2749        } else {
2750            invokeEngineOneWay(msgContext);
2751        }
2752
2753        if (log.isDebugEnabled()) {
2754            log.debug("Exit: Call::invoke()");
2755        }
2756    }
2757
2758    /**
2759     * Invoke the message on the current engine and do not wait for a response.
2760     *
2761     * @param msgContext the <code>MessageContext</code> to use
2762     * @throws AxisFault if the invocation raised a fault
2763     */

2764    private void invokeEngine(MessageContext msgContext) throws AxisFault {
2765        service.getEngine().invoke( msgContext );
2766
2767        if (transport != null) {
2768            transport.processReturnedMessageContext(msgContext);
2769        }
2770
2771        Message resMsg = msgContext.getResponseMessage();
2772
2773        if (resMsg == null) {
2774          if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) {
2775            throw new AxisFault(Messages.getMessage("nullResponse00"));
2776          } else {
2777            return;
2778          }
2779        }
2780
2781        /** This must happen before deserialization...
2782         */

2783        resMsg.setMessageType(Message.RESPONSE);
2784
2785        SOAPEnvelope resEnv = resMsg.getSOAPEnvelope();
2786
2787        SOAPBodyElement respBody = resEnv.getFirstBody();
2788        if (respBody instanceof SOAPFault) {
2789            //we got a fault
2790
if(operation == null ||
2791                    operation.getReturnClass() == null ||
2792                    operation.getReturnClass() !=
2793                        javax.xml.soap.SOAPMessage JavaDoc.class) {
2794                //unless we don't care about the return value or we want
2795
//a raw message back
2796
//get the fault from the body and throw it
2797
throw ((SOAPFault)respBody).getFault();
2798            }
2799        }
2800    }
2801
2802    /**
2803     * Implement async invocation by running the request in a new thread
2804     * @param msgContext
2805     */

2806    private void invokeEngineOneWay(final MessageContext msgContext) {
2807        //TODO: this is not a good way to do stuff, as it has no error reporting facility
2808
//create a new class
2809
Runnable JavaDoc runnable = new Runnable JavaDoc(){
2810            public void run() {
2811                msgContext.setProperty(Call.ONE_WAY, Boolean.TRUE);
2812                try {
2813                    service.getEngine().invoke( msgContext );
2814                } catch (AxisFault af){
2815                    //TODO: handle errors properly
2816
log.debug(Messages.getMessage("exceptionPrinting"), af);
2817                }
2818                msgContext.removeProperty(Call.ONE_WAY);
2819            }
2820        };
2821        //create a thread to run it
2822
Thread JavaDoc thread = new Thread JavaDoc(runnable);
2823        //run it
2824
thread.start();
2825    }
2826
2827    /**
2828     * Get the output parameters (if any) from the last invocation.
2829     *
2830     * This allows named access - if you need sequential access, use
2831     * getOutputValues().
2832     *
2833     * @return a Map containing the output parameter values, indexed by QName
2834     */

2835    public Map JavaDoc getOutputParams()
2836    {
2837        if (isNeverInvoked) {
2838            throw new JAXRPCException JavaDoc(
2839                    Messages.getMessage("outputParamsUnavailable"));
2840        }
2841        return this.outParams;
2842    }
2843
2844    /**
2845     * Returns a List values for the output parameters of the last
2846     * invoked operation.
2847     *
2848     * @return Values for the output parameters. An empty List is
2849     * returned if there are no output values.
2850     *
2851     * @throws JAXRPCException - If this method is invoked for a
2852     * one-way operation or is invoked
2853     * before any invoke method has been called.
2854     */

2855    public List JavaDoc getOutputValues() {
2856        if (isNeverInvoked) {
2857            throw new JAXRPCException JavaDoc(
2858                    Messages.getMessage("outputParamsUnavailable"));
2859        }
2860        return outParamsList;
2861    }
2862
2863    /**
2864     * Get the Service object associated with this Call object.
2865     *
2866     * Note: Not part of JAX-RPC specification.
2867     *
2868     * @return Service the Service object this Call object is associated with
2869     */

2870    public Service getService()
2871    {
2872        return this.service;
2873    }
2874
2875    /**
2876     *
2877     * Set the service so that it defers missing property gets to the
2878     * Call. So when client-side Handlers get at the MessageContext,
2879     * the property scoping will be MC -> SOAPService -> Call
2880     */

2881    public void setSOAPService(SOAPService service)
2882    {
2883        myService = service;
2884        if (service != null) {
2885            // Set the service so that it defers missing property gets to the
2886
// Call. So when client-side Handlers get at the MessageContext,
2887
// the property scoping will be MC -> SOAPService -> Call -> Engine
2888

2889            // THE ORDER OF THESE TWO CALLS IS IMPORTANT, since setting the
2890
// engine on a service will set the property parent for the service
2891
service.setEngine(this.service.getAxisClient());
2892            service.setPropertyParent(myProperties);
2893        }
2894    }
2895
2896    /**
2897     * Sets the client-side request and response Handlers. This is handy
2898     * for programatically setting up client-side work without deploying
2899     * via WSDD or the EngineConfiguration mechanism.
2900     */

2901    public void setClientHandlers(Handler reqHandler, Handler respHandler)
2902    {
2903        // Create a SOAPService which will be used as the client-side service
2904
// handler.
2905
setSOAPService(new SOAPService(reqHandler, null, respHandler));
2906    }
2907
2908
2909    /**
2910     * This method adds an attachment.
2911     * <p>
2912     * Note: Not part of JAX-RPC specification.
2913     *
2914     * @param attachment the <code>Object</code> to attach
2915     * @exception RuntimeException if there is no support for attachments
2916     *
2917     */

2918     public void addAttachmentPart( Object JavaDoc attachment){
2919         attachmentParts.add(attachment);
2920     }
2921
2922    /**
2923     * Add a fault for this operation.
2924     * <p>
2925     * Note: Not part of JAX-RPC specificaion.
2926     *
2927     * @param qname qname of the fault
2928     * @param cls class of the fault
2929     * @param xmlType XML type of the fault
2930     * @param isComplex true if xmlType is a complex type, false otherwise
2931     */

2932    public void addFault(QName JavaDoc qname, Class JavaDoc cls,
2933                         QName JavaDoc xmlType, boolean isComplex) {
2934        if (operationSetManually) {
2935            throw new RuntimeException JavaDoc(
2936                    Messages.getMessage("operationAlreadySet"));
2937        }
2938
2939        if (operation == null) {
2940            operation = new OperationDesc();
2941        }
2942
2943        FaultDesc fault = new FaultDesc();
2944        fault.setQName(qname);
2945        fault.setClassName(cls.getName());
2946        fault.setXmlType(xmlType);
2947        fault.setComplex(isComplex);
2948        operation.addFault(fault);
2949    }
2950
2951    /**
2952     * Hand a complete OperationDesc to the Call, and note that this was
2953     * done so that others don't try to mess with it by calling addParameter,
2954     * setReturnType, etc.
2955     *
2956     * @param operation the OperationDesc to associate with this call.
2957     */

2958    public void setOperation(OperationDesc operation) {
2959        this.operation = operation;
2960        operationSetManually = true;
2961    }
2962
2963    public OperationDesc getOperation()
2964    {
2965        return operation;
2966    }
2967
2968    public void clearOperation() {
2969        operation = null;
2970        operationSetManually = false;
2971    }
2972}
Popular Tags