0001 /* 0002 * The Apache Software License, Version 1.1 0003 * 0004 * 0005 * Copyright (c) 2001-2003 The Apache Software Foundation. All rights 0006 * reserved. 0007 * 0008 * Redistribution and use in source and binary forms, with or without 0009 * modification, are permitted provided that the following conditions 0010 * are met: 0011 * 0012 * 1. Redistributions of source code must retain the above copyright 0013 * notice, this list of conditions and the following disclaimer. 0014 * 0015 * 2. Redistributions in binary form must reproduce the above copyright 0016 * notice, this list of conditions and the following disclaimer in 0017 * the documentation and/or other materials provided with the 0018 * distribution. 0019 * 0020 * 3. The end-user documentation included with the redistribution, 0021 * if any, must include the following acknowledgment: 0022 * "This product includes software developed by the 0023 * Apache Software Foundation (http://www.apache.org/)." 0024 * Alternately, this acknowledgment may appear in the software itself, 0025 * if and wherever such third-party acknowledgments normally appear. 0026 * 0027 * 4. The names "Axis" and "Apache Software Foundation" must 0028 * not be used to endorse or promote products derived from this 0029 * software without prior written permission. For written 0030 * permission, please contact apache@apache.org. 0031 * 0032 * 5. Products derived from this software may not be called "Apache", 0033 * nor may "Apache" appear in their name, without prior written 0034 * permission of the Apache Software Foundation. 0035 * 0036 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 0037 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0038 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 0039 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 0040 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 0041 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 0042 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 0043 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 0044 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 0045 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 0046 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 0047 * SUCH DAMAGE. 0048 * ==================================================================== 0049 * 0050 * This software consists of voluntary contributions made by many 0051 * individuals on behalf of the Apache Software Foundation. For more 0052 * information on the Apache Software Foundation, please see 0053 * <http://www.apache.org/>. 0054 */ 0055 0056 package org.apache.axis.client ; 0057 0058 import org.apache.axis.AxisFault; 0059 import org.apache.axis.AxisProperties; 0060 import org.apache.axis.Constants; 0061 import org.apache.axis.Handler; 0062 import org.apache.axis.InternalException; 0063 import org.apache.axis.Message; 0064 import org.apache.axis.MessageContext; 0065 import org.apache.axis.components.logger.LogFactory; 0066 import org.apache.axis.description.FaultDesc; 0067 import org.apache.axis.description.OperationDesc; 0068 import org.apache.axis.description.ParameterDesc; 0069 import org.apache.axis.encoding.DeserializerFactory; 0070 import org.apache.axis.encoding.SerializationContext; 0071 import org.apache.axis.encoding.SerializationContextImpl; 0072 import org.apache.axis.encoding.SerializerFactory; 0073 import org.apache.axis.encoding.TypeMapping; 0074 import org.apache.axis.encoding.TypeMappingRegistry; 0075 import org.apache.axis.encoding.XMLType; 0076 import org.apache.axis.encoding.ser.BaseDeserializerFactory; 0077 import org.apache.axis.encoding.ser.BaseSerializerFactory; 0078 import org.apache.axis.enum.Style; 0079 import org.apache.axis.enum.Use; 0080 import org.apache.axis.handlers.soap.SOAPService; 0081 import org.apache.axis.message.RPCElement; 0082 import org.apache.axis.message.RPCHeaderParam; 0083 import org.apache.axis.message.RPCParam; 0084 import org.apache.axis.message.SOAPBodyElement; 0085 import org.apache.axis.message.SOAPEnvelope; 0086 import org.apache.axis.message.SOAPFault; 0087 import org.apache.axis.message.SOAPHeaderElement; 0088 import org.apache.axis.soap.SOAPConstants; 0089 import org.apache.axis.transport.http.HTTPTransport; 0090 import org.apache.axis.utils.ClassUtils; 0091 import org.apache.axis.utils.JavaUtils; 0092 import org.apache.axis.utils.Messages; 0093 import org.apache.axis.wsdl.symbolTable.BindingEntry; 0094 import org.apache.axis.wsdl.symbolTable.Parameter; 0095 import org.apache.axis.wsdl.symbolTable.Parameters; 0096 import org.apache.axis.wsdl.symbolTable.SymbolTable; 0097 import org.apache.axis.wsdl.symbolTable.FaultInfo; 0098 import org.apache.axis.wsdl.toJava.Utils; 0099 import org.apache.commons.logging.Log; 0100 0101 import javax.wsdl.Binding; 0102 import javax.wsdl.BindingInput; 0103 import javax.wsdl.BindingOperation; 0104 import javax.wsdl.Operation; 0105 import javax.wsdl.Part; 0106 import javax.wsdl.Port; 0107 import javax.wsdl.PortType; 0108 import javax.wsdl.extensions.soap.SOAPAddress; 0109 import javax.wsdl.extensions.soap.SOAPBody; 0110 import javax.wsdl.extensions.soap.SOAPOperation; 0111 import javax.xml.namespace.QName; 0112 import javax.xml.rpc.JAXRPCException; 0113 import javax.xml.rpc.ParameterMode; 0114 import java.io.StringWriter; 0115 import java.net.MalformedURLException; 0116 import java.net.URL; 0117 import java.util.ArrayList; 0118 import java.util.HashMap; 0119 import java.util.Hashtable; 0120 import java.util.Iterator; 0121 import java.util.List; 0122 import java.util.Map; 0123 import java.util.StringTokenizer; 0124 import java.util.Vector; 0125 import java.rmi.RemoteException; 0126 0127 /** 0128 * Axis' JAXRPC Dynamic Invocation Interface implementation of the Call 0129 * interface. This class should be used to actually invoke the Web Service. 0130 * It can be prefilled by a WSDL document (on the constructor to the Service 0131 * object) or you can fill in the data yourself. 0132 * <pre> 0133 * Standard properties defined by in JAX-RPC's javax..xml.rpc.Call interface: 0134 * USERNAME_PROPERTY - User name for authentication 0135 * PASSWORD_PROPERTY - Password for authentication 0136 * SESSION_PROPERTY - Participate in a session with the endpoint? 0137 * OPERATION_STYLE_PROPERTY - "rpc" or "document" 0138 * SOAPACTION_USE_PROPERTY - Should SOAPAction be used? 0139 * SOAPACTION_URI_PROPERTY - If SOAPAction is used, this is that action 0140 * ENCODING_STYLE_PROPERTY - Default is SOAP 1.1: "http://schemas.xmlsoap.org/soap/encoding/" 0141 * 0142 * AXIS properties: 0143 * SEND_TYPE_ATTR - Should we send the XSI type attributes (true/false) 0144 * TIMEOUT - Timeout used by transport sender in milliseconds 0145 * TRANSPORT_NAME - Name of transport handler to use 0146 * ATTACHMENT_ENCAPSULATION_FORMAT- Send attachments as MIME the default, or DIME. 0147 * </pre> 0148 * 0149 * @author Doug Davis (dug@us.ibm.com) 0150 */ 0151 0152 public class Call implements javax.xml.rpc.Call { 0153 protected static Log log = 0154 LogFactory.getLog(Call.class.getName()); 0155 private static Log tlog = 0156 LogFactory.getLog(Constants.TIME_LOG_CATEGORY); 0157 0158 // The enterprise category is for stuff that an enterprise product might 0159 // want to track, but in a simple environment (like the AXIS build) would 0160 // be nothing more than a nuisance. 0161 protected static Log entLog = 0162 LogFactory.getLog(Constants.ENTERPRISE_LOG_CATEGORY); 0163 0164 private boolean parmAndRetReq = true ; 0165 private Service service = null ; 0166 private QName portName = null; 0167 private QName operationName = null ; 0168 0169 private MessageContext msgContext = null ; 0170 0171 // Collection of properties to store and put in MessageContext at 0172 // invoke() time. Known ones are stored in actual variables for 0173 // efficiency/type-consistency. Unknown ones are in myProperties. 0174 private Hashtable myProperties = new Hashtable(); 0175 private String username = null; 0176 private String password = null; 0177 private boolean maintainSession = false; 0178 private boolean useSOAPAction = false; 0179 private String SOAPActionURI = null; 0180 private Integer timeout = null; 0181 0182 /** Metadata for the operation associated with this Call */ 0183 private OperationDesc operation = null; 0184 /** This will be true if an OperationDesc is handed to us whole */ 0185 private boolean operationSetManually = false; 0186 0187 // Is this a one-way call? 0188 private boolean invokeOneWay = false; 0189 private boolean isMsg = false; 0190 0191 // Our Transport, if any 0192 private Transport transport = null ; 0193 private String transportName = null ; 0194 0195 // A couple places to store output parameters. 0196 // As a HashMap, retrievable via QName (for getOutputParams). 0197 private HashMap outParams = null; 0198 // As a list, retrievable by index (for getOutputValues). 0199 private ArrayList outParamsList = null; 0200 0201 // A place to store any client-specified headers 0202 private Vector myHeaders = null; 0203 0204 public static final String SEND_TYPE_ATTR = "send_type_attr" ; 0205 public static final String TRANSPORT_NAME = "transport_name" ; 0206 public static final String TRANSPORT_PROPERTY= "java.protocol.handler.pkgs"; 0207 0208 public static final String WSDL_SERVICE = "wsdl.service"; 0209 0210 public static final String WSDL_PORT_NAME = "wsdl.portName"; 0211 0212 // @deprecated use WSDL_SERVICE instead. 0213 public static final String JAXRPC_SERVICE = WSDL_SERVICE; 0214 0215 // @deprected use WSDL_PORT_NAME instead. 0216 public static final String JAXRPC_PORTTYPE_NAME = WSDL_PORT_NAME; 0217 0218 // If true, the code will throw a fault if there is no 0219 // response message from the server. Otherwise, the 0220 // invoke method will return a null. 0221 public static final boolean FAULT_ON_NO_RESPONSE = false; 0222 0223 /** 0224 * Property for setting attachment format. 0225 */ 0226 public static final String ATTACHMENT_ENCAPSULATION_FORMAT= 0227 "attachment_encapsulation_format"; 0228 /** 0229 * Property value for setting attachment format as MIME. 0230 */ 0231 public static final String ATTACHMENT_ENCAPSULATION_FORMAT_MIME= 0232 "axis.attachment.style.mime"; 0233 /** 0234 * Property value for setting attachment format as DIME. 0235 */ 0236 public static final String ATTACHMENT_ENCAPSULATION_FORMAT_DIME= 0237 "axis.attachment.style.dime"; 0238 0239 /** 0240 * A Hashtable mapping protocols (Strings) to Transports (classes) 0241 */ 0242 private static Hashtable transports = new Hashtable(); 0243 0244 static ParameterMode [] modes = new ParameterMode [] { null, 0245 ParameterMode.IN, 0246 ParameterMode.OUT, 0247 ParameterMode.INOUT }; 0248 0249 /** This is true when someone has called setEncodingStyle() */ 0250 private boolean encodingStyleExplicitlySet = false; 0251 /** This is true when someone has called setOperationUse() */ 0252 private boolean useExplicitlySet = false; 0253 0254 /************************************************************************/ 0255 /* Start of core JAX-RPC stuff */ 0256 /************************************************************************/ 0257 0258 /** 0259 * Default constructor - not much else to say. 0260 */ 0261 public Call(Service service) { 0262 this.service = service ; 0263 msgContext = new MessageContext( service.getEngine() ); 0264 maintainSession = service.getMaintainSession(); 0265 initialize(); 0266 } 0267 0268 /** 0269 * Build a call from a URL string 0270 * 0271 * @param url the target endpoint URL 0272 * @exception MalformedURLException 0273 */ 0274 public Call(String url) throws MalformedURLException { 0275 this(new Service()); 0276 setTargetEndpointAddress(new URL(url)); 0277 } 0278 0279 /** 0280 * Build a call from a URL 0281 * 0282 * @param url the target endpoint URL 0283 */ 0284 public Call(URL url) { 0285 this(new Service()); 0286 setTargetEndpointAddress(url); 0287 } 0288 0289 //////////////////////////// 0290 // 0291 // Properties and the shortcuts for common ones. 0292 // 0293 0294 /** 0295 * Allows you to set a named property to the passed in value. 0296 * There are a few known properties (like username, password, etc) 0297 * that are variables in Call. The rest of the properties are 0298 * stored in a Hashtable. These common properties should be 0299 * accessed via the accessors for speed/type safety, but they may 0300 * still be obtained via this method. It's up to one of the 0301 * Handlers (or the Axis engine itself) to go looking for 0302 * one of them. 0303 * 0304 * @param name Name of the property 0305 * @param value Value of the property 0306 */ 0307 public void setProperty(String name, Object value) { 0308 if (name == null || value == null) { 0309 throw new JAXRPCException( 0310 Messages.getMessage(name == null ? 0311 "badProp03" : "badProp04")); 0312 } 0313 else if (name.equals(USERNAME_PROPERTY)) { 0314 if (!(value instanceof String)) { 0315 throw new JAXRPCException( 0316 Messages.getMessage("badProp00", new String[] { 0317 name, "java.lang.String", value.getClass().getName()})); 0318 } 0319 setUsername((String) value); 0320 } 0321 else if (name.equals(PASSWORD_PROPERTY)) { 0322 if (!(value instanceof String)) { 0323 throw new JAXRPCException( 0324 Messages.getMessage("badProp00", new String[] { 0325 name, "java.lang.String", value.getClass().getName()})); 0326 } 0327 setPassword((String) value); 0328 } 0329 else if (name.equals(SESSION_MAINTAIN_PROPERTY)) { 0330 if (!(value instanceof Boolean)) { 0331 throw new JAXRPCException( 0332 Messages.getMessage("badProp00", new String[] 0333 {name, 0334 "java.lang.Boolean", 0335 value.getClass().getName()})); 0336 } 0337 setMaintainSession(((Boolean) value).booleanValue()); 0338 } 0339 else if (name.equals(OPERATION_STYLE_PROPERTY)) { 0340 if (!(value instanceof String)) { 0341 throw new JAXRPCException( 0342 Messages.getMessage("badProp00", new String[] { 0343 name, "java.lang.String", value.getClass().getName()})); 0344 } 0345 setOperationStyle((String) value); Rate0346 if (getOperationStyle() == Style.DOCUMENT || 0347 getOperationStyle() == Style.WRAPPED) { 0348 setOperationUse(Use.LITERAL_STR); Rate0349 } else if (getOperationStyle() == Style.RPC) { 0350 setOperationUse(Use.ENCODED_STR); 0351 } 0352 } 0353 else if (name.equals(SOAPACTION_USE_PROPERTY)) { 0354 if (!(value instanceof Boolean)) { 0355 throw new JAXRPCException( 0356 Messages.getMessage("badProp00", new String[] 0357 {name, 0358 "java.lang.Boolean", 0359 value.getClass().getName()})); 0360 } 0361 setUseSOAPAction(((Boolean) value).booleanValue()); 0362 } 0363 else if (name.equals(SOAPACTION_URI_PROPERTY)) { 0364 if (!(value instanceof String)) { 0365 throw new JAXRPCException( 0366 Messages.getMessage("badProp00", new String[] 0367 {name, 0368 "java.lang.String", 0369 value.getClass().getName()})); 0370 } 0371 setSOAPActionURI((String) value); 0372 } 0373 else if (name.equals(ENCODINGSTYLE_URI_PROPERTY)) { 0374 if (!(value instanceof String)) { 0375 throw new JAXRPCException( 0376 Messages.getMessage("badProp00", new String[] 0377 {name, 0378 "java.lang.String", 0379 value.getClass().getName()})); 0380 } 0381 setEncodingStyle((String) value); 0382 } 0383 else if (name.equals(Stub.ENDPOINT_ADDRESS_PROPERTY)) { 0384 if (!(value instanceof String)) { 0385 throw new JAXRPCException( 0386 Messages.getMessage("badProp00", new String[] 0387 {name, 0388 "java.lang.String", 0389 value.getClass().getName()})); 0390 } 0391 setTargetEndpointAddress((String) value); 0392 } 0393 else if ( name.equals(TRANSPORT_NAME) ) { 0394 if (!(value instanceof String)) { 0395 throw new JAXRPCException( 0396 Messages.getMessage("badProp00", new String[] { 0397 name, "java.lang.String", value.getClass().getName()})); 0398 } 0399 transportName = (String) value ; 0400 if (transport != null) 0401 transport.setTransportName((String) value); 0402 } 0403 else if ( name.equals(ATTACHMENT_ENCAPSULATION_FORMAT) ) { 0404 if (!(value instanceof String)) { 0405 throw new JAXRPCException( 0406 Messages.getMessage("badProp00", new String[] { 0407 name, "java.lang.String", value.getClass().getName()})); 0408 } 0409 if(!value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_MIME ) && 0410 !value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_DIME )) 0411 throw new JAXRPCException( 0412 Messages.getMessage("badattachmenttypeerr", new String[] { 0413 (String) value, ATTACHMENT_ENCAPSULATION_FORMAT_MIME + " " 0414 +ATTACHMENT_ENCAPSULATION_FORMAT_DIME })); 0415 } 0416 else if (name.startsWith("java.") || name.startsWith("javax.")) { 0417 throw new JAXRPCException( 0418 Messages.getMessage("badProp05", name)); 0419 } 0420 myProperties.put(name, value); 0421 } // setProperty 0422 0423 /** 0424 * Returns the value associated with the named property 0425 * 0426 * @return Object value of the property or null if the property is not set 0427 * @throws JAXRPCException if the requested property is not a supported property 0428 */ 0429 public Object getProperty(String name) { 0430 if (name == null || !isPropertySupported(name)) { 0431 throw new JAXRPCException(name == null ? 0432 Messages.getMessage("badProp03") : 0433 Messages.getMessage("badProp05", name)); 0434 } 0435 return myProperties.get(name); 0436 } // getProperty 0437 0438 /** 0439 * Removes (if set) the named property. 0440 * 0441 * @param name name of the property to remove 0442 */ 0443 public void removeProperty(String name) { 0444 if (name == null || !isPropertySupported(name)) { 0445 throw new JAXRPCException(name == null ? 0446 Messages.getMessage("badProp03") : 0447 Messages.getMessage("badProp05", name)); 0448 } 0449 myProperties.remove(name); 0450 } // removeProperty 0451 0452 /** 0453 * Set a scoped property on the call (i.e. one that propagates down into 0454 * the runtime). 0455 * 0456 * Deprecated, since setProperty() now does the right thing here. Expect 0457 * this to disappear in 1.1. 0458 * 0459 * @deprecated 0460 * @param name 0461 * @param value 0462 */ 0463 public void setScopedProperty(String name, Object value) { 0464 if (name == null || value == null) { 0465 throw new JAXRPCException( 0466 Messages.getMessage(name == null ? 0467 "badProp03" : "badProp04")); 0468 } 0469 myProperties.put(name, value); 0470 } // setScopedProperty 0471 0472 /** 0473 * Get a scoped property (i.e. one that propagates down into the runtime). 0474 * 0475 * Deprecated, since there's only one property bag now. Expect this to 0476 * disappear in 1.1. 0477 * 0478 * @deprecated 0479 * @param name 0480 * @return 0481 */ 0482 public Object getScopedProperty(String name) { 0483 if (name != null) { 0484 return myProperties.get(name); 0485 } 0486 return null; 0487 } // getScopedProperty 0488 0489 /** 0490 * Remove a scoped property (i.e. one that propagates down into the 0491 * runtime). 0492 * 0493 * Deprecated, since there's only one property bag now. Expect this to 0494 * disappear in 1.1. 0495 * 0496 * @deprecated 0497 * @param name 0498 */ 0499 public void removeScopedProperty(String name) { 0500 if ( name == null || myProperties == null ) return ; 0501 myProperties.remove( name ); 0502 } // removeScopedProperty 0503 0504 /** 0505 * Configurable properties supported by this Call object. 0506 */ 0507 private static ArrayList propertyNames = new ArrayList(); 0508 static { 0509 propertyNames.add(USERNAME_PROPERTY); 0510 propertyNames.add(PASSWORD_PROPERTY); 0511 propertyNames.add(SESSION_MAINTAIN_PROPERTY); 0512 propertyNames.add(ATTACHMENT_ENCAPSULATION_FORMAT); 0513 propertyNames.add(OPERATION_STYLE_PROPERTY); 0514 propertyNames.add(SOAPACTION_USE_PROPERTY); 0515 propertyNames.add(SOAPACTION_URI_PROPERTY); 0516 propertyNames.add(ENCODINGSTYLE_URI_PROPERTY); 0517 propertyNames.add(TRANSPORT_NAME); 0518 propertyNames.add(ATTACHMENT_ENCAPSULATION_FORMAT); 0519 } 0520 0521 public Iterator getPropertyNames() { 0522 return propertyNames.iterator(); 0523 } 0524 0525 public boolean isPropertySupported(String name) { 0526 return propertyNames.contains(name) || (!name.startsWith("java.") 0527 && !name.startsWith("javax.")); 0528 } 0529 0530 /** 0531 * Set the username. 0532 */ 0533 public void setUsername(String username) { 0534 this.username = username; 0535 } // setUsername 0536 0537 /** 0538 * Get the user name 0539 */ 0540 public String getUsername() { 0541 return username; 0542 } // getUsername 0543 0544 /** 0545 * Set the password. 0546 */ 0547 public void setPassword(String password) { 0548 this.password = password; 0549 } // setPassword 0550 0551 /** 0552 * Get the password 0553 */ 0554 public String getPassword() { 0555 return password; 0556 } // getPassword 0557 0558 /** 0559 * Determine whether we'd like to track sessions or not. This 0560 * overrides the default setting from the service. 0561 * This just passes through the value into the MessageContext. 0562 * Note: Not part of JAX-RPC specification. 0563 * 0564 * @param yesno true if session state is desired, false if not. 0565 */ 0566 public void setMaintainSession(boolean yesno) { 0567 maintainSession = yesno; 0568 } 0569 0570 /** 0571 * Get the value of maintainSession flag. 0572 */ 0573 public boolean getMaintainSession() { 0574 return maintainSession; 0575 } 0576 0577 /** 0578 * Set the operation style: "document", "rpc" 0579 * @param operationStyle string designating style 0580 */ 0581 public void setOperationStyle(String operationStyle) { 0582 Style style = Style.getStyle(operationStyle, Style.DEFAULT); 0583 setOperationStyle(style); 0584 } // setOperationStyle 0585 0586 /** 0587 * Set the operation style 0588 * 0589 * @param operationStyle 0590 */ 0591 public void setOperationStyle(Style operationStyle) { 0592 if (operation == null) { 0593 operation = new OperationDesc(); 0594 } 0595 0596 operation.setStyle(operationStyle); 0597 0598 // If no one has explicitly set the use, we should track 0599 // the style. If it's non-RPC, default to LITERAL. 0600 if (!useExplicitlySet) { 0601 if (operationStyle != Style.RPC) { 0602 operation.setUse(Use.LITERAL); 0603 } 0604 } 0605 0606 // If no one has explicitly set the encodingStyle, we should 0607 // track the style. If it's RPC, default to SOAP-ENC, otherwise 0608 // default to "". 0609 if (!encodingStyleExplicitlySet) { 0610 String encStyle = ""; 0611 if (operationStyle == Style.RPC) { 0612 // RPC style defaults to encoded, otherwise default to literal 0613 encStyle = msgContext.getSOAPConstants().getEncodingURI(); 0614 } 0615 msgContext.setEncodingStyle(encStyle); 0616 } 0617 } 0618 0619 /** 0620 * Get the operation style. 0621 */ 0622 public Style getOperationStyle() { 0623 if (operation != null) { 0624 return operation.getStyle(); 0625 } 0626 return Style.DEFAULT; 0627 } // getOperationStyle 0628 0629 /** 0630 * Set the operation use: "literal", "encoded" 0631 * @param operationUse string designating use 0632 */ 0633 public void setOperationUse(String operationUse) { 0634 Use use = Use.getUse(operationUse, Use.DEFAULT); 0635 setOperationUse(use); 0636 } // setOperationUse 0637 0638 /** 0639 * Set the operation use 0640 * @param operationUse 0641 */ 0642 public void setOperationUse(Use operationUse) { 0643 useExplicitlySet = true; 0644 0645 if (operation == null) { 0646 operation = new OperationDesc(); 0647 } 0648 0649 operation.setUse(operationUse); 0650 if (!encodingStyleExplicitlySet) { 0651 String encStyle = ""; 0652 if (operationUse == Use.ENCODED) { 0653 // RPC style defaults to encoded, otherwise default to literal 0654 encStyle = msgContext.getSOAPConstants().getEncodingURI(); 0655 } 0656 msgContext.setEncodingStyle(encStyle); 0657 } 0658 } 0659 0660 /** 0661 * Get the operation use. 0662 */ 0663 public Use getOperationUse() { 0664 if (operation != null) { 0665 return operation.getUse(); 0666 } 0667 return Use.DEFAULT; 0668 } // getOperationStyle 0669 0670 /** 0671 * Should soapAction be used? 0672 */ 0673 public void setUseSOAPAction(boolean useSOAPAction) { 0674 this.useSOAPAction = useSOAPAction; 0675 } // setUseSOAPAction 0676 0677 /** 0678 * Are we using soapAction? 0679 */ 0680 public boolean useSOAPAction() { 0681 return useSOAPAction; 0682 } // useSOAPAction 0683 0684 /** 0685 * Set the soapAction URI. 0686 */ 0687 public void setSOAPActionURI(String SOAPActionURI) 0688 throws IllegalArgumentException { 0689 useSOAPAction = true; 0690 this.SOAPActionURI = SOAPActionURI; 0691 } // setSOAPActionURI 0692 0693 /** 0694 * Get the soapAction URI. 0695 */ 0696 public String getSOAPActionURI() { 0697 return SOAPActionURI; 0698 } // getSOAPActionURI 0699 0700 /** 0701 * Sets the encoding style to the URL passed in. 0702 * 0703 * @param namespaceURI URI of the encoding to use. 0704 */ 0705 public void setEncodingStyle(String namespaceURI) { 0706 encodingStyleExplicitlySet = true; 0707 msgContext.setEncodingStyle(namespaceURI); 0708 } 0709 0710 /** 0711 * Returns the encoding style as a URI that should be used for the SOAP 0712 * message. 0713 * 0714 * @return String URI of the encoding style to use 0715 */ 0716 public String getEncodingStyle() { 0717 return msgContext.getEncodingStyle(); 0718 } 0719 0720 /** 0721 * Sets the endpoint address of the target service port. This address must 0722 * correspond to the transport specified in the binding for this Call 0723 * instance. 0724 * 0725 * @param address - Endpoint address of the target service port; specified 0726 * as URI 0727 */ 0728 public void setTargetEndpointAddress(String address) { 0729 URL urlAddress; 0730 try { 0731 urlAddress = new URL(address); 0732 } 0733 catch (MalformedURLException mue) { 0734 throw new JAXRPCException(mue); 0735 } 0736 setTargetEndpointAddress(urlAddress); 0737 } 0738 0739 /** 0740 * Sets the URL of the target Web Service. 0741 * 0742 * Note: Not part of JAX-RPC specification. 0743 * 0744 * @param address URL of the target Web Service 0745 */ 0746 public void setTargetEndpointAddress(java.net.URL address) { 0747 try { 0748 if ( address == null ) { 0749 setTransport(null); 0750 return ; 0751 } 0752 0753 String protocol = address.getProtocol(); 0754 0755 // Handle the case where the protocol is the same but we 0756 // just want to change the URL - if so just set the URL, 0757 // creating a new Transport object will drop all session 0758 // data - and we want that stuff to persist between invoke()s. 0759 // Technically the session data should be in the message 0760 // context so that it can be persistent across transports 0761 // as well, but for now the data is in the Transport object. 0762 //////////////////////////////////////////////////////////////// 0763 if ( this.transport != null ) { 0764 String oldAddr = this.transport.getUrl(); 0765 if ( oldAddr != null && !oldAddr.equals("") ) { 0766 URL tmpURL = new URL( oldAddr ); 0767 String oldProto = tmpURL.getProtocol(); 0768 if ( protocol.equals(oldProto) ) { 0769 this.transport.setUrl( address.toString() ); 0770 return ; 0771 } 0772 } 0773 } 0774 0775 // Do we already have a transport for this address? 0776 Transport transport = service.getTransportForURL(address); 0777 if (transport != null) { 0778 setTransport(transport); 0779 } 0780 else { 0781 // We don't already have a transport for this address. Create one. 0782 transport = getTransportForProtocol(protocol); 0783 if (transport == null) 0784 throw new AxisFault("Call.setTargetEndpointAddress", 0785 Messages.getMessage("noTransport01", 0786 protocol), null, null); 0787 transport.setUrl(address.toString()); 0788 setTransport(transport); 0789 service.registerTransportForURL(address, transport); 0790 } 0791 } 0792 catch( Exception exp ) { 0793 log.error(Messages.getMessage("exception00"), exp); 0794 // do what? 0795 // throw new AxisFault("Call.setTargetEndpointAddress", 0796 //"Malformed URL Exception: " + e.getMessage(), null, null); 0797 } 0798 } 0799 0800 /** 0801 * Returns the URL of the target Web Service. 0802 * 0803 * @return URL URL of the target Web Service 0804 */ 0805 public String getTargetEndpointAddress() { 0806 try { 0807 if ( transport == null ) return( null ); 0808 return( transport.getUrl() ); 0809 } 0810 catch( Exception exp ) { 0811 return( null ); 0812 } 0813 } 0814 0815 public Integer getTimeout() { 0816 return timeout; 0817 } 0818 0819 public void setTimeout(Integer timeout) { 0820 this.timeout = timeout; 0821 } 0822 // 0823 // end properties code. 0824 // 0825 //////////////////////////// 0826 0827 /** 0828 * Is the caller required to provide the parameter and return type 0829 * specification? 0830 * If true, then 0831 * addParameter and setReturnType MUST be called to provide the meta data. 0832 * If false, then 0833 * addParameter and setReturnType SHOULD NOT be called because the 0834 * Call object already has the meta data describing the 0835 * parameters and return type. If addParameter is called, the specified 0836 * parameter is added to the end of the list of parameters. 0837 */ 0838 public boolean isParameterAndReturnSpecRequired(QName operationName) { 0839 return parmAndRetReq; 0840 } // isParameterAndReturnSpecRequired 0841 0842 /** 0843 * Adds the specified parameter to the list of parameters for the 0844 * operation associated with this Call object. 0845 * 0846 * Note: Not part of JAX-RPC specification. 0847 * 0848 * @param paramName Name that will be used for the parameter in the XML 0849 * @param xmlType XMLType of the parameter 0850 * @param parameterMode one of IN, OUT or INOUT 0851 */ 0852 public void addParameter(QName paramName, QName xmlType, 0853 ParameterMode parameterMode) { 0854 Class javaType = null; 0855 TypeMapping tm = getTypeMapping(); 0856 if (tm != null) { 0857 javaType = tm.getClassForQName(xmlType); 0858 } 0859 addParameter(paramName, xmlType, javaType, parameterMode); 0860 } 0861 0862 /** 0863 * Adds the specified parameter to the list of parameters for the 0864 * operation associated with this Call object. 0865 * 0866 * 0867 * Note: Not part of JAX-RPC specification. 0868 * 0869 * @param paramName Name that will be used for the parameter in the XML 0870 * @param xmlType XMLType of the parameter 0871 * @param javaType The Java class of the parameter 0872 * @param parameterMode one of IN, OUT or INOUT 0873 */ 0874 public void addParameter(QName paramName, QName xmlType, 0875 Class javaType, ParameterMode parameterMode) { 0876 0877 if (operationSetManually) { 0878 throw new RuntimeException( 0879 Messages.getMessage("operationAlreadySet")); 0880 } 0881 0882 if (operation == null) 0883 operation = new OperationDesc(); 0884 0885 // In order to allow any Call to be re-used, Axis 0886 // chooses to allow parameters to be added when 0887 // parmAndRetReq==false. This does not conflict with 0888 // JSR 101 which indicates an exception MAY be thrown. 0889 0890 //if (parmAndRetReq) { 0891 ParameterDesc param = new ParameterDesc(); 0892 param.setQName( paramName ); 0893 param.setTypeQName( xmlType ); 0894 param.setJavaType( javaType ); 0895 byte mode = ParameterDesc.IN; 0896 if (parameterMode == ParameterMode.INOUT) { 0897 mode = ParameterDesc.INOUT; 0898 } else if (parameterMode == ParameterMode.OUT) { 0899 mode = ParameterDesc.OUT; 0900 } 0901 param.setMode(mode); 0902 0903 operation.addParameter(param); 0904 parmAndRetReq = true; 0905 //} 0906 //else { 0907 //throw new JAXRPCException(Messages.getMessage("noParmAndRetReq")); 0908 //} 0909 } 0910 0911 /** 0912 * Adds the specified parameter to the list of parameters for the 0913 * operation associated with this Call object. 0914 * 0915 * @param paramName Name that will be used for the parameter in the XML 0916 * @param xmlType XMLType of the parameter 0917 * @param parameterMode one of IN, OUT or INOUT 0918 */ 0919 public void addParameter(String paramName, QName xmlType, 0920 ParameterMode parameterMode) { 0921 Class javaType = null; 0922 TypeMapping tm = getTypeMapping(); 0923 if (tm != null) { 0924 javaType = tm.getClassForQName(xmlType); 0925 } 0926 addParameter(new QName("", paramName), xmlType, 0927 javaType, parameterMode); 0928 } 0929 0930 /** 0931 * Adds a parameter type and mode for a specific operation. Note that the 0932 * client code is not required to call any addParameter and setReturnType 0933 * methods before calling the invoke method. A Call implementation class 0934 * can determine the parameter types by using the Java reflection and 0935 * configured type mapping registry. 0936 * 0937 * @param paramName - Name of the parameter 0938 * @param xmlType - XML datatype of the parameter 0939 * @param javaType - The Java class of the parameter 0940 * @param parameterMode - Mode of the parameter-whether IN, OUT or INOUT 0941 * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns 0942 * false, then addParameter MAY throw 0943 * JAXRPCException....actually Axis allows 0944 * modification in such cases 0945 */ 0946 public void addParameter(String paramName, QName xmlType, 0947 Class javaType, ParameterMode parameterMode) { 0948 addParameter(new QName("", paramName), xmlType, 0949 javaType, parameterMode); 0950 } 0951 0952 /** 0953 0954 * Adds a parameter type as a soap:header. 0955 * @param paramName - Name of the parameter 0956 * @param xmlType - XML datatype of the parameter 0957 * @param javaType - The Java class of the parameter 0958 * @param parameterMode - Mode of the parameter-whether IN, OUT or INOUT 0959 * @param headerMode - Mode of the header. Even if this is an INOUT 0960 * parameter, it need not be in the header in both 0961 * directions. 0962 * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns 0963 * false, then addParameter MAY throw 0964 * JAXRPCException....actually Axis allows 0965 * modification in such cases 0966 */ 0967 public void addParameterAsHeader(QName paramName, QName xmlType, 0968 Class javaType, ParameterMode parameterMode, 0969 ParameterMode headerMode) { 0970 if (operationSetManually) { 0971 throw new RuntimeException( 0972 Messages.getMessage("operationAlreadySet")); 0973 } 0974 0975 if (operation == null) 0976 operation = new OperationDesc(); 0977 0978 ParameterDesc param = new ParameterDesc(); 0979 param.setQName(paramName); 0980 param.setTypeQName(xmlType); 0981 param.setJavaType(javaType); 0982 if (parameterMode == ParameterMode.IN) { 0983 param.setMode(ParameterDesc.IN); 0984 } 0985 else if (parameterMode == ParameterMode.INOUT) { 0986 param.setMode(ParameterDesc.INOUT); 0987 } 0988 else if (parameterMode == ParameterMode.OUT) { 0989 param.setMode(ParameterDesc.OUT); 0990 } 0991 if (headerMode == ParameterMode.IN) { 0992 param.setInHeader(true); 0993 } 0994 else if (headerMode == ParameterMode.INOUT) { 0995 param.setInHeader(true); 0996 param.setOutHeader(true); 0997 } 0998 else if (headerMode == ParameterMode.OUT) { 0999 param.setOutHeader(true); 1000 } 1001 operation.addParameter(param); 1002 parmAndRetReq = true; 1003 } // addParameterAsHeader 1004 1005 /** 1006 * Return the QName of the type of the parameters with the given name. 1007 * 1008 * @param paramName name of the parameter to return 1009 * @return XMLType XMLType of paramName, or null if not found. 1010 */ 1011 public QName getParameterTypeByName(String paramName) { 1012 QName paramQName = new QName("", paramName); 1013 1014 return getParameterTypeByQName(paramQName); 1015 } 1016 1017 /** 1018 * Return the QName of the type of the parameters with the given name. 1019 * 1020 * Note: Not part of JAX-RPC specification. 1021 * 1022 * @param paramQName QName of the parameter to return 1023 * @return XMLType XMLType of paramQName, or null if not found. 1024 */ 1025 public QName getParameterTypeByQName(QName paramQName) { 1026 ParameterDesc param = operation.getParamByQName(paramQName); 1027 if (param != null) { 1028 return param.getTypeQName(); 1029 } 1030 return( null ); 1031 } 1032 1033 /** 1034 * Sets the return type of the operation associated with this Call object. 1035 * 1036 * @param type QName of the return value type. 1037 */ 1038 public void setReturnType(QName type) { 1039 if (operationSetManually) { 1040 throw new RuntimeException( 1041 Messages.getMessage("operationAlreadySet")); 1042 } 1043 1044 if (operation == null) 1045 operation = new OperationDesc(); 1046 1047 // In order to allow any Call to be re-used, Axis 1048 // chooses to allow setReturnType to be changed when 1049 // parmAndRetReq==false. This does not conflict with 1050 // JSR 101 which indicates an exception MAY be thrown. 1051 1052 //if (parmAndRetReq) { 1053 operation.setReturnType(type); 1054 TypeMapping tm = getTypeMapping(); 1055 operation.setReturnClass(tm.getClassForQName(type)); 1056 parmAndRetReq = true; 1057 //} 1058 //else { 1059 //throw new JAXRPCException(Messages.getMessage("noParmAndRetReq")); 1060 //} 1061 } 1062 1063 /** 1064 * Sets the return type for a specific operation. 1065 * 1066 * @param xmlType - QName of the data type of the return value 1067 * @param javaType - Java class of the return value 1068 * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns 1069 * false, then setReturnType MAY throw JAXRPCException...Axis allows 1070 * modification without throwing the exception. 1071 */ 1072 public void setReturnType(QName xmlType, Class javaType) { 1073 setReturnType(xmlType); 1074 // Use specified type as the operation return 1075 operation.setReturnClass(javaType); 1076 } 1077 1078 /** 1079 * Set the return type as a header 1080 */ 1081 public void setReturnTypeAsHeader(QName xmlType) { 1082 setReturnType(xmlType); 1083 operation.setReturnHeader(true); 1084 } // setReturnTypeAsHeader 1085 1086 /** 1087 * Set the return type as a header 1088 */ 1089 public void setReturnTypeAsHeader(QName xmlType, Class javaType) { 1090 setReturnType(xmlType, javaType); 1091 operation.setReturnHeader(true); 1092 } // setReturnTypeAsHeader 1093 1094 /** 1095 * Returns the QName of the type of the return value of this Call - or null 1096 * if not set. 1097 * 1098 * Note: Not part of JAX-RPC specification. 1099 * 1100 * @return the XMLType specified for this Call (or null). 1101 */ 1102 public QName getReturnType() { 1103 if (operation != null) 1104 return operation.getReturnType(); 1105 1106 return null; 1107 } 1108 1109 /** 1110 * Set the QName of the return element 1111 * 1112 * NOT part of JAX-RPC 1113 */ 1114 public void setReturnQName(QName qname) { 1115 if (operationSetManually) { 1116 throw new RuntimeException( 1117 Messages.getMessage("operationAlreadySet")); 1118 } 1119 1120 if (operation == null) 1121 operation = new OperationDesc(); 1122 1123 operation.setReturnQName(qname); 1124 } 1125 /** 1126 * Sets the desired return Java Class. This is a convenience method 1127 * which will cause the Call to automatically convert return values 1128 * into a desired class if possible. For instance, we return object 1129 * arrays by default now for SOAP arrays - you could specify: 1130 * 1131 * setReturnClass(Vector.class) 1132 * 1133 * and you'd get a Vector back from invoke() instead of having to do 1134 * the conversion yourself. 1135 * 1136 * Note: Not part of JAX-RPC specification. To be JAX-RPC compliant, 1137 * use setReturnType(QName, Class). 1138 * 1139 * @param cls the desired return class. 1140 */ 1141 public void setReturnClass(Class cls) { 1142 if (operationSetManually) { 1143 throw new RuntimeException( 1144 Messages.getMessage("operationAlreadySet")); 1145 } 1146 1147 if (operation == null) 1148 operation = new OperationDesc(); 1149 1150 operation.setReturnClass(cls); 1151 TypeMapping tm = getTypeMapping(); 1152 operation.setReturnType(tm.getTypeQName(cls)); 1153 parmAndRetReq = true; 1154 } 1155 1156 /** 1157 * Clears the list of parameters. 1158 * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns 1159 * false, then removeAllParameters MAY throw JAXRPCException...Axis allows 1160 * modification to the Call object without throwing an exception. 1161 */ 1162 public void removeAllParameters() { 1163 //if (parmAndRetReq) { 1164 operation = new OperationDesc(); 1165 operationSetManually = false; 1166 parmAndRetReq = true; 1167 //} 1168 //else { 1169 //throw new JAXRPCException(Messages.getMessage("noParmAndRetReq")); 1170 //} 1171 } 1172 1173 /** 1174 * Returns the operation name associated with this Call object. 1175 * 1176 * @return String Name of the operation or null if not set. 1177 */ 1178 public QName getOperationName() { 1179 return( operationName ); 1180 } 1181 1182 /** 1183 * Sets the operation name associated with this Call object. This will 1184 * not check the WSDL (if there is WSDL) to make sure that it's a valid 1185 * operation name. 1186 * 1187 * @param opName Name of the operation. 1188 */ 1189 public void setOperationName(QName opName) { 1190 operationName = opName ; 1191 } 1192 1193 /** 1194 * This is a convenience method. If the user doesn't care about the QName 1195 * of the operation, the user can call this method, which converts a String 1196 * operation name to a QName. 1197 */ 1198 public void setOperationName(String opName) { 1199 operationName = new QName(opName); 1200 } 1201 1202 /** 1203 * Prefill as much info from the WSDL as it can. 1204 * Right now it's SOAPAction, operation qname, parameter types 1205 * and return type of the Web Service. 1206 * 1207 * This methods considers that port name and target endpoint address have 1208 * already been set. This is useful when you want to use the same Call 1209 * instance for several calls on the same Port 1210 * 1211 * Note: Not part of JAX-RPC specification. 1212 * 1213 * @param opName Operation(method) that's going to be invoked 1214 */ 1215 public void setOperation(String opName) { 1216 if ( service == null ) 1217 throw new JAXRPCException( Messages.getMessage("noService04") ); 1218 1219 // remove all settings concerning an operation 1220 // leave portName and targetEndPoint as they are 1221 this.setOperationName( opName ); 1222 this.setEncodingStyle( null ); 1223 this.setReturnType( null ); 1224 this.removeAllParameters(); 1225 1226 javax.wsdl.Service wsdlService = service.getWSDLService(); 1227 // Nothing to do is the WSDL is not already set. 1228 if(wsdlService == null) 1229 return; 1230 1231 Port port = wsdlService.getPort( portName.getLocalPart() ); 1232 if ( port == null ) 1233 throw new JAXRPCException( Messages.getMessage("noPort00", "" + 1234 portName) ); 1235 1236 Binding binding = port.getBinding(); 1237 PortType portType = binding.getPortType(); 1238 if ( portType == null ) 1239 throw new JAXRPCException( Messages.getMessage("noPortType00", "" + 1240 portName) ); 1241 1242 List operations = portType.getOperations(); 1243 if ( operations == null ) 1244 throw new JAXRPCException( Messages.getMessage("noOperation01", 1245 opName) ); 1246 1247 Operation op = null ; 1248 for ( int i = 0 ; i < operations.size() ; i++, op=null ) { 1249 op = (Operation) operations.get( i ); 1250 if ( opName.equals( op.getName() ) ) break ; 1251 } 1252 if ( op == null ) 1253 throw new JAXRPCException( Messages.getMessage("noOperation01", 1254 opName) ); 1255 1256 // Get the SOAPAction 1257 //////////////////////////////////////////////////////////////////// 1258 List list = port.getExtensibilityElements(); 1259 String opStyle = null; 1260 BindingOperation bop = binding.getBindingOperation(opName, 1261 null, null); 1262 if ( bop == null ) 1263 throw new JAXRPCException( Messages.getMessage("noOperation02", 1264 opName )); 1265 list = bop.getExtensibilityElements(); 1266 for ( int i = 0 ; list != null && i < list.size() ; i++ ) { 1267 Object obj = list.get(i); 1268 if ( obj instanceof SOAPOperation ) { 1269 SOAPOperation sop = (SOAPOperation) obj ; 1270 opStyle = ((SOAPOperation) obj).getStyle(); 1271 String action = sop.getSoapActionURI(); 1272 if ( action != null ) { 1273 setUseSOAPAction(true); 1274 setSOAPActionURI(action); 1275 } 1276 else { 1277 setUseSOAPAction(false); 1278 setSOAPActionURI(null); 1279 } 1280 break ; 1281 } 1282 } 1283 1284 // Get the body's namespace URI and encoding style 1285 //////////////////////////////////////////////////////////////////// 1286 BindingInput bIn = bop.getBindingInput(); 1287 if ( bIn != null ) { 1288 list = bIn.getExtensibilityElements(); 1289 for ( int i = 0 ; list != null && i < list.size() ; i++ ) { 1290 Object obj = list.get(i); 1291 if( obj instanceof 1292 javax.wsdl.extensions.mime.MIMEMultipartRelated){ 1293 javax.wsdl.extensions.mime.MIMEMultipartRelated mpr= 1294 (javax.wsdl.extensions.mime.MIMEMultipartRelated) obj; 1295 Object part= null; 1296 List l= mpr.getMIMEParts(); 1297 for(int j=0; l!= null && j< l.size() && part== null; j++){ 1298 javax.wsdl.extensions.mime.MIMEPart mp 1299 = (javax.wsdl.extensions.mime.MIMEPart)l.get(j); 1300 List ll= mp.getExtensibilityElements(); 1301 for(int k=0; ll != null && k < ll.size() && part == null; 1302 k++){ 1303 part= ll.get(k); 1304 if ( !(part instanceof SOAPBody)) part = null; 1305 } 1306 } 1307 if(null != part) obj= part; 1308 } 1309 1310 if ( obj instanceof SOAPBody ) { 1311 SOAPBody sBody = (SOAPBody) obj ; 1312 list = sBody.getEncodingStyles(); 1313 if ( list != null && list.size() > 0 ) 1314 this.setEncodingStyle( (String) list.get(0) ); 1315 String ns = sBody.getNamespaceURI(); 1316 if (ns != null && !ns.equals("")) 1317 setOperationName( new QName( ns, opName ) ); 1318 break ; 1319 } 1320 } 1321 } 1322 1323 Service service = this.getService(); 1324 SymbolTable symbolTable = service.getWSDLParser().getSymbolTable(); 1325 BindingEntry bEntry = symbolTable.getBindingEntry(binding.getQName()); 1326 Parameters parameters = bEntry.getParameters(bop.getOperation()); 1327 1328 // loop over paramters and set up in/out params 1329 for (int j = 0; j < parameters.list.size(); ++j) { 1330 Parameter p = (Parameter) parameters.list.get(j); 1331 // Get the QName representing the parameter type 1332 QName paramType = Utils.getXSIType(p); 1333 this.addParameter( p.getQName(), paramType, modes[p.getMode()]); 1334 } 1335 1336 Map faultMap = bEntry.getFaults(); 1337 // Get the list of faults for this operation 1338 ArrayList faults = (ArrayList) faultMap.get(bop); 1339 1340 // check for no faults 1341 if (faults == null) { 1342 return; 1343 } 1344 // For each fault, register its information 1345 for (Iterator faultIt = faults.iterator(); faultIt.hasNext();) { 1346 FaultInfo info = (FaultInfo) faultIt.next(); 1347 QName qname = info.getQName(); 1348 javax.wsdl.Message message = info.getMessage(); 1349 1350 // if no parts in fault, skip it! 1351 if (qname == null) { 1352 continue; 1353 } 1354 try { 1355 Class clazz = getTypeMapping().getClassForQName(info.getXMLType()); 1356 addFault(qname, clazz, info.getXMLType(), true); 1357 } catch (Exception e) { 1358 //TODO: ??? 1359 } 1360 } 1361 1362 // set output type 1363 if (parameters.returnParam != null) { 1364 // Get the QName for the return Type 1365 QName returnType = Utils.getXSIType(parameters.returnParam); 1366 QName returnQName = parameters.returnParam.getQName(); 1367 1368 // Get the javaType 1369 String javaType = null; 1370 if (parameters.returnParam.getMIMEInfo() != null) { 1371 javaType = "javax.activation.DataHandler"; 1372 } 1373 else { 1374 javaType = parameters.returnParam.getType().getName(); 1375 } 1376 if (javaType == null) { 1377 javaType = ""; 1378 } 1379 else { 1380 javaType = javaType + ".class"; 1381 } 1382 this.setReturnType(returnType); 1383 try { 1384 this.setReturnClass(ClassUtils.forName(javaType)); 1385 } catch (Exception e){ 1386 //TODO: ??? 1387 } 1388 this.setReturnQName(returnQName); 1389 } 1390 else { 1391 this.setReturnType(org.apache.axis.encoding.XMLType.AXIS_VOID); 1392 } 1393 1394 boolean hasMIME = Utils.hasMIME(bEntry, bop); 1395 Use use = bEntry.getInputBodyType(bop.getOperation()); 1396 Style style = Style.getStyle(opStyle, bEntry.getBindingStyle()); 1397 if (use == Use.LITERAL) { 1398 // Turn off encoding 1399 setEncodingStyle(null); 1400 // turn off XSI types 1401 setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE); 1402 } 1403 if (hasMIME || use == Use.LITERAL) { 1404 // If it is literal, turn off multirefs. 1405 // 1406 // If there are any MIME types, turn off multirefs. 1407 // I don't know enough about the guts to know why 1408 // attachments don't work with multirefs, but they don't. 1409 setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE); 1410 } 1411 1412 if (style == Style.DOCUMENT && symbolTable.isWrapped()) { 1413 style = Style.WRAPPED; 1414 } 1415 1416 // Operation name 1417 if (style == Style.WRAPPED) { 1418 // We need to make sure the operation name, which is what we 1419 // wrap the elements in, matches the Qname of the parameter 1420 // element. 1421 Map partsMap = bop.getOperation().getInput().getMessage().getParts(); 1422 Part p = (Part)partsMap.values().iterator().next(); 1423 QName q = p.getElementName(); 1424 setOperationName(q); 1425 } else { 1426 QName elementQName = 1427 Utils.getOperationQName(bop, bEntry, symbolTable); 1428 if (elementQName != null) { 1429 setOperationName(elementQName); 1430 } 1431 } 1432 1433 // Indicate that the parameters and return no longer 1434 // need to be specified with addParameter calls. 1435 parmAndRetReq = false; 1436 return; 1437 1438 } 1439 1440 1441 /** 1442 * prefill as much info from the WSDL as it can. 1443 * Right now it's target URL, SOAPAction, Parameter types, 1444 * and return type of the Web Service. 1445 * 1446 * If wsdl is not present, this function set port name and operation name 1447 * and does not modify target endpoint address. 1448 * 1449 * Note: Not part of JAX-RPC specification. 1450 * 1451 * @param portName PortName in the WSDL doc to search for 1452 * @param opName Operation(method) that's going to be invoked 1453 */ 1454 public void setOperation(QName portName, String opName) { 1455 if ( service == null ) 1456 throw new JAXRPCException( Messages.getMessage("noService04") ); 1457 1458 // Make sure we're making a fresh start. 1459 this.setPortName( portName ); 1460 this.setOperationName( opName ); 1461 this.setEncodingStyle( null ); 1462 this.setReturnType( null ); 1463 this.removeAllParameters(); 1464 1465 javax.wsdl.Service wsdlService = service.getWSDLService(); 1466 // Nothing to do is the WSDL is not already set. 1467 if(wsdlService == null) 1468 return; 1469 1470 // we reinitialize target endpoint only if we have wsdl 1471 this.setTargetEndpointAddress( (URL) null ); 1472 1473 Port port = wsdlService.getPort( portName.getLocalPart() ); 1474 if ( port == null ) 1475 throw new JAXRPCException( Messages.getMessage("noPort00", "" + 1476 portName) ); 1477 1478 Binding binding = port.getBinding(); 1479 PortType portType = binding.getPortType(); 1480 if ( portType == null ) 1481 throw new JAXRPCException( Messages.getMessage("noPortType00", "" + 1482 portName) ); 1483 1484 // Get the URL 1485 //////////////////////////////////////////////////////////////////// 1486 List list = port.getExtensibilityElements(); 1487 for ( int i = 0 ; list != null && i < list.size() ; i++ ) { 1488 Object obj = list.get(i); 1489 if ( obj instanceof SOAPAddress ) { 1490 try { 1491 SOAPAddress addr = (SOAPAddress) obj ; 1492 URL url = new URL(addr.getLocationURI()); 1493 this.setTargetEndpointAddress(url); 1494 } 1495 catch(Exception exp) { 1496 throw new JAXRPCException( 1497 Messages.getMessage("cantSetURI00", "" + exp) ); 1498 } 1499 } 1500 } 1501 1502 // Get the SOAPAction 1503 //////////////////////////////////////////////////////////////////// 1504 BindingOperation bop = binding.getBindingOperation(opName, 1505 null, null); 1506 if ( bop == null ) 1507 throw new JAXRPCException( Messages.getMessage("noOperation02", 1508 opName )); 1509 list = bop.getExtensibilityElements(); 1510 for ( int i = 0 ; list != null && i < list.size() ; i++ ) { 1511 Object obj = list.get(i); 1512 if ( obj instanceof SOAPOperation ) { 1513 SOAPOperation sop = (SOAPOperation) obj ; 1514 String action = sop.getSoapActionURI(); 1515 if ( action != null ) { 1516 setUseSOAPAction(true); 1517 setSOAPActionURI(action); 1518 } 1519 else { 1520 setUseSOAPAction(false); 1521 setSOAPActionURI(null); 1522 } 1523 break ; 1524 } 1525 } 1526 setOperation(opName); 1527 } 1528 1529 /** 1530 * Returns the fully qualified name of the port for this Call object 1531 * (if there is one). 1532 * 1533 * @return QName Fully qualified name of the port (or null if not set) 1534 */ 1535 public QName getPortName() { 1536 return( portName ); 1537 } // getPortName 1538 1539 /** 1540 * Sets the port name of this Call object. This call will not set 1541 * any additional fields, nor will it do any checking to verify that 1542 * this port name is actually defined in the WSDL - for now anyway. 1543 * 1544 * @param portName Fully qualified name of the port 1545 */ 1546 public void setPortName(QName portName) { 1547 this.portName = portName; 1548 } // setPortName 1549 1550 /** 1551 * Returns the fully qualified name of the port for this Call object 1552 * (if there is one). 1553 * 1554 * @return QName Fully qualified name of the port 1555 * 1556 * @deprecated This is really the service's port name, not portType name. 1557 * Use getPortName instead. 1558 */ 1559 public QName getPortTypeName() { 1560 return portName == null ? new QName("") : portName; 1561 } 1562 1563 /** 1564 * Sets the port name of this Call object. This call will not set 1565 * any additional fields, nor will it do any checking to verify that 1566 * this port type is actually defined in the WSDL - for now anyway. 1567 * 1568 * @param portType Fully qualified name of the portType 1569 * 1570 * @deprecated This is really the service's port name, not portType name. 1571 * Use setPortName instead. 1572 */ 1573 public void setPortTypeName(QName portType) { 1574 setPortName(portType); 1575 } 1576 1577 /** 1578 * Allow the user to set the default SOAP version. For SOAP 1.2, pass 1579 * SOAPConstants.SOAP12_CONSTANTS. 1580 * 1581 * @param soapConstants the SOAPConstants object representing the correct 1582 * version 1583 */ 1584 public void setSOAPVersion(SOAPConstants soapConstants) { 1585 msgContext.setSOAPConstants(soapConstants); 1586 } 1587 1588 /** 1589 * Invokes a specific operation using a synchronous request-response interaction mode. The invoke method takes 1590 * as parameters the object values corresponding to these defined parameter types. Implementation of the invoke 1591 * method must check whether the passed parameter values correspond to the number, order and types of parameters 1592 * specified in the corresponding operation specification. 1593 * 1594 * @param operationName - Name of the operation to invoke 1595 * @param params - Parameters for this invocation 1596 * 1597 * @return the value returned from the other end. 1598 * 1599 * @throws java.rmi.RemoteException - if there is any error in the remote method invocation or if the Call 1600 * object is not configured properly. 1601 */ 1602 public Object invoke(QName operationName, Object[] params) 1603 throws java.rmi.RemoteException { 1604 QName origOpName = this.operationName; 1605 this.operationName = operationName; 1606 try { 1607 return this.invoke(params); 1608 } 1609 catch (AxisFault af) { 1610 this.operationName = origOpName; 1611 if(af.detail != null && af.detail instanceof RemoteException) { 1612 throw ((RemoteException)af.detail); 1613 } 1614 throw af; 1615 } 1616 catch (java.rmi.RemoteException re) { 1617 this.operationName = origOpName; 1618 throw re; 1619 } 1620 catch (RuntimeException re) { 1621 this.operationName = origOpName; 1622 throw re; 1623 } 1624 catch (Error e) { 1625 this.operationName = origOpName; 1626 throw e; 1627 } 1628 } // invoke 1629 1630 /** 1631 * Invokes the operation associated with this Call object using the 1632 * passed in parameters as the arguments to the method. 1633 * 1634 * For Messaging (ie. non-RPC) the params argument should be an array 1635 * of SOAPBodyElements. <b>All</b> of them need to be SOAPBodyElements, 1636 * if any of them are not this method will default back to RPC. In the 1637 * Messaging case the return value will be a vector of SOAPBodyElements. 1638 * 1639 * @param params Array of parameters to invoke the Web Service with 1640 * @return Object Return value of the operation/method - or null 1641 * @throws java.rmi.RemoteException if there's an error 1642 */ 1643 public Object invoke(Object[] params) throws java.rmi.RemoteException { 1644 long t0=0, t1=0; 1645 if( tlog.isDebugEnabled() ) { 1646 t0=System.currentTimeMillis(); 1647 } 1648 /* First see if we're dealing with Messaging instead of RPC. */ 1649 /* If ALL of the params are SOAPBodyElements then we're doing */ 1650 /* Messaging, otherwise just fall through to normal RPC processing. */ 1651 /********************************************************************/ 1652 SOAPEnvelope env = null ; 1653 int i ; 1654 1655 for ( i = 0 ; params != null && i < params.length ; i++ ) 1656 if ( !(params[i] instanceof SOAPBodyElement) ) break ; 1657 1658 if ( params != null && params.length > 0 && i == params.length ) { 1659 /* ok, we're doing Messaging, so build up the message */ 1660 /******************************************************/ 1661 isMsg = true ; 1662 env = new SOAPEnvelope(msgContext.getSOAPConstants(), 1663 msgContext.getSchemaVersion()); 1664 1665 if ( !(params[0] instanceof SOAPEnvelope) ) 1666 for ( i = 0 ; i < params.length ; i++ ) 1667 env.addBodyElement( (SOAPBodyElement) params[i] ); 1668 1669 Message msg = new Message( env ); 1670 setRequestMessage(msg); 1671 1672 invoke(); 1673 1674 msg = msgContext.getResponseMessage(); 1675 if (msg == null) { 1676 if (FAULT_ON_NO_RESPONSE) { 1677 throw new AxisFault(Messages.getMessage("nullResponse00")); 1678 } else { 1679 return null; 1680 } 1681 } 1682 1683 env = msg.getSOAPEnvelope(); 1684 return( env.getBodyElements() ); 1685 } 1686 1687 1688 if ( operationName == null ) 1689 throw new AxisFault( Messages.getMessage("noOperation00") ); 1690 try { 1691 Object res=this.invoke(operationName.getNamespaceURI(), 1692 operationName.getLocalPart(), params); 1693 if( tlog.isDebugEnabled() ) { 1694 t1=System.currentTimeMillis(); 1695 tlog.debug("axis.Call.invoke: " + (t1-t0) + " " + operationName); 1696 } 1697 return res; 1698 } 1699 catch( AxisFault af) { 1700 if(af.detail != null && af.detail instanceof RemoteException) { 1701 throw ((RemoteException)af.detail); 1702 } 1703 throw af; 1704 } 1705 catch( Exception exp ) { 1706 //if ( exp instanceof AxisFault ) throw (AxisFault) exp ; 1707 entLog.debug(Messages.getMessage("toAxisFault00"), exp); 1708 throw new AxisFault( 1709 Messages.getMessage("errorInvoking00", "\n" + exp) ); 1710 } 1711 } 1712 1713 /** 1714 * Invokes the operation associated with this Call object using the passed 1715 * in parameters as the arguments to the method. This will return 1716 * immediately rather than waiting for the server to complete its 1717 * processing. 1718 * 1719 * NOTE: the return immediately part isn't implemented yet 1720 * 1721 * @param params Array of parameters to invoke the Web Service with 1722 * @throws JAXRPCException is there's an error 1723 */ 1724 public void invokeOneWay(Object[] params) { 1725 try { 1726 invokeOneWay = true; 1727 invoke( params ); 1728 } catch( Exception exp ) { 1729 throw new JAXRPCException( exp.toString() ); 1730 } finally { 1731 invokeOneWay = false; 1732 } 1733 } 1734 1735 /************************************************************************/ 1736 /* End of core JAX-RPC stuff */ 1737 /************************************************************************/ 1738 1739 /** Invoke the service with a custom SOAPEnvelope. 1740 * 1741 * Note: Not part of JAX-RPC specification. 1742 * 1743 * @param env a SOAPEnvelope to send. 1744 * @exception AxisFault 1745 */ 1746 public SOAPEnvelope invoke(SOAPEnvelope env) 1747 throws java.rmi.RemoteException { 1748 try { 1749 Message msg = null ; 1750 1751 msg = new Message( env ); 1752 setRequestMessage( msg ); 1753 invoke(); 1754 msg = msgContext.getResponseMessage(); 1755 if (msg == null) { 1756 if (this.FAULT_ON_NO_RESPONSE) { 1757 throw new AxisFault(Messages.getMessage("nullResponse00")); 1758 } else { 1759 return null; 1760 } 1761 } 1762 return( msg.getSOAPEnvelope() ); 1763 } 1764 catch( Exception exp ) { 1765 if ( exp instanceof AxisFault ) throw (AxisFault) exp ; 1766 1767 entLog.debug(Messages.getMessage("toAxisFault00"), exp); 1768 throw new AxisFault( 1769 Messages.getMessage("errorInvoking00", "\n" + exp) ); 1770 } 1771 } 1772 1773 1774 /** Register a Transport that should be used for URLs of the specified 1775 * protocol. 1776 * 1777 * Note: Not part of JAX-RPC specification. 1778 * 1779 * @param protocol the URL protocol (i.e. "tcp" for "tcp://" urls) 1780 * @param transportClass the class of a Transport type which will be used 1781 * for matching URLs. 1782 */ 1783 public static void setTransportForProtocol(String protocol, 1784 Class transportClass) { 1785 if (Transport.class.isAssignableFrom(transportClass)) 1786 transports.put(protocol, transportClass); 1787 else 1788 throw new InternalException(transportClass.toString()); 1789 } 1790 1791 /** 1792 * Set up the default transport URL mappings. 1793 * 1794 * This must be called BEFORE doing non-standard URL parsing (i.e. if you 1795 * want the system to accept a "local:" URL). This is why the Options class 1796 * calls it before parsing the command-line URL argument. 1797 * 1798 * Note: Not part of JAX-RPC specification. 1799 */ 1800 public static synchronized void initialize() { 1801 addTransportPackage("org.apache.axis.transport"); 1802 1803 setTransportForProtocol("java", 1804 org.apache.axis.transport.java.JavaTransport.class); 1805 setTransportForProtocol("local", 1806 org.apache.axis.transport.local.LocalTransport.class); 1807 setTransportForProtocol("http", HTTPTransport.class); 1808 setTransportForProtocol("https", HTTPTransport.class); 1809 } 1810 1811 /** 1812 * Cache of transport packages we've already added to the system 1813 * property. 1814 */ 1815 private static ArrayList transportPackages = null; 1816 1817 /** Add a package to the system protocol handler search path. This 1818 * enables users to create their own URLStreamHandler classes, and thus 1819 * allow custom protocols to be used in Axis (typically on the client 1820 * command line). 1821 * 1822 * For instance, if you add "samples.transport" to the packages property, 1823 * and have a class samples.transport.tcp.Handler, the system will be able 1824 * to parse URLs of the form "tcp://host:port..." 1825 * 1826 * Note: Not part of JAX-RPC specification. 1827 * 1828 * @param packageName the package in which to search for protocol names. 1829 */ 1830 public static synchronized void addTransportPackage(String packageName) { 1831 if (transportPackages == null) { 1832 transportPackages = new ArrayList(); 1833 String currentPackages = 1834 AxisProperties.getProperty(TRANSPORT_PROPERTY); 1835 if (currentPackages != null) { 1836 StringTokenizer tok = new StringTokenizer(currentPackages, 1837 "|"); 1838 while (tok.hasMoreTokens()) { 1839 transportPackages.add(tok.nextToken()); 1840 } 1841 } 1842 } 1843 1844 if (transportPackages.contains(packageName)) 1845 return; 1846 1847 transportPackages.add(packageName); 1848 1849 StringBuffer currentPackages = new StringBuffer(); 1850 for (Iterator i = transportPackages.iterator(); i.hasNext();) { 1851 String thisPackage = (String) i.next(); 1852 currentPackages.append(thisPackage); 1853 currentPackages.append('|'); 1854 } 1855 1856 System.setProperty(TRANSPORT_PROPERTY, currentPackages.toString()); 1857 } 1858 1859 /** 1860 * Convert the list of objects into RPCParam's based on the paramNames, 1861 * paramXMLTypes and paramModes variables. If those aren't set then just 1862 * return what was passed in. 1863 * 1864 * @param params Array of parameters to pass into the operation/method 1865 * @return Object[] Array of parameters to pass to invoke() 1866 */ 1867 private Object[] getParamList(Object[] params) { 1868 int numParams = 0 ; 1869 1870 // If we never set-up any names... then just return what was passed in 1871 ////////////////////////////////////////////////////////////////////// 1872 if (log.isDebugEnabled()) { 1873 log.debug( "operation=" + operation); 1874 if (operation != null) 1875 log.debug("operation.getNumParams()=" + 1876 operation.getNumParams()); 1877 } 1878 if ( operation == null || operation.getNumParams() == 0 ) 1879 return( params ); 1880 1881 // Count the number of IN and INOUT params, this needs to match the 1882 // number of params passed in - if not throw an error 1883 ///////////////////////////////////////////////////////////////////// 1884 numParams = operation.getNumInParams(); 1885 1886 if ( params == null || numParams != params.length ) 1887 throw new JAXRPCException( 1888 Messages.getMessage("parmMismatch00", 1889 "" + params.length, "" + numParams) ); 1890 1891 log.debug( "getParamList number of params: " + params.length); 1892 1893 // All ok - so now produce an array of RPCParams 1894 ////////////////////////////////////////////////// 1895 Vector result = new Vector(); 1896 int j = 0 ; 1897 ArrayList parameters = operation.getParameters(); 1898 1899 for (int i = 0; i < parameters.size(); i++) { 1900 ParameterDesc param = (ParameterDesc)parameters.get(i); 1901 if (param.getMode() != ParameterDesc.OUT) { 1902 QName paramQName = param.getQName(); 1903 1904 // Create an RPCParam if param isn't already an RPCParam. 1905 RPCParam rpcParam = null; 1906 Object p = params[j++]; 1907 if(p instanceof RPCParam) { 1908 rpcParam = (RPCParam)p; 1909 } else { 1910 rpcParam = new RPCParam(paramQName.getNamespaceURI(), 1911 paramQName.getLocalPart(), 1912 p); 1913 } 1914 // Attach the ParameterDescription to the RPCParam 1915 // so that the serializer can use the (javaType, xmlType) 1916 // information. 1917 rpcParam.setParamDesc(param); 1918 1919 // Add the param to the header or vector depending 1920 // on whether it belongs in the header or body. 1921 if (param.isInHeader()) { 1922 addHeader(new RPCHeaderParam(rpcParam)); 1923 } else { 1924 result.add(rpcParam); 1925 } 1926 } 1927 } 1928 return( result.toArray() ); 1929 } 1930 1931 /** 1932 * Set the Transport 1933 * 1934 * Note: Not part of JAX-RPC specification. 1935 * 1936 * @param trans the Transport object we'll use to set up 1937 * MessageContext properties. 1938 */ 1939 public void setTransport(Transport trans) { 1940 transport = trans; 1941 if (log.isDebugEnabled()) 1942 log.debug(Messages.getMessage("transport00", "" + transport)); 1943 } 1944 1945 /** Get the Transport registered for the given protocol. 1946 * 1947 * Note: Not part of JAX-RPC specification. 1948 * 1949 * @param protocol a protocol such as "http" or "local" which may 1950 * have a Transport object associated with it. 1951 * @return the Transport registered for this protocol, or null if none. 1952 */ 1953 public Transport getTransportForProtocol(String protocol) 1954 { 1955 Class transportClass = (Class)transports.get(protocol); 1956 Transport ret = null; 1957 if (transportClass != null) { 1958 try { 1959 ret = (Transport)transportClass.newInstance(); 1960 } catch (InstantiationException e) { 1961 } catch (IllegalAccessException e) { 1962 } 1963 } 1964 return ret; 1965 } 1966 1967 /** 1968 * Directly set the request message in our MessageContext. 1969 * 1970 * This allows custom message creation. 1971 * 1972 * Note: Not part of JAX-RPC specification. 1973 * 1974 * @param msg the new request message. 1975 */ 1976 public void setRequestMessage(Message msg) { 1977 String attachformat= (String)getProperty( 1978 ATTACHMENT_ENCAPSULATION_FORMAT); 1979 1980 if(null != attachformat){ 1981 org.apache.axis.attachments.Attachments attachments= 1982 msg.getAttachmentsImpl(); 1983 if(null != attachments) { 1984 if( null != attachformat && attachformat.equals( 1985 ATTACHMENT_ENCAPSULATION_FORMAT_MIME)) 1986 attachments.setSendType(attachments.SEND_TYPE_MIME); 1987 else if( null != attachformat && attachformat.equals( 1988 ATTACHMENT_ENCAPSULATION_FORMAT_DIME)) { 1989 attachments.setSendType(attachments.SEND_TYPE_DIME); 1990 } 1991 } 1992 } 1993 1994 if(null != attachmentParts && !attachmentParts.isEmpty()){ 1995 try{ 1996 org.apache.axis.attachments.Attachments attachments= msg.getAttachmentsImpl(); 1997 if(null == attachments) { 1998 throw new RuntimeException( 1999 Messages.getMessage("noAttachments")); 2000 } 2001 2002 attachments.setAttachmentParts(attachmentParts); 2003 }catch(org.apache.axis.AxisFault ex){ 2004 log.info(Messages.getMessage("axisFault00"), ex); 2005 throw new RuntimeException(ex.getMessage()); 2006 } 2007 } 2008 2009 msgContext.setRequestMessage(msg); 2010 attachmentParts.clear(); 2011 } 2012 2013 /** 2014 * Directly get the response message in our MessageContext. 2015 * 2016 * Shortcut for having to go thru the msgContext 2017 * 2018 * Note: Not part of JAX-RPC specification. 2019 * 2020 * @return the response Message object in the msgContext 2021 */ 2022 public Message getResponseMessage() { 2023 return msgContext.getResponseMessage(); 2024 } 2025 2026 /** 2027 * Obtain a reference to our MessageContext. 2028 * 2029 * Note: Not part of JAX-RPC specification. 2030 * 2031 * @return the MessageContext. 2032 */ 2033 public MessageContext getMessageContext () { 2034 return msgContext; 2035 } 2036 2037 /** 2038 * Add a header which should be inserted into each outgoing message 2039 * we generate. 2040 * 2041 * Note: Not part of JAX-RPC specification. 2042 * 2043 * @param header a SOAPHeaderElement to be inserted into messages 2044 */ 2045 public void addHeader(SOAPHeaderElement header) 2046 { 2047 if (myHeaders == null) { 2048 myHeaders = new Vector(); 2049 } 2050 myHeaders.add(header); 2051 } 2052 2053 /** 2054 * Clear the list of headers which we insert into each message 2055 * 2056 * Note: Not part of JAX-RPC specification. 2057 */ 2058 public void clearHeaders() 2059 { 2060 myHeaders = null; 2061 } 2062 2063 public TypeMapping getTypeMapping() 2064 { 2065 // Get the TypeMappingRegistry 2066 TypeMappingRegistry tmr = msgContext.getTypeMappingRegistry(); 2067 2068 // If a TypeMapping is not available, add one. 2069 return tmr.getOrMakeTypeMapping(getEncodingStyle()); 2070 } 2071 2072 /** 2073 * Register type mapping information for serialization/deserialization 2074 * 2075 * Note: Not part of JAX-RPC specification. 2076 * 2077 * @param javaType is the Java class of the data type. 2078 * @param xmlType the xsi:type QName of the associated XML type. 2079 * @param sf/df are the factories (or the Class objects of the factory). 2080 */ 2081 public void registerTypeMapping(Class javaType, QName xmlType, 2082 SerializerFactory sf, 2083 DeserializerFactory df) { 2084 registerTypeMapping(javaType, xmlType, sf, df, true); 2085 } 2086 2087 /** 2088 * Register type mapping information for serialization/deserialization 2089 * 2090 * Note: Not part of JAX-RPC specification. 2091 * 2092 * @param javaType is the Java class of the data type. 2093 * @param xmlType the xsi:type QName of the associated XML type. 2094 * @param sf/df are the factories (or the Class objects of the factory). 2095 * @param force Indicates whether to add the information if already registered. 2096 */ 2097 public void registerTypeMapping(Class javaType, QName xmlType, 2098 SerializerFactory sf, 2099 DeserializerFactory df, 2100 boolean force) { 2101 TypeMapping tm = getTypeMapping(); 2102 if (!force && tm.isRegistered(javaType, xmlType)) 2103 return; 2104 2105 // Register the information 2106 tm.register(javaType, xmlType, sf, df); 2107 } 2108 2109 public void registerTypeMapping(Class javaType, QName xmlType, 2110 Class sfClass, Class dfClass) { 2111 registerTypeMapping(javaType, xmlType, sfClass, dfClass, true); 2112 } 2113 2114 public void registerTypeMapping(Class javaType, 2115 QName xmlType, 2116 Class sfClass, 2117 Class dfClass, 2118 boolean force) { 2119 // Instantiate the factory using introspection. 2120 SerializerFactory sf = 2121 BaseSerializerFactory.createFactory(sfClass, javaType, xmlType); 2122 DeserializerFactory df = 2123 BaseDeserializerFactory.createFactory(dfClass, 2124 javaType, 2125 xmlType); 2126 if (sf != null || df != null) { 2127 registerTypeMapping(javaType, xmlType, sf, df, force); 2128 } 2129 } 2130 2131 /************************************************ 2132 * Invocation 2133 */ 2134 2135 /** Invoke an RPC service with a method name and arguments. 2136 * 2137 * This will call the service, serializing all the arguments, and 2138 * then deserialize the return value. 2139 * 2140 * Note: Not part of JAX-RPC specification. 2141 * 2142 * @param namespace the desired namespace URI of the method element 2143 * @param method the method name 2144 * @param args an array of Objects representing the arguments to the 2145 * invoked method. If any of these objects are RPCParams, 2146 * Axis will use the embedded name of the RPCParam as the 2147 * name of the parameter. Otherwise, we will serialize 2148 * each argument as an XML element called "arg<n>". 2149 * @return a deserialized Java Object containing the return value 2150 * @exception AxisFault 2151 */ 2152 public Object invoke(String namespace, String method, Object[] args) 2153 throws AxisFault { 2154 2155 if (log.isDebugEnabled()) { 2156 log.debug("Enter: Call::invoke(ns, meth, args)"); 2157 } 2158 2159 /** 2160 * Since JAX-RPC requires us to specify all or nothing, if setReturnType 2161 * was called (returnType != null) and we have args but addParameter 2162 * wasn't called (paramXMLTypes == null), then toss a fault. 2163 */ 2164 if (getReturnType() != null && args != null && args.length != 0 2165 && operation.getNumParams() == 0) { 2166 throw new AxisFault(Messages.getMessage("mustSpecifyParms")); 2167 } 2168 2169 RPCElement body = new RPCElement(namespace, method, getParamList(args)); 2170 2171 Object ret = invoke( body ); 2172 2173 if (log.isDebugEnabled()) { 2174 log.debug("Exit: Call::invoke(ns, meth, args)"); 2175 } 2176 2177 return ret; 2178 } 2179 2180 /** Convenience method to invoke a method with a default (empty) 2181 * namespace. Calls invoke() above. 2182 * 2183 * Note: Not part of JAX-RPC specification. 2184 * 2185 * @param method the method name 2186 * @param args an array of Objects representing the arguments to the 2187 * invoked method. If any of these objects are RPCParams, 2188 * Axis will use the embedded name of the RPCParam as the 2189 * name of the parameter. Otherwise, we will serialize 2190 * each argument as an XML element called "arg<n>". 2191 * @return a deserialized Java Object containing the return value 2192 * @exception AxisFault 2193 */ 2194 public Object invoke( String method, Object [] args ) throws AxisFault 2195 { 2196 return invoke("", method, args); 2197 } 2198 2199 /** Invoke an RPC service with a pre-constructed RPCElement. 2200 * 2201 * Note: Not part of JAX-RPC specification. 2202 * 2203 * @param body an RPCElement containing all the information about 2204 * this call. 2205 * @return a deserialized Java Object containing the return value 2206 * @exception AxisFault 2207 */ 2208 public Object invoke( RPCElement body ) throws AxisFault { 2209 if (log.isDebugEnabled()) { 2210 log.debug("Enter: Call::invoke(RPCElement)"); 2211 } 2212 2213 /** 2214 * Since JAX-RPC requires us to specify a return type if we've set 2215 * parameter types, check for this case right now and toss a fault 2216 * if things don't look right. 2217 */ 2218 if (!invokeOneWay && operation != null && 2219 operation.getNumParams() > 0 && getReturnType() == null) { 2220 // TCK: 2221 // Issue an error if the return type was not set, but continue processing. 2222 //throw new AxisFault(Messages.getMessage("mustSpecifyReturnType")); 2223 log.error(Messages.getMessage("mustSpecifyReturnType")); 2224 } 2225 2226 SOAPEnvelope reqEnv = 2227 new SOAPEnvelope(msgContext.getSOAPConstants(), 2228 msgContext.getSchemaVersion()); 2229 SOAPEnvelope resEnv = null ; 2230 Message reqMsg = new Message( reqEnv ); 2231 Message resMsg = null ; 2232 Vector resArgs = null ; 2233 Object result = null ; 2234 2235 // Clear the output params 2236 outParams = new HashMap(); 2237 outParamsList = new ArrayList(); 2238 2239 // Set both the envelope and the RPCElement encoding styles 2240 try { 2241 body.setEncodingStyle(getEncodingStyle()); 2242 2243 setRequestMessage(reqMsg); 2244 2245 reqEnv.addBodyElement(body); 2246 reqEnv.setMessageType(Message.REQUEST); 2247 2248 invoke(); 2249 } catch (Exception e) { 2250 entLog.debug(Messages.getMessage("toAxisFault00"), e); 2251 throw AxisFault.makeFault(e); 2252 } 2253 2254 resMsg = msgContext.getResponseMessage(); 2255 2256 if (resMsg == null) { 2257 if (FAULT_ON_NO_RESPONSE) { 2258 throw new AxisFault(Messages.getMessage("nullResponse00")); 2259 } else { 2260 return null; 2261 } 2262 } 2263 2264 resEnv = resMsg.getSOAPEnvelope(); 2265 SOAPBodyElement bodyEl = resEnv.getFirstBody(); 2266 if (bodyEl == null) { 2267 return null; 2268 } 2269 2270 if (bodyEl instanceof RPCElement) { 2271 try { 2272 resArgs = ((RPCElement) bodyEl).getParams(); 2273 } catch (Exception e) { 2274 log.error(Messages.getMessage("exception00"), e); 2275 throw AxisFault.makeFault(e); 2276 } 2277 2278 if (resArgs != null && resArgs.size() > 0) { 2279 2280 // If there is no return, then we start at index 0 to create the outParams Map. 2281 // If there IS a return, then we start with 1. 2282 int outParamStart = 0; 2283 2284 // If we have resArgs and the returnType is specified, then the first 2285 // resArgs is the return. If we have resArgs and neither returnType 2286 // nor paramXMLTypes are specified, then we assume that the caller is 2287 // following the non-JAX-RPC AXIS shortcut of not having to specify 2288 // the return, in which case we again assume the first resArgs is 2289 // the return. 2290 // NOTE 1: the non-JAX-RPC AXIS shortcut allows a potential error 2291 // to escape notice. If the caller IS NOT following the non-JAX-RPC 2292 // shortcut but instead intentionally leaves returnType and params 2293 // null (ie., a method that takes no parameters and returns nothing) 2294 // then, if we DO receive something it should be an error, but this 2295 // code passes it through. The ideal solution here is to require 2296 // this caller to set the returnType to void, but there's no void 2297 // type in XML. 2298 // NOTE 2: we should probably verify that the resArgs element 2299 // types match the expected returnType and paramXMLTypes, but I'm not 2300 // sure how to do that since the resArgs value is a Java Object 2301 // and the returnType and paramXMLTypes are QNames. 2302 2303 // GD 03/15/02 : We're now checking for invalid metadata 2304 // config at the top of this method, so don't need to do it 2305 // here. Check for void return, though. 2306 2307 boolean findReturnParam = false; 2308 QName returnParamQName = null; 2309 if (operation != null) 2310 returnParamQName = operation.getReturnQName(); 2311 2312 if (!XMLType.AXIS_VOID.equals(getReturnType())) { 2313 if (returnParamQName == null) { 2314 // Assume the first param is the return 2315 RPCParam param = (RPCParam)resArgs.get(0); 2316 result = param.getValue(); 2317 outParamStart = 1; 2318 } else { 2319 // If the QName of the return value was given to us, look 2320 // through the result arguments to find the right name 2321 findReturnParam = true; 2322 } 2323 } 2324 2325 // The following loop looks at the resargs and 2326 // converts the value to the appropriate return/out parameter 2327 // value. If the return value is found, is value is 2328 // placed in result. The remaining resargs are 2329 // placed in the outParams list (note that if a resArg 2330 // is found that does not match a operation parameter qname, 2331 // it is still placed in the outParms list). 2332 for (int i = outParamStart; i < resArgs.size(); i++) { 2333 RPCParam param = (RPCParam) resArgs.get(i); 2334 2335 Class javaType = getJavaTypeForQName(param.getQName()); 2336 Object value = param.getValue(); 2337 2338 // Convert type if needed 2339 if (javaType != null && value != null && 2340 !javaType.isAssignableFrom(value.getClass())) { 2341 value = JavaUtils.convert(value, javaType); 2342 } 2343 2344 // Check if this parameter is our return 2345 // otherwise just add it to our outputs 2346 if (findReturnParam && 2347 returnParamQName.equals(param.getQName())) { 2348 // found it! 2349 result = value; 2350 findReturnParam = false; 2351 } else { 2352 outParams.put(param.getQName(), value); 2353 outParamsList.add(value); 2354 } 2355 } 2356 2357 // added by scheu: 2358 // If the return param is still not found, that means 2359 // the returned value did not have the expected qname. 2360 // The soap specification indicates that this should be 2361 // accepted (and we also fail interop tests if we are strict here). 2362 // Look through the outParms and find one that 2363 // does not match one of the operation parameters. 2364 if (findReturnParam) { 2365 Iterator it = outParams.keySet().iterator(); 2366 while (it.hasNext() && findReturnParam) { 2367 QName qname = (QName) it.next(); 2368 ParameterDesc paramDesc = 2369 operation.getOutputParamByQName(qname); 2370 if (paramDesc == null) { 2371 // Doesn't match a paramter, so use this for the return 2372 findReturnParam = false; 2373 result = outParams.remove(qname); 2374 } 2375 } 2376 } 2377 2378 // If we were looking for a particular QName for the return and 2379 // still didn't find it, throw an exception 2380 if (findReturnParam) { 2381 String returnParamName = returnParamQName.toString(); 2382 throw new AxisFault(Messages.getMessage("noReturnParam", 2383 returnParamName)); 2384 } 2385 } 2386 } else { 2387 // This is a SOAPBodyElement, try to treat it like a return value 2388 try { 2389 result = bodyEl.getValueAsType(getReturnType()); 2390 } catch (Exception e) { 2391 // just return the SOAPElement 2392 result = bodyEl; 2393 } 2394 2395 } 2396 2397 if (log.isDebugEnabled()) { 2398 log.debug("Exit: Call::invoke(RPCElement)"); 2399 } 2400 2401 // Convert type if needed 2402 if (operation != null && operation.getReturnClass() != null) { 2403 result = JavaUtils.convert(result, operation.getReturnClass()); 2404 } 2405 2406 return( result ); 2407 } 2408 2409 /** 2410 * Get the javaType for a given parameter. 2411 * 2412 */ 2413 private Class getJavaTypeForQName(QName name) { 2414 if (operation == null) return null; 2415 2416 ParameterDesc param = operation.getOutputParamByQName(name); 2417 return param == null ? null : param.getJavaType(); 2418 } 2419 2420 /** 2421 * Set engine option. 2422 * 2423 * Note: Not part of JAX-RPC specification. 2424 */ 2425 public void setOption(String name, Object value) { 2426 service.getEngine().setOption(name, value); 2427 } 2428 2429 /** 2430 * Invoke this Call with its established MessageContext 2431 * (perhaps because you called this.setRequestMessage()) 2432 * 2433 * Note: Not part of JAX-RPC specification. 2434 * 2435 * @exception AxisFault 2436 */ 2437 public void invoke() throws AxisFault { 2438 if (log.isDebugEnabled()) { 2439 log.debug("Enter: Call::invoke()"); 2440 } 2441 2442 Message reqMsg = null ; 2443 SOAPEnvelope reqEnv = null ; 2444 2445 msgContext.reset(); 2446 msgContext.setResponseMessage(null); 2447 msgContext.setProperty( MessageContext.CALL, this ); 2448 msgContext.setProperty( WSDL_SERVICE, service ); 2449 msgContext.setProperty( WSDL_PORT_NAME, getPortName() ); 2450 if ( isMsg ) 2451 msgContext.setProperty( MessageContext.IS_MSG, "true" ); 2452 2453 if (username != null) { 2454 msgContext.setUsername(username); 2455 } 2456 if (password != null) { 2457 msgContext.setPassword(password); 2458 } 2459 msgContext.setMaintainSession(maintainSession); 2460 2461 if (operation != null) { 2462 msgContext.setOperation(operation); 2463 Rate2464 operation.setStyle(getOperationStyle()); 2465 operation.setUse(getOperationUse()); 2466 } 2467 2468 if (useSOAPAction) { 2469 msgContext.setUseSOAPAction(true); 2470 } 2471 if (SOAPActionURI != null) { 2472 msgContext.setSOAPActionURI(SOAPActionURI); 2473 } 2474 if (timeout != null) { 2475 msgContext.setTimeout(timeout.intValue()); 2476 } 2477 2478 // Determine client target service 2479 if (myService != null) { 2480 // If we have a SOAPService kicking around, use that directly 2481 msgContext.setService(myService); 2482 } else { 2483 if (portName != null) { 2484 // No explicit service. If we have a target service name, 2485 // try that. 2486 msgContext.setTargetService(portName.getLocalPart()); 2487 } else { 2488 // No direct config, so try the namespace of the first body. 2489 reqMsg = msgContext.getRequestMessage(); 2490 2491 if (reqMsg != null) { 2492 reqEnv = reqMsg.getSOAPEnvelope(); 2493 2494 SOAPBodyElement body = reqEnv.getFirstBody(); 2495 2496 if (body != null) { 2497 if ( body.getNamespaceURI() == null ) { 2498 throw new AxisFault("Call.invoke", 2499 Messages.getMessage("cantInvoke00", body.getName()), 2500 null, null); 2501 } else { 2502 msgContext.setTargetService(body.getNamespaceURI()); 2503 } 2504 } 2505 } 2506 } 2507 2508 SOAPService svc = msgContext.getService(); 2509 if (svc != null) { 2510 svc.setPropertyParent(myProperties); 2511 } else { 2512 msgContext.setPropertyParent(myProperties); 2513 } 2514 } 2515 if (log.isDebugEnabled()) { 2516 log.debug(Messages.getMessage("targetService", 2517 msgContext.getTargetService())); 2518 } 2519 2520 Message requestMessage = msgContext.getRequestMessage(); 2521 if (requestMessage != null) { 2522 reqEnv = requestMessage.getSOAPEnvelope(); 2523 2524 // If we have headers to insert, do so now. 2525 for (int i = 0 ; myHeaders != null && i < myHeaders.size() ; i++ ) { 2526 reqEnv.addHeader((SOAPHeaderElement)myHeaders.get(i)); 2527 } 2528 } 2529 2530 // set up transport if there is one 2531 if (transport != null) { 2532 transport.setupMessageContext(msgContext, this, service.getEngine()); 2533 } 2534 else 2535 msgContext.setTransportName( transportName ); 2536 2537 // For debugging - print request message 2538 if (log.isDebugEnabled()) { 2539 StringWriter writer = new StringWriter(); 2540 try { 2541 SerializationContext ctx = new SerializationContextImpl(writer, 2542 msgContext); 2543 reqEnv.output(ctx); 2544 writer.close(); 2545 } catch (Exception e) { 2546 log.debug(Messages.getMessage("exceptionPrinting"), e); 2547 } finally { 2548 log.debug(writer.getBuffer().toString()); 2549 } 2550 } 2551 2552 if(!invokeOneWay) { 2553 invokeEngine(msgContext); 2554 } else { 2555 invokeEngineOneWay(msgContext); 2556 } 2557 2558 if (log.isDebugEnabled()) { 2559 log.debug("Exit: Call::invoke()"); 2560 } 2561 } 2562 2563 private void invokeEngine(MessageContext msgContext) throws AxisFault { 2564 service.getEngine().invoke( msgContext ); 2565 2566 if (transport != null) 2567 transport.processReturnedMessageContext(msgContext); 2568 2569 Message resMsg = msgContext.getResponseMessage(); 2570 2571 if (resMsg == null) { 2572 if (this.FAULT_ON_NO_RESPONSE) { 2573 throw new AxisFault(Messages.getMessage("nullResponse00")); 2574 } else { 2575 return; 2576 } 2577 } 2578 2579 /** This must happen before deserialization... 2580 */ 2581 resMsg.setMessageType(Message.RESPONSE); 2582 2583 SOAPEnvelope resEnv = resMsg.getSOAPEnvelope(); 2584 2585 SOAPBodyElement respBody = resEnv.getFirstBody(); 2586 if (respBody instanceof SOAPFault) { 2587 if(operation == null || 2588 operation.getReturnClass() == null || 2589 operation.getReturnClass() != 2590 javax.xml.soap.SOAPMessage.class) 2591 throw ((SOAPFault)respBody).getFault(); 2592 } 2593 } 2594 2595 private void invokeEngineOneWay(final MessageContext msgContext) { 2596 Runnable runnable = new Runnable(){ 2597 public void run() { 2598 try { 2599 service.getEngine().invoke( msgContext ); 2600 } catch (AxisFault af){ 2601 log.debug(Messages.getMessage("exceptionPrinting"), af); 2602 } 2603 } 2604 }; 2605 Thread thread = new Thread(runnable); 2606 thread.start(); 2607 } 2608 2609 /** 2610 * Get the output parameters (if any) from the last invocation. 2611 * 2612 * NOTE that the params returned are all RPCParams, containing 2613 * name and value - if you want the value, you'll need to call 2614 * param.getValue(). 2615 * 2616 * @return Vector of RPCParams 2617 */ 2618 public Map getOutputParams() 2619 { 2620 return this.outParams; 2621 } 2622 2623 /** 2624 * Returns a List values for the output parameters of the last 2625 * invoked operation. 2626 * 2627 * @return Values for the output parameters. An empty List is 2628 * returned if there are no output values. 2629 * 2630 * @throws JAXRPCException - If this method is invoked for a 2631 * one-way operation or is invoked 2632 * before any invoke method has been called. 2633 */ 2634 public List getOutputValues() { 2635 return outParamsList; 2636 } 2637 2638 /** 2639 * Get the Service object associated with this Call object. 2640 * 2641 * Note: Not part of JAX-RPC specification. 2642 * 2643 * @return Service the Service object this Call object is associated with 2644 */ 2645 public Service getService() 2646 { 2647 return this.service; 2648 } 2649 2650 private SOAPService myService = null; 2651 2652 /** 2653 * 2654 */ 2655 public void setSOAPService(SOAPService service) 2656 { 2657 myService = service; 2658 if (service != null) { 2659 // Set the service so that it defers missing property gets to the 2660 // Call. So when client-side Handlers get at the MessageContext, 2661 // the property scoping will be MC -> SOAPService -> Call 2662 service.setPropertyParent(myProperties); 2663 service.setEngine(this.service.getAxisClient()); 2664 } 2665 } 2666 2667 /** 2668 * Sets the client-side request and response Handlers. This is handy 2669 * for programatically setting up client-side work without deploying 2670 * via WSDD or the EngineConfiguration mechanism. 2671 */ 2672 public void setClientHandlers(Handler reqHandler, Handler respHandler) 2673 { 2674 // Create a SOAPService which will be used as the client-side service 2675 // handler. 2676 setSOAPService(new SOAPService(reqHandler, null, respHandler)); 2677 } 2678 2679 protected java.util.Vector attachmentParts= new java.util.Vector(); 2680 2681 /** 2682 * This method adds an attachment. 2683 * 2684 * Note: Not part of JAX-RPC specification. 2685 * @exception RuntimeException if there is no support for attachments. 2686 * 2687 */ 2688 public void addAttachmentPart( Object attachment){ 2689 attachmentParts.add(attachment); 2690 } 2691 2692 /** 2693 * Add a fault for this operation 2694 * 2695 * Note: Not part of JAX-RPC specificaion 2696 */ 2697 public void addFault(QName qname, Class cls, 2698 QName xmlType, boolean isComplex) { 2699 if (operationSetManually) { 2700 throw new RuntimeException( 2701 Messages.getMessage("operationAlreadySet")); 2702 } 2703 2704 if (operation == null) 2705 operation = new OperationDesc(); 2706 2707 FaultDesc fault = new FaultDesc(); 2708 fault.setQName(qname); 2709 fault.setClassName(cls.getName()); 2710 fault.setXmlType(xmlType); 2711 fault.setComplex(isComplex); 2712 operation.addFault(fault); 2713 } 2714 2715 /** 2716 * Hand a complete OperationDesc to the Call, and note that this was 2717 * done so that others don't try to mess with it by calling addParameter, 2718 * setReturnType, etc. 2719 * 2720 * @param operation the OperationDesc to associate with this call. 2721 */ 2722 public void setOperation(OperationDesc operation) { 2723 this.operation = operation; 2724 operationSetManually = true; 2725 } 2726 2727 public OperationDesc getOperation() 2728 { 2729 return operation; 2730 } 2731 2732 public void clearOperation() { 2733 operation = null; 2734 operationSetManually = false; 2735 } 2736 }