| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.axis.client ; |
| |
| import org.apache.axis.AxisFault; |
| import org.apache.axis.AxisProperties; |
| import org.apache.axis.Constants; |
| import org.apache.axis.Handler; |
| import org.apache.axis.InternalException; |
| import org.apache.axis.Message; |
| import org.apache.axis.MessageContext; |
| import org.apache.axis.AxisEngine; |
| import org.apache.axis.SOAPPart; |
| import org.apache.axis.attachments.Attachments; |
| import org.apache.axis.components.logger.LogFactory; |
| import org.apache.axis.description.FaultDesc; |
| import org.apache.axis.description.OperationDesc; |
| import org.apache.axis.description.ParameterDesc; |
| import org.apache.axis.encoding.DeserializerFactory; |
| import org.apache.axis.encoding.SerializationContext; |
| import org.apache.axis.encoding.SerializerFactory; |
| import org.apache.axis.encoding.TypeMapping; |
| import org.apache.axis.encoding.TypeMappingRegistry; |
| import org.apache.axis.encoding.XMLType; |
| import org.apache.axis.encoding.ser.BaseDeserializerFactory; |
| import org.apache.axis.encoding.ser.BaseSerializerFactory; |
| import org.apache.axis.constants.Style; |
| import org.apache.axis.constants.Use; |
| import org.apache.axis.handlers.soap.SOAPService; |
| import org.apache.axis.message.RPCElement; |
| import org.apache.axis.message.RPCHeaderParam; |
| import org.apache.axis.message.RPCParam; |
| import org.apache.axis.message.SOAPBodyElement; |
| import org.apache.axis.message.SOAPEnvelope; |
| import org.apache.axis.message.SOAPFault; |
| import org.apache.axis.message.SOAPHeaderElement; |
| import org.apache.axis.soap.SOAPConstants; |
| import org.apache.axis.transport.http.HTTPTransport; |
| import org.apache.axis.utils.ClassUtils; |
| import org.apache.axis.utils.JavaUtils; |
| import org.apache.axis.utils.Messages; |
| import org.apache.axis.utils.LockableHashtable; |
| import org.apache.axis.wsdl.symbolTable.BindingEntry; |
| import org.apache.axis.wsdl.symbolTable.Parameter; |
| import org.apache.axis.wsdl.symbolTable.Parameters; |
| import org.apache.axis.wsdl.symbolTable.SymbolTable; |
| import org.apache.axis.wsdl.symbolTable.FaultInfo; |
| import org.apache.axis.wsdl.symbolTable.Utils; |
| import org.apache.commons.logging.Log; |
| |
| import javax.wsdl.Binding; |
| import javax.wsdl.BindingInput; |
| import javax.wsdl.BindingOperation; |
| import javax.wsdl.Operation; |
| import javax.wsdl.extensions.mime.MIMEPart; |
| import javax.wsdl.extensions.mime.MIMEMultipartRelated; |
| import javax.wsdl.Part; |
| import javax.wsdl.Port; |
| import javax.wsdl.PortType; |
| import javax.wsdl.extensions.soap.SOAPAddress; |
| import javax.wsdl.extensions.soap.SOAPBody; |
| import javax.wsdl.extensions.soap.SOAPOperation; |
| import javax.xml.namespace.QName; |
| import javax.xml.rpc.JAXRPCException; |
| import javax.xml.rpc.ParameterMode; |
| import javax.xml.soap.SOAPException; |
| import javax.xml.soap.SOAPMessage; |
| |
| import java.io.StringWriter; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| import java.util.Vector; |
| import java.rmi.RemoteException; |
| |
| /** |
| * Axis' JAXRPC Dynamic Invocation Interface implementation of the Call |
| * interface. This class should be used to actually invoke the Web Service. |
| * It can be prefilled by a WSDL document (on the constructor to the Service |
| * object) or you can fill in the data yourself. |
| * <pre> |
| * Standard properties defined by in JAX-RPC's javax..xml.rpc.Call interface: |
| * USERNAME_PROPERTY - User name for authentication |
| * PASSWORD_PROPERTY - Password for authentication |
| * SESSION_PROPERTY - Participate in a session with the endpoint? |
| * OPERATION_STYLE_PROPERTY - "rpc" or "document" |
| * SOAPACTION_USE_PROPERTY - Should SOAPAction be used? |
| * SOAPACTION_URI_PROPERTY - If SOAPAction is used, this is that action |
| * ENCODING_STYLE_PROPERTY - Default is SOAP 1.1: "http://schemas.xmlsoap.org/soap/encoding/" |
| * |
| * AXIS properties: |
| * SEND_TYPE_ATTR - Should we send the XSI type attributes (true/false) |
| * TIMEOUT - Timeout used by transport sender in milliseconds |
| * TRANSPORT_NAME - Name of transport handler to use |
| * ATTACHMENT_ENCAPSULATION_FORMAT- Send attachments as MIME the default, or DIME. |
| * CHARACTER_SET_ENCODING - Character set encoding to use for request |
| * </pre> |
| * |
| * @author Doug Davis (dug@us.ibm.com) |
| * @author Steve Loughran |
| */ |
| |
| public class Call implements javax.xml.rpc.Call { |
| protected static Log log = |
| LogFactory.getLog(Call.class.getName()); |
| private static Log tlog = |
| LogFactory.getLog(Constants.TIME_LOG_CATEGORY); |
| |
| // The enterprise category is for stuff that an enterprise product might |
| // want to track, but in a simple environment (like the AXIS build) would |
| // be nothing more than a nuisance. |
| protected static Log entLog = |
| LogFactory.getLog(Constants.ENTERPRISE_LOG_CATEGORY); |
| |
| private boolean parmAndRetReq = true ; |
| private Service service = null ; |
| private QName portName = null; |
| private QName portTypeName = null; |
| private QName operationName = null ; |
| |
| private MessageContext msgContext = null ; |
| |
| // Collection of properties to store and put in MessageContext at |
| // invoke() time. Known ones are stored in actual variables for |
| // efficiency/type-consistency. Unknown ones are in myProperties. |
| private LockableHashtable myProperties = new LockableHashtable(); |
| private String username = null; |
| private String password = null; |
| private boolean maintainSession = false; |
| private boolean useSOAPAction = false; |
| private String SOAPActionURI = null; |
| private Integer timeout = null; |
| private boolean useStreaming = false; |
| |
| /** Metadata for the operation associated with this Call */ |
| private OperationDesc operation = null; |
| /** This will be true if an OperationDesc is handed to us whole */ |
| private boolean operationSetManually = false; |
| |
| // Is this a one-way call? |
| private boolean invokeOneWay = false; |
| private boolean isMsg = false; |
| |
| // Our Transport, if any |
| private Transport transport = null ; |
| private String transportName = null ; |
| |
| // A couple places to store output parameters. |
| // As a HashMap, retrievable via QName (for getOutputParams). |
| private HashMap outParams = null; |
| // As a list, retrievable by index (for getOutputValues). |
| private ArrayList outParamsList = null; |
| |
| // A place to store any client-specified headers |
| private Vector myHeaders = null; |
| |
| public static final String SEND_TYPE_ATTR = AxisEngine.PROP_SEND_XSI; |
| |
| /** |
| * This is the name of a property to set the transport of the message |
| * |
| * @see #setProperty |
| */ |
| public static final String TRANSPORT_NAME = "transport_name" ; |
| |
| /** |
| * This is the character set encoding to use for the message |
| * |
| * @see #setProperty |
| */ |
| public static final String CHARACTER_SET_ENCODING = SOAPMessage.CHARACTER_SET_ENCODING; |
| |
| /** |
| * This is not the name of a property that can be set with |
| * setProperty, despite its name. |
| */ |
| public static final String TRANSPORT_PROPERTY= "java.protocol.handler.pkgs"; |
| |
| /** |
| * this is a property set in the message context when the invocation |
| * process begins, for the benefit of handlers |
| */ |
| public static final String WSDL_SERVICE = "wsdl.service"; |
| |
| /** |
| * this is a property set in the message context when the invocation |
| * process begins, for the benefit of handlers |
| */ |
| public static final String WSDL_PORT_NAME = "wsdl.portName"; |
| |
| /** |
| * @deprecated use WSDL_SERVICE instead. |
| */ |
| public static final String JAXRPC_SERVICE = WSDL_SERVICE; |
| |
| /** |
| * @deprecated use WSDL_PORT_NAME instead. |
| */ |
| public static final String JAXRPC_PORTTYPE_NAME = WSDL_PORT_NAME; |
| |
| /** |
| * If this property is true, the code will throw a fault if there is no |
| * response message from the server. Otherwise, the |
| * invoke method will return a null. |
| */ |
| public static final String FAULT_ON_NO_RESPONSE = "call.FaultOnNoResponse"; |
| |
| /** |
| * If this property is true, code will enforce must understand check on both |
| * the request and the response paths. |
| */ |
| public static final String CHECK_MUST_UNDERSTAND = "call.CheckMustUnderstand"; |
| |
| /** |
| * Property for setting attachment format. |
| * Can be set to either DIME or MIME (default) |
| * @see #setProperty |
| * @see #ATTACHMENT_ENCAPSULATION_FORMAT_DIME |
| * @see #ATTACHMENT_ENCAPSULATION_FORMAT_MIME |
| * @see #ATTACHMENT_ENCAPSULATION_FORMAT_MTOM |
| */ |
| public static final String ATTACHMENT_ENCAPSULATION_FORMAT= |
| "attachment_encapsulation_format"; |
| /** |
| * Property value for setting attachment format as MIME. |
| */ |
| public static final String ATTACHMENT_ENCAPSULATION_FORMAT_MIME= |
| "axis.attachment.style.mime"; |
| /** |
| * Property value for setting attachment format as DIME. |
| */ |
| public static final String ATTACHMENT_ENCAPSULATION_FORMAT_DIME= |
| "axis.attachment.style.dime"; |
| /** |
| * Property value for setting attachment format as DIME. |
| */ |
| public static final String ATTACHMENT_ENCAPSULATION_FORMAT_MTOM= |
| "axis.attachment.style.mtom"; |
| |
| /** |
| * Timeout property: should be accompanies by an integer |
| * @see #setProperty |
| */ |
| public static final String CONNECTION_TIMEOUT_PROPERTY = |
| "axis.connection.timeout"; |
| |
| /** |
| * Streaming property: should be accompanied by an boolean |
| * (i.e. NO high-fidelity recording, deserialize on the fly) |
| * @see #setProperty |
| */ |
| public static final String STREAMING_PROPERTY = |
| "axis.streaming"; |
| |
| /** |
| * Internal property to indicate a one way call. |
| * That will disable processing of response handlers. |
| */ |
| protected static final String ONE_WAY = |
| "axis.one.way"; |
| |
| /** |
| * A Hashtable mapping protocols (Strings) to Transports (classes) |
| */ |
| private static Hashtable transports = new Hashtable(); |
| |
| static ParameterMode [] modes = new ParameterMode [] { null, |
| ParameterMode.IN, |
| ParameterMode.OUT, |
| ParameterMode.INOUT }; |
| |
| /** This is true when someone has called setEncodingStyle() */ |
| private boolean encodingStyleExplicitlySet = false; |
| /** This is true when someone has called setOperationUse() */ |
| private boolean useExplicitlySet = false; |
| |
| /** |
| * the name of a SOAP service that the call is bound to |
| */ |
| private SOAPService myService = null; |
| |
| /** |
| * these are our attachments |
| */ |
| protected java.util.Vector attachmentParts = new java.util.Vector(); |
| |
| /** This is false when invoke() is called. */ |
| private boolean isNeverInvoked = true; |
| |
| static { |
| initialize(); |
| } |
| |
| /************************************************************************/ |
| /* Start of core JAX-RPC stuff */ |
| /************************************************************************/ |
| |
| /** |
| * Default constructor - not much else to say. |
| * |
| * @param service the <code>Service</code> this <code>Call</code> will |
| * work with |
| */ |
| public Call(Service service) { |
| this.service = service ; |
| AxisEngine engine = service.getEngine(); |
| msgContext = new MessageContext( engine ); |
| myProperties.setParent(engine.getOptions()); |
| maintainSession = service.getMaintainSession(); |
| } |
| |
| /** |
| * Build a call from a URL string. |
| * |
| * This is handy so that you don't have to manually call Call.initialize() |
| * in order to register custom transports. In other words, whereas doing |
| * a new URL("local:...") would fail, new Call("local:...") works because |
| * we do the initialization of our own and any configured custom protocols. |
| * |
| * @param url the target endpoint URL |
| * @exception MalformedURLException |
| */ |
| public Call(String url) throws MalformedURLException { |
| this(new Service()); |
| setTargetEndpointAddress(new URL(url)); |
| } |
| |
| /** |
| * Build a call from a URL. |
| * |
| * @param url the target endpoint URL |
| */ |
| public Call(URL url) { |
| this(new Service()); |
| setTargetEndpointAddress(url); |
| } |
| |
| //////////////////////////// |
| // |
| // Properties and the shortcuts for common ones. |
| // |
| |
| /** |
| * Allows you to set a named property to the passed in value. |
| * There are a few known properties (like username, password, etc) |
| * that are variables in Call. The rest of the properties are |
| * stored in a Hashtable. These common properties should be |
| * accessed via the accessors for speed/type safety, but they may |
| * still be obtained via this method. It's up to one of the |
| * Handlers (or the Axis engine itself) to go looking for |
| * one of them. |
| * |
| * There are various well defined properties defined in the |
| * JAX-RPC specification and declared in the Call and Stub classes. |
| * It is not possible to set any other properties beginning in java. or |
| * javax. that are not in the specification. |
| * @see javax.xml.rpc.Stub |
| * @see javax.xml.rpc.Call |
| * |
| * There are other properties implemented in this class above and |
| * beyond those of the JAX-RPC spec |
| * Specifically, ATTACHMENT_ENCAPSULATION_FORMAT, CONNECTION_TIMEOUT_PROPERTY, |
| * and TRANSPORT_NAME. |
| * |
| * It is intended that all future Axis-specific properties will begin |
| * with axis. or apache. To ensure integration with future versions Axis, |
| * use different prefixes for your own properties. |
| * |
| * Axis developers: keep this in sync with propertyNames below |
| * @see #ATTACHMENT_ENCAPSULATION_FORMAT |
| * @see #TRANSPORT_NAME |
| * @see #CONNECTION_TIMEOUT_PROPERTY |
| * @param name Name of the property |
| * @param value Value of the property |
| */ |
| public void setProperty(String name, Object value) { |
| if (name == null || value == null) { |
| throw new JAXRPCException( |
| Messages.getMessage(name == null ? |
| "badProp03" : "badProp04")); |
| } |
| else if (name.equals(USERNAME_PROPERTY)) { |
| verifyStringProperty(name, value); |
| setUsername((String) value); |
| } |
| else if (name.equals(PASSWORD_PROPERTY)) { |
| verifyStringProperty(name, value); |
| setPassword((String) value); |
| } |
| else if (name.equals(SESSION_MAINTAIN_PROPERTY)) { |
| verifyBooleanProperty(name, value); |
| setMaintainSession(((Boolean) value).booleanValue()); |
| } |
| else if (name.equals(OPERATION_STYLE_PROPERTY)) { |
| verifyStringProperty(name, value); |
| setOperationStyle((String) value); |
| if (getOperationStyle() == Style.DOCUMENT || |
| getOperationStyle() == Style.WRAPPED) { |
| setOperationUse(Use.LITERAL_STR); |
| } else if (getOperationStyle() == Style.RPC) { |
| setOperationUse(Use.ENCODED_STR); |
| } |
| } |
| else if (name.equals(SOAPACTION_USE_PROPERTY)) { |
| verifyBooleanProperty(name, value); |
| setUseSOAPAction(((Boolean) value).booleanValue()); |
| } |
| else if (name.equals(SOAPACTION_URI_PROPERTY)) { |
| verifyStringProperty(name, value); |
| setSOAPActionURI((String) value); |
| } |
| else if (name.equals(ENCODINGSTYLE_URI_PROPERTY)) { |
| verifyStringProperty(name, value); |
| setEncodingStyle((String) value); |
| } |
| else if (name.equals(Stub.ENDPOINT_ADDRESS_PROPERTY)) { |
| verifyStringProperty(name, value); |
| setTargetEndpointAddress((String) value); |
| } |
| else if ( name.equals(TRANSPORT_NAME) ) { |
| verifyStringProperty(name, value); |
| transportName = (String) value ; |
| if (transport != null) { |
| transport.setTransportName((String) value); |
| } |
| } |
| else if ( name.equals(ATTACHMENT_ENCAPSULATION_FORMAT) ) { |
| verifyStringProperty(name, value); |
| if(!value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_MIME ) && |
| !value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_MTOM ) && |
| !value.equals(ATTACHMENT_ENCAPSULATION_FORMAT_DIME )) |
| throw new JAXRPCException( |
| Messages.getMessage("badattachmenttypeerr", new String[] { |
| (String) value, ATTACHMENT_ENCAPSULATION_FORMAT_MIME + " " |
| +ATTACHMENT_ENCAPSULATION_FORMAT_MTOM + " " |
| +ATTACHMENT_ENCAPSULATION_FORMAT_DIME })); |
| } |
| else if (name.equals(CONNECTION_TIMEOUT_PROPERTY)) { |
| verifyIntegerProperty(name,value); |
| setTimeout((Integer)value); |
| } |
| else if (name.equals(STREAMING_PROPERTY)) { |
| verifyBooleanProperty(name, value); |
| setStreaming(((Boolean) value).booleanValue()); |
| } |
| else if (name.equals(CHARACTER_SET_ENCODING)) { |
| verifyStringProperty(name, value); |
| } |
| else if (name.startsWith("java.") || name.startsWith("javax.")) { |
| throw new JAXRPCException( |
| Messages.getMessage("badProp05", name)); |
| } |
| myProperties.put(name, value); |
| } // setProperty |
| |
| /** |
| * Verify that the type of the object is a String, and throw |
| * an i18n-ized exception if not |
| * @param name |
| * @param value |
| * @throws JAXRPCException if value is not a String |
| */ |
| private void verifyStringProperty(String name, Object value) { |
| if (!(value instanceof String)) { |
| throw new JAXRPCException( |
| Messages.getMessage("badProp00", new String[] |
| {name, |
| "java.lang.String", |
| value.getClass().getName()})); |
| } |
| } |
| |
| /** |
| * Verify that the type of the object is a Boolean, and throw |
| * an i18n-ized exception if not |
| * @param name |
| * @param value |
| * @throws JAXRPCException if value is not a Boolean |
| */ |
| private void verifyBooleanProperty(String name, Object value) { |
| if (!(value instanceof Boolean)) { |
| throw new JAXRPCException( |
| Messages.getMessage("badProp00", new String[] |
| {name, |
| "java.lang.Boolean", |
| value.getClass().getName()})); |
| } |
| } |
| |
| /** |
| * Verify that the type of the object is an Integer, and throw |
| * an i18n-ized exception if not |
| * @param name |
| * @param value |
| * @throws JAXRPCException if value is not an Integer |
| */ |
| private void verifyIntegerProperty(String name, Object value) { |
| if (!(value instanceof Integer)) { |
| throw new JAXRPCException( |
| Messages.getMessage("badProp00", new String[] |
| {name, |
| "java.lang.Integer", |
| value.getClass().getName()})); |
| } |
| } |
| |
| /** |
| * Returns the value associated with the named property. |
| * |
| * @param name the name of the property |
| * @return Object value of the property or null if the property is not set |
| * @throws JAXRPCException if the requested property is not a supported property |
| */ |
| public Object getProperty(String name) { |
| if (name == null || !isPropertySupported(name)) { |
| throw new JAXRPCException(name == null ? |
| Messages.getMessage("badProp03") : |
| Messages.getMessage("badProp05", name)); |
| } |
| return myProperties.get(name); |
| } // getProperty |
| |
| /** |
| * Removes (if set) the named property. |
| * |
| * @param name name of the property to remove |
| */ |
| public void removeProperty(String name) { |
| if (name == null || !isPropertySupported(name)) { |
| throw new JAXRPCException(name == null ? |
| Messages.getMessage("badProp03") : |
| Messages.getMessage("badProp05", name)); |
| } |
| myProperties.remove(name); |
| } // removeProperty |
| |
| /** |
| * Configurable properties supported by this Call object. |
| */ |
| private static ArrayList propertyNames = new ArrayList(); |
| static { |
| propertyNames.add(USERNAME_PROPERTY); |
| propertyNames.add(PASSWORD_PROPERTY); |
| propertyNames.add(SESSION_MAINTAIN_PROPERTY); |
| propertyNames.add(OPERATION_STYLE_PROPERTY); |
| propertyNames.add(SOAPACTION_USE_PROPERTY); |
| propertyNames.add(SOAPACTION_URI_PROPERTY); |
| propertyNames.add(ENCODINGSTYLE_URI_PROPERTY); |
| propertyNames.add(Stub.ENDPOINT_ADDRESS_PROPERTY); |
| propertyNames.add(TRANSPORT_NAME); |
| propertyNames.add(ATTACHMENT_ENCAPSULATION_FORMAT); |
| propertyNames.add(CONNECTION_TIMEOUT_PROPERTY); |
| propertyNames.add(CHARACTER_SET_ENCODING); |
| } |
| |
| public Iterator getPropertyNames() { |
| return propertyNames.iterator(); |
| } |
| |
| public boolean isPropertySupported(String name) { |
| return propertyNames.contains(name) || (!name.startsWith("java.") |
| && !name.startsWith("javax.")); |
| } |
| |
| /** |
| * Set the username. |
| * |
| * @param username the new user name |
| */ |
| public void setUsername(String username) { |
| this.username = username; |
| } // setUsername |
| |
| /** |
| * Get the user name. |
| * |
| * @return the user name |
| */ |
| public String getUsername() { |
| return username; |
| } // getUsername |
| |
| /** |
| * Set the password. |
| * |
| * @param password plain-text copy of the password |
| */ |
| public void setPassword(String password) { |
| this.password = password; |
| } // setPassword |
| |
| /** |
| * Get the password. |
| * |
| * @return a plain-text copy of the password |
| */ |
| public String getPassword() { |
| return password; |
| } // getPassword |
| |
| /** |
| * Determine whether we'd like to track sessions or not. This |
| * overrides the default setting from the service. |
| * This just passes through the value into the MessageContext. |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param yesno true if session state is desired, false if not. |
| */ |
| public void setMaintainSession(boolean yesno) { |
| maintainSession = yesno; |
| } |
| |
| /** |
| * Get the value of maintainSession flag. |
| * |
| * @return true if session is maintained, false otherwise |
| */ |
| public boolean getMaintainSession() { |
| return maintainSession; |
| } |
| |
| /** |
| * Set the operation style: "document", "rpc" |
| * @param operationStyle string designating style |
| */ |
| public void setOperationStyle(String operationStyle) { |
| Style style = Style.getStyle(operationStyle, Style.DEFAULT); |
| setOperationStyle(style); |
| } // setOperationStyle |
| |
| /** |
| * Set the operation style |
| * |
| * @param operationStyle |
| */ |
| public void setOperationStyle(Style operationStyle) { |
| if (operation == null) { |
| operation = new OperationDesc(); |
| } |
| |
| operation.setStyle(operationStyle); |
| |
| // If no one has explicitly set the use, we should track |
| // the style. If it's non-RPC, default to LITERAL. |
| if (!useExplicitlySet) { |
| if (operationStyle != Style.RPC) { |
| operation.setUse(Use.LITERAL); |
| } |
| } |
| |
| // If no one has explicitly set the encodingStyle, we should |
| // track the style. If it's RPC, default to SOAP-ENC, otherwise |
| // default to "". |
| if (!encodingStyleExplicitlySet) { |
| String encStyle = ""; |
| if (operationStyle == Style.RPC) { |
| // RPC style defaults to encoded, otherwise default to literal |
| encStyle = msgContext.getSOAPConstants().getEncodingURI(); |
| } |
| msgContext.setEncodingStyle(encStyle); |
| } |
| } |
| |
| /** |
| * Get the operation style. |
| * |
| * @return the <code>Style</code> of the operation |
| */ |
| public Style getOperationStyle() { |
| if (operation != null) { |
| return operation.getStyle(); |
| } |
| return Style.DEFAULT; |
| } // getOperationStyle |
| |
| /** |
| * Set the operation use: "literal", "encoded" |
| * @param operationUse string designating use |
| */ |
| public void setOperationUse(String operationUse) { |
| Use use = Use.getUse(operationUse, Use.DEFAULT); |
| setOperationUse(use); |
| } // setOperationUse |
| |
| /** |
| * Set the operation use |
| * @param operationUse |
| */ |
| public void setOperationUse(Use operationUse) { |
| useExplicitlySet = true; |
| |
| if (operation == null) { |
| operation = new OperationDesc(); |
| } |
| |
| operation.setUse(operationUse); |
| if (!encodingStyleExplicitlySet) { |
| String encStyle = ""; |
| if (operationUse == Use.ENCODED) { |
| // RPC style defaults to encoded, otherwise default to literal |
| encStyle = msgContext.getSOAPConstants().getEncodingURI(); |
| } |
| msgContext.setEncodingStyle(encStyle); |
| } |
| } |
| |
| /** |
| * Get the operation use. |
| * |
| * @return the <code>Use</code> of the operation |
| */ |
| public Use getOperationUse() { |
| if (operation != null) { |
| return operation.getUse(); |
| } |
| return Use.DEFAULT; |
| } // getOperationStyle |
| |
| /** |
| * Flag to indicate if soapAction should be used. |
| * |
| * @param useSOAPAction true if the soapAction header is to be used to |
| * help find the method to invoke, false otherwise |
| */ |
| public void setUseSOAPAction(boolean useSOAPAction) { |
| this.useSOAPAction = useSOAPAction; |
| } // setUseSOAPAction |
| |
| /** |
| * Discover if soapAction is being used. |
| * |
| * @return true if it is, false otherwise |
| */ |
| public boolean useSOAPAction() { |
| return useSOAPAction; |
| } // useSOAPAction |
| |
| /** |
| * Set the soapAction URI. |
| * |
| * @param SOAPActionURI the new SOAP action URI |
| */ |
| public void setSOAPActionURI(String SOAPActionURI) { |
| useSOAPAction = true; |
| this.SOAPActionURI = SOAPActionURI; |
| } // setSOAPActionURI |
| |
| /** |
| * Get the soapAction URI. |
| * |
| * @return the curretn SOAP action URI |
| */ |
| public String getSOAPActionURI() { |
| return SOAPActionURI; |
| } // getSOAPActionURI |
| |
| /** |
| * Sets the encoding style to the URL passed in. |
| * |
| * @param namespaceURI URI of the encoding to use. |
| */ |
| public void setEncodingStyle(String namespaceURI) { |
| encodingStyleExplicitlySet = true; |
| msgContext.setEncodingStyle(namespaceURI); |
| } |
| |
| /** |
| * Returns the encoding style as a URI that should be used for the SOAP |
| * message. |
| * |
| * @return String URI of the encoding style to use |
| */ |
| public String getEncodingStyle() { |
| return msgContext.getEncodingStyle(); |
| } |
| |
| /** |
| * Sets the endpoint address of the target service port. This address must |
| * correspond to the transport specified in the binding for this Call |
| * instance. |
| * |
| * @param address - Endpoint address of the target service port; specified |
| * as URI |
| */ |
| public void setTargetEndpointAddress(String address) { |
| URL urlAddress; |
| try { |
| urlAddress = new URL(address); |
| } |
| catch (MalformedURLException mue) { |
| throw new JAXRPCException(mue); |
| } |
| setTargetEndpointAddress(urlAddress); |
| } |
| |
| /** |
| * Sets the URL of the target Web Service. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param address URL of the target Web Service |
| */ |
| public void setTargetEndpointAddress(java.net.URL address) { |
| try { |
| if ( address == null ) { |
| setTransport(null); |
| return ; |
| } |
| |
| String protocol = address.getProtocol(); |
| |
| // Handle the case where the protocol is the same but we |
| // just want to change the URL - if so just set the URL, |
| // creating a new Transport object will drop all session |
| // data - and we want that stuff to persist between invoke()s. |
| // Technically the session data should be in the message |
| // context so that it can be persistent across transports |
| // as well, but for now the data is in the Transport object. |
| //////////////////////////////////////////////////////////////// |
| if ( this.transport != null ) { |
| String oldAddr = this.transport.getUrl(); |
| if ( oldAddr != null && !oldAddr.equals("") ) { |
| URL tmpURL = new URL( oldAddr ); |
| String oldProto = tmpURL.getProtocol(); |
| if ( protocol.equals(oldProto) ) { |
| this.transport.setUrl( address.toString() ); |
| return ; |
| } |
| } |
| } |
| |
| // Do we already have a transport for this address? |
| Transport transport = service.getTransportForURL(address); |
| if (transport != null) { |
| setTransport(transport); |
| } |
| else { |
| // We don't already have a transport for this address. Create one. |
| transport = getTransportForProtocol(protocol); |
| if (transport == null) |
| throw new AxisFault("Call.setTargetEndpointAddress", |
| Messages.getMessage("noTransport01", |
| protocol), null, null); |
| transport.setUrl(address.toString()); |
| setTransport(transport); |
| service.registerTransportForURL(address, transport); |
| } |
| } |
| catch( Exception exp ) { |
| log.error(Messages.getMessage("exception00"), exp); |
| // do what? |
| // throw new AxisFault("Call.setTargetEndpointAddress", |
| //"Malformed URL Exception: " + e.getMessage(), null, null); |
| } |
| } |
| |
| /** |
| * Returns the URL of the target Web Service. |
| * |
| * @return URL URL of the target Web Service |
| */ |
| public String getTargetEndpointAddress() { |
| try { |
| if ( transport == null ) return( null ); |
| return( transport.getUrl() ); |
| } |
| catch( Exception exp ) { |
| return( null ); |
| } |
| } |
| |
| public Integer getTimeout() { |
| return timeout; |
| } |
| |
| public void setTimeout(Integer timeout) { |
| this.timeout = timeout; |
| } |
| |
| public boolean getStreaming() { |
| return useStreaming; |
| } |
| |
| public void setStreaming(boolean useStreaming) { |
| this.useStreaming = useStreaming; |
| } |
| // |
| // end properties code. |
| // |
| //////////////////////////// |
| |
| /** |
| * Is the caller required to provide the parameter and return type |
| * specification? |
| * If true, then |
| * addParameter and setReturnType MUST be called to provide the meta data. |
| * If false, then |
| * addParameter and setReturnType SHOULD NOT be called because the |
| * Call object already has the meta data describing the |
| * parameters and return type. If addParameter is called, the specified |
| * parameter is added to the end of the list of parameters. |
| */ |
| public boolean isParameterAndReturnSpecRequired(QName operationName) { |
| return parmAndRetReq; |
| } // isParameterAndReturnSpecRequired |
| |
| /** |
| * Adds the specified parameter to the list of parameters for the |
| * operation associated with this Call object. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param paramName Name that will be used for the parameter in the XML |
| * @param xmlType XMLType of the parameter |
| * @param parameterMode one of IN, OUT or INOUT |
| */ |
| public void addParameter(QName paramName, QName xmlType, |
| ParameterMode parameterMode) { |
| Class javaType = null; |
| TypeMapping tm = getTypeMapping(); |
| if (tm != null) { |
| javaType = tm.getClassForQName(xmlType); |
| } |
| addParameter(paramName, xmlType, javaType, parameterMode); |
| } |
| |
| /** |
| * Adds the specified parameter to the list of parameters for the |
| * operation associated with this Call object. |
| * |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param paramName Name that will be used for the parameter in the XML |
| * @param xmlType XMLType of the parameter |
| * @param javaType The Java class of the parameter |
| * @param parameterMode one of IN, OUT or INOUT |
| */ |
| public void addParameter(QName paramName, QName xmlType, |
| Class javaType, ParameterMode parameterMode) { |
| |
| if (operationSetManually) { |
| throw new RuntimeException( |
| Messages.getMessage("operationAlreadySet")); |
| } |
| |
| if (operation == null) |
| operation = new OperationDesc(); |
| |
| ParameterDesc param = new ParameterDesc(); |
| byte mode = ParameterDesc.IN; |
| if (parameterMode == ParameterMode.INOUT) { |
| mode = ParameterDesc.INOUT; |
| param.setIsReturn(true); |
| } else if (parameterMode == ParameterMode.OUT) { |
| mode = ParameterDesc.OUT; |
| param.setIsReturn(true); |
| } |
| param.setMode(mode); |
| param.setQName(new QName(paramName.getNamespaceURI(),Utils.getLastLocalPart(paramName.getLocalPart()))); |
| param.setTypeQName( xmlType ); |
| param.setJavaType( javaType ); |
| |
| operation.addParameter(param); |
| parmAndRetReq = true; |
| } |
| |
| /** |
| * Adds the specified parameter to the list of parameters for the |
| * operation associated with this Call object. |
| * |
| * @param paramName Name that will be used for the parameter in the XML |
| * @param xmlType XMLType of the parameter |
| * @param parameterMode one of IN, OUT or INOUT |
| */ |
| public void addParameter(String paramName, QName xmlType, |
| ParameterMode parameterMode) { |
| Class javaType = null; |
| TypeMapping tm = getTypeMapping(); |
| if (tm != null) { |
| javaType = tm.getClassForQName(xmlType); |
| } |
| addParameter(new QName("", paramName), xmlType, |
| javaType, parameterMode); |
| } |
| |
| /** |
| * Adds a parameter type and mode for a specific operation. Note that the |
| * client code is not required to call any addParameter and setReturnType |
| * methods before calling the invoke method. A Call implementation class |
| * can determine the parameter types by using the Java reflection and |
| * configured type mapping registry. |
| * |
| * @param paramName - Name of the parameter |
| * @param xmlType - XML datatype of the parameter |
| * @param javaType - The Java class of the parameter |
| * @param parameterMode - Mode of the parameter-whether IN, OUT or INOUT |
| * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns |
| * false, then addParameter MAY throw |
| * JAXRPCException....actually Axis allows |
| * modification in such cases |
| */ |
| public void addParameter(String paramName, QName xmlType, |
| Class javaType, ParameterMode parameterMode) { |
| addParameter(new QName("", paramName), xmlType, |
| javaType, parameterMode); |
| } |
| |
| /** |
| * Adds a parameter type as a soap:header. |
| * |
| * @param paramName - Name of the parameter |
| * @param xmlType - XML datatype of the parameter |
| * @param parameterMode - Mode of the parameter-whether IN, OUT or INOUT |
| * @param headerMode - Mode of the header. Even if this is an INOUT |
| * parameter, it need not be in the header in both |
| * directions. |
| * @throws JAXRPCException - if isParameterAndReturnSpecRequired returns |
| * false, then addParameter MAY throw |
| * JAXRPCException....actually Axis allows |
| * modification in such cases |
| */ |
| public void addParameterAsHeader(QName paramName, QName xmlType, |
| ParameterMode parameterMode, |
| ParameterMode headerMode) { |
| Class javaType = null; |
| TypeMapping tm = getTypeMapping(); |
| if (tm != null) { |
| javaType = tm.getClassForQName(xmlType); |
| } |
| addParameterAsHeader(paramName, xmlType, javaType, |
| parameterMode, headerMode); |
| } |
| |
| /** |
| |
| * Adds a parameter type as a soap:header. |
| * @param paramName - Name of the parameter |
| * @param xmlType - XML datatype of the parameter |
| * @param javaType - The Java class of the parameter |
| * @param parameterMode - Mode of the parameter-whether IN, OUT or INOUT |
| * @param headerMode - Mode of the header. Even if this is an INOUT |
| * parameter, it need not be in the header in both |
| * directions. |
| * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns |
| * false, then addParameter MAY throw |
| * JAXRPCException....actually Axis allows |
| * modification in such cases |
| */ |
| public void addParameterAsHeader(QName paramName, QName xmlType, |
| Class javaType, ParameterMode parameterMode, |
| ParameterMode headerMode) { |
| if (operationSetManually) { |
| throw new RuntimeException( |
| Messages.getMessage("operationAlreadySet")); |
| } |
| |
| if (operation == null) |
| operation = new OperationDesc(); |
| |
| ParameterDesc param = new ParameterDesc(); |
| param.setQName(new QName(paramName.getNamespaceURI(),Utils.getLastLocalPart(paramName.getLocalPart()))); |
| param.setTypeQName(xmlType); |
| param.setJavaType(javaType); |
| if (parameterMode == ParameterMode.IN) { |
| param.setMode(ParameterDesc.IN); |
| } |
| else if (parameterMode == ParameterMode.INOUT) { |
| param.setMode(ParameterDesc.INOUT); |
| } |
| else if (parameterMode == ParameterMode.OUT) { |
| param.setMode(ParameterDesc.OUT); |
| } |
| if (headerMode == ParameterMode.IN) { |
| param.setInHeader(true); |
| } |
| else if (headerMode == ParameterMode.INOUT) { |
| param.setInHeader(true); |
| param.setOutHeader(true); |
| } |
| else if (headerMode == ParameterMode.OUT) { |
| param.setOutHeader(true); |
| } |
| operation.addParameter(param); |
| parmAndRetReq = true; |
| } // addParameterAsHeader |
| |
| /** |
| * Return the QName of the type of the parameters with the given name. |
| * |
| * @param paramName name of the parameter to return |
| * @return XMLType XMLType of paramName, or null if not found. |
| */ |
| public QName getParameterTypeByName(String paramName) { |
| QName paramQName = new QName("", paramName); |
| |
| return getParameterTypeByQName(paramQName); |
| } |
| |
| /** |
| * Return the QName of the type of the parameters with the given name. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param paramQName QName of the parameter to return |
| * @return XMLType XMLType of paramQName, or null if not found. |
| */ |
| public QName getParameterTypeByQName(QName paramQName) { |
| ParameterDesc param = operation.getParamByQName(paramQName); |
| if (param != null) { |
| return param.getTypeQName(); |
| } |
| return( null ); |
| } |
| |
| /** |
| * Sets the return type of the operation associated with this Call object. |
| * |
| * @param type QName of the return value type. |
| */ |
| public void setReturnType(QName type) { |
| if (operationSetManually) { |
| throw new RuntimeException( |
| Messages.getMessage("operationAlreadySet")); |
| } |
| |
| if (operation == null) |
| operation = new OperationDesc(); |
| |
| // In order to allow any Call to be re-used, Axis |
| // chooses to allow setReturnType to be changed when |
| // parmAndRetReq==false. This does not conflict with |
| // JSR 101 which indicates an exception MAY be thrown. |
| |
| //if (parmAndRetReq) { |
| operation.setReturnType(type); |
| TypeMapping tm = getTypeMapping(); |
| operation.setReturnClass(tm.getClassForQName(type)); |
| parmAndRetReq = true; |
| //} |
| //else { |
| //throw new JAXRPCException(Messages.getMessage("noParmAndRetReq")); |
| //} |
| } |
| |
| /** |
| * Sets the return type for a specific operation. |
| * |
| * @param xmlType - QName of the data type of the return value |
| * @param javaType - Java class of the return value |
| * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns |
| * false, then setReturnType MAY throw JAXRPCException...Axis allows |
| * modification without throwing the exception. |
| */ |
| public void setReturnType(QName xmlType, Class javaType) { |
| setReturnType(xmlType); |
| // Use specified type as the operation return |
| operation.setReturnClass(javaType); |
| } |
| |
| /** |
| * Set the return type as a header |
| */ |
| public void setReturnTypeAsHeader(QName xmlType) { |
| setReturnType(xmlType); |
| operation.setReturnHeader(true); |
| } // setReturnTypeAsHeader |
| |
| /** |
| * Set the return type as a header |
| */ |
| public void setReturnTypeAsHeader(QName xmlType, Class javaType) { |
| setReturnType(xmlType, javaType); |
| operation.setReturnHeader(true); |
| } // setReturnTypeAsHeader |
| |
| /** |
| * Returns the QName of the type of the return value of this Call - or null |
| * if not set. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @return the XMLType specified for this Call (or null). |
| */ |
| public QName getReturnType() { |
| if (operation != null) |
| return operation.getReturnType(); |
| |
| return null; |
| } |
| |
| /** |
| * Set the QName of the return element |
| * |
| * NOT part of JAX-RPC |
| */ |
| public void setReturnQName(QName qname) { |
| if (operationSetManually) { |
| throw new RuntimeException( |
| Messages.getMessage("operationAlreadySet")); |
| } |
| |
| if (operation == null) |
| operation = new OperationDesc(); |
| |
| operation.setReturnQName(qname); |
| } |
| /** |
| * Sets the desired return Java Class. This is a convenience method |
| * which will cause the Call to automatically convert return values |
| * into a desired class if possible. For instance, we return object |
| * arrays by default now for SOAP arrays - you could specify: |
| * |
| * setReturnClass(Vector.class) |
| * |
| * and you'd get a Vector back from invoke() instead of having to do |
| * the conversion yourself. |
| * |
| * Note: Not part of JAX-RPC specification. To be JAX-RPC compliant, |
| * use setReturnType(QName, Class). |
| * |
| * @param cls the desired return class. |
| */ |
| public void setReturnClass(Class cls) { |
| if (operationSetManually) { |
| throw new RuntimeException( |
| Messages.getMessage("operationAlreadySet")); |
| } |
| |
| if (operation == null) |
| operation = new OperationDesc(); |
| |
| operation.setReturnClass(cls); |
| TypeMapping tm = getTypeMapping(); |
| operation.setReturnType(tm.getTypeQName(cls)); |
| parmAndRetReq = true; |
| } |
| |
| /** |
| * Clears the list of parameters. |
| * @exception JAXRPCException - if isParameterAndReturnSpecRequired returns |
| * false, then removeAllParameters MAY throw JAXRPCException...Axis allows |
| * modification to the Call object without throwing an exception. |
| */ |
| public void removeAllParameters() { |
| //if (parmAndRetReq) { |
| operation = new OperationDesc(); |
| operationSetManually = false; |
| parmAndRetReq = true; |
| //} |
| //else { |
| //throw new JAXRPCException(Messages.getMessage("noParmAndRetReq")); |
| //} |
| } |
| |
| /** |
| * Returns the operation name associated with this Call object. |
| * |
| * @return String Name of the operation or null if not set. |
| */ |
| public QName getOperationName() { |
| return( operationName ); |
| } |
| |
| /** |
| * Sets the operation name associated with this Call object. This will |
| * not check the WSDL (if there is WSDL) to make sure that it's a valid |
| * operation name. |
| * |
| * @param opName Name of the operation. |
| */ |
| public void setOperationName(QName opName) { |
| operationName = opName ; |
| } |
| |
| /** |
| * This is a convenience method. If the user doesn't care about the QName |
| * of the operation, the user can call this method, which converts a String |
| * operation name to a QName. |
| */ |
| public void setOperationName(String opName) { |
| operationName = new QName(opName); |
| } |
| |
| /** |
| * Prefill as much info from the WSDL as it can. |
| * Right now it's SOAPAction, operation qname, parameter types |
| * and return type of the Web Service. |
| * |
| * This methods considers that port name and target endpoint address have |
| * already been set. This is useful when you want to use the same Call |
| * instance for several calls on the same Port |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param opName Operation(method) that's going to be invoked |
| * @throws JAXRPCException |
| */ |
| public void setOperation(String opName) { |
| if ( service == null ) { |
| throw new JAXRPCException( Messages.getMessage("noService04") ); |
| } |
| |
| // remove all settings concerning an operation |
| // leave portName and targetEndPoint as they are |
| this.setOperationName( opName ); |
| this.setEncodingStyle( null ); |
| this.setReturnType( null ); |
| this.removeAllParameters(); |
| |
| javax.wsdl.Service wsdlService = service.getWSDLService(); |
| // Nothing to do is the WSDL is not already set. |
| if(wsdlService == null) { |
| return; |
| } |
| |
| Port port = wsdlService.getPort( portName.getLocalPart() ); |
| if ( port == null ) { |
| throw new JAXRPCException( Messages.getMessage("noPort00", "" + |
| portName) ); |
| } |
| |
| Binding binding = port.getBinding(); |
| PortType portType = binding.getPortType(); |
| if ( portType == null ) { |
| throw new JAXRPCException( Messages.getMessage("noPortType00", "" + |
| portName) ); |
| } |
| this.setPortTypeName(portType.getQName()); |
| |
| List operations = portType.getOperations(); |
| if ( operations == null ) { |
| throw new JAXRPCException( Messages.getMessage("noOperation01", |
| opName) ); |
| } |
| |
| Operation op = null ; |
| for ( int i = 0 ; i < operations.size() ; i++, op=null ) { |
| op = (Operation) operations.get( i ); |
| if ( opName.equals( op.getName() ) ) { |
| break ; |
| } |
| } |
| if ( op == null ) { |
| throw new JAXRPCException( Messages.getMessage("noOperation01", |
| opName) ); |
| } |
| |
| // Get the SOAPAction |
| //////////////////////////////////////////////////////////////////// |
| List list = port.getExtensibilityElements(); |
| String opStyle = null; |
| BindingOperation bop = binding.getBindingOperation(opName, |
| null, null); |
| if ( bop == null ) { |
| throw new JAXRPCException( Messages.getMessage("noOperation02", |
| opName )); |
| } |
| list = bop.getExtensibilityElements(); |
| for ( int i = 0 ; list != null && i < list.size() ; i++ ) { |
| Object obj = list.get(i); |
| if ( obj instanceof SOAPOperation ) { |
| SOAPOperation sop = (SOAPOperation) obj ; |
| opStyle = ((SOAPOperation) obj).getStyle(); |
| String action = sop.getSoapActionURI(); |
| if ( action != null ) { |
| setUseSOAPAction(true); |
| setSOAPActionURI(action); |
| } |
| else { |
| setUseSOAPAction(false); |
| setSOAPActionURI(null); |
| } |
| break ; |
| } |
| } |
| |
| // Get the body's namespace URI and encoding style |
| //////////////////////////////////////////////////////////////////// |
| BindingInput bIn = bop.getBindingInput(); |
| if ( bIn != null ) { |
| list = bIn.getExtensibilityElements(); |
| for ( int i = 0 ; list != null && i < list.size() ; i++ ) { |
| Object obj = list.get(i); |
| if( obj instanceof MIMEMultipartRelated){ |
| MIMEMultipartRelated mpr=(MIMEMultipartRelated) obj; |
| Object part= null; |
| List l= mpr.getMIMEParts(); |
| for(int j=0; l!= null && j< l.size() && part== null; j++){ |
| MIMEPart mp = (MIMEPart)l.get(j); |
| List ll= mp.getExtensibilityElements(); |
| for(int k=0; ll != null && k < ll.size() && part == null; |
| k++){ |
| part= ll.get(k); |
| if ( !(part instanceof SOAPBody)) { |
| part = null; |
| } |
| } |
| } |
| if(null != part) { |
| obj= part; |
| } |
| } |
| |
| if ( obj instanceof SOAPBody ) { |
| SOAPBody sBody = (SOAPBody) obj ; |
| list = sBody.getEncodingStyles(); |
| if ( list != null && list.size() > 0 ) { |
| this.setEncodingStyle( (String) list.get(0) ); |
| } |
| String ns = sBody.getNamespaceURI(); |
| if (ns != null && !ns.equals("")) { |
| setOperationName( new QName( ns, opName ) ); |
| } |
| break ; |
| } |
| } |
| } |
| |
| Service service = this.getService(); |
| SymbolTable symbolTable = service.getWSDLParser().getSymbolTable(); |
| BindingEntry bEntry = symbolTable.getBindingEntry(binding.getQName()); |
| Parameters parameters = bEntry.getParameters(bop.getOperation()); |
| |
| // loop over paramters and set up in/out params |
| for (int j = 0; j < parameters.list.size(); ++j) { |
| Parameter p = (Parameter) parameters.list.get(j); |
| // Get the QName representing the parameter type |
| QName paramType = Utils.getXSIType(p); |
| |
| // checks whether p is an IN or OUT header |
| // and adds it as a header parameter else |
| // add it to the body |
| ParameterMode mode = modes[p.getMode()]; |
| if (p.isInHeader() || p.isOutHeader()) { |
| this.addParameterAsHeader(p.getQName(), paramType, |
| mode, mode); |
| } else { |
| this.addParameter(p.getQName(), paramType, mode); |
| } |
| } |
| |
| Map faultMap = bEntry.getFaults(); |
| // Get the list of faults for this operation |
| ArrayList faults = (ArrayList) faultMap.get(bop); |
| |
| // check for no faults |
| if (faults == null) { |
| return; |
| } |
| // For each fault, register its information |
| for (Iterator faultIt = faults.iterator(); faultIt.hasNext();) { |
| FaultInfo info = (FaultInfo) faultIt.next(); |
| QName qname = info.getQName(); |
| info.getMessage(); |
| |
| // if no parts in fault, skip it! |
| if (qname == null) { |
| continue; |
| } |
| |
| QName xmlType = info.getXMLType(); |
| Class clazz = getTypeMapping().getClassForQName(xmlType); |
| if (clazz != null) { |
| addFault(qname, clazz, xmlType, true); |
| } else { |
| //we cannot map from the info to a java class |
| //In Axis1.1 and before this was silently swallowed. Now we log it |
| |
| log.debug(Messages.getMessage("clientNoTypemapping", xmlType.toString())); |
| } |
| } |
| |
| // set output type |
| if (parameters.returnParam != null) { |
| // Get the QName for the return Type |
| QName returnType = Utils.getXSIType(parameters.returnParam); |
| QName returnQName = parameters.returnParam.getQName(); |
| |
| // Get the javaType |
| String javaType = null; |
| if (parameters.returnParam.getMIMEInfo() != null) { |
| javaType = "javax.activation.DataHandler"; |
| } |
| else { |
| javaType = parameters.returnParam.getType().getName(); |
| } |
| if (javaType == null) { |
| javaType = ""; |
| } |
| else { |
| javaType = javaType + ".class"; |
| } |
| this.setReturnType(returnType); |
| try { |
| Class clazz = ClassUtils.forName(javaType); |
| this.setReturnClass(clazz); |
| } catch (ClassNotFoundException swallowedException) { |
| //log that this lookup failed, |
| log.debug(Messages.getMessage("clientNoReturnClass", |
| javaType)); |
| } |
| this.setReturnQName(returnQName); |
| } |
| else { |
| this.setReturnType(org.apache.axis.encoding.XMLType.AXIS_VOID); |
| } |
| |
| boolean hasMIME = Utils.hasMIME(bEntry, bop); |
| Use use = bEntry.getInputBodyType(bop.getOperation()); |
| setOperationUse(use); |
| if (use == Use.LITERAL) { |
| // Turn off encoding |
| setEncodingStyle(null); |
| // turn off XSI types |
| setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE); |
| } |
| if (hasMIME || use == Use.LITERAL) { |
| // If it is literal, turn off multirefs. |
| // |
| // If there are any MIME types, turn off multirefs. |
| // I don't know enough about the guts to know why |
| // attachments don't work with multirefs, but they don't. |
| setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE); |
| } |
| |
| Style style = Style.getStyle(opStyle, bEntry.getBindingStyle()); |
| if (style == Style.DOCUMENT && symbolTable.isWrapped()) { |
| style = Style.WRAPPED; |
| } |
| setOperationStyle(style); |
| |
| // Operation name |
| if (style == Style.WRAPPED) { |
| // We need to make sure the operation name, which is what we |
| // wrap the elements in, matches the Qname of the parameter |
| // element. |
| Map partsMap = bop.getOperation().getInput().getMessage().getParts(); |
| Part p = (Part)partsMap.values().iterator().next(); |
| QName q = p.getElementName(); |
| setOperationName(q); |
| } else { |
| QName elementQName = |
| Utils.getOperationQName(bop, bEntry, symbolTable); |
| if (elementQName != null) { |
| setOperationName(elementQName); |
| } |
| } |
| |
| // Indicate that the parameters and return no longer |
| // need to be specified with addParameter calls. |
| parmAndRetReq = false; |
| return; |
| |
| } |
| |
| |
| /** |
| * prefill as much info from the WSDL as it can. |
| * Right now it's target URL, SOAPAction, Parameter types, |
| * and return type of the Web Service. |
| * |
| * If wsdl is not present, this function set port name and operation name |
| * and does not modify target endpoint address. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param portName PortName in the WSDL doc to search for |
| * @param opName Operation(method) that's going to be invoked |
| */ |
| public void setOperation(QName portName, String opName) { |
| setOperation(portName, new QName(opName)); |
| } |
| |
| |
| /** |
| * prefill as much info from the WSDL as it can. |
| * Right now it's target URL, SOAPAction, Parameter types, |
| * and return type of the Web Service. |
| * |
| * If wsdl is not present, this function set port name and operation name |
| * and does not modify target endpoint address. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param portName PortName in the WSDL doc to search for |
| * @param opName Operation(method) that's going to be invoked |
| */ |
| public void setOperation(QName portName, QName opName) { |
| if ( service == null ) |
| throw new JAXRPCException( Messages.getMessage("noService04") ); |
| |
| // Make sure we're making a fresh start. |
| this.setPortName( portName ); |
| this.setOperationName( opName ); |
| this.setReturnType( null ); |
| this.removeAllParameters(); |
| |
| javax.wsdl.Service wsdlService = service.getWSDLService(); |
| // Nothing to do is the WSDL is not already set. |
| if(wsdlService == null) { |
| return; |
| } |
| |
| // we reinitialize target endpoint only if we have wsdl |
| this.setTargetEndpointAddress( (URL) null ); |
| |
| Port port = wsdlService.getPort( portName.getLocalPart() ); |
| if ( port == null ) { |
| throw new JAXRPCException( Messages.getMessage("noPort00", "" + |
| portName) ); |
| } |
| |
| // Get the URL |
| //////////////////////////////////////////////////////////////////// |
| List list = port.getExtensibilityElements(); |
| for ( int i = 0 ; list != null && i < list.size() ; i++ ) { |
| Object obj = list.get(i); |
| if ( obj instanceof SOAPAddress ) { |
| try { |
| SOAPAddress addr = (SOAPAddress) obj ; |
| URL url = new URL(addr.getLocationURI()); |
| this.setTargetEndpointAddress(url); |
| } |
| catch(Exception exp) { |
| throw new JAXRPCException( |
| Messages.getMessage("cantSetURI00", "" + exp) ); |
| } |
| } |
| } |
| |
| setOperation(opName.getLocalPart()); |
| } |
| |
| /** |
| * Returns the fully qualified name of the port for this Call object |
| * (if there is one). |
| * |
| * @return QName Fully qualified name of the port (or null if not set) |
| */ |
| public QName getPortName() { |
| return( portName ); |
| } // getPortName |
| |
| /** |
| * Sets the port name of this Call object. This call will not set |
| * any additional fields, nor will it do any checking to verify that |
| * this port name is actually defined in the WSDL - for now anyway. |
| * |
| * @param portName Fully qualified name of the port |
| */ |
| public void setPortName(QName portName) { |
| this.portName = portName; |
| } // setPortName |
| |
| /** |
| * Returns the fully qualified name of the port type for this Call object |
| * (if there is one). |
| * |
| * @return QName Fully qualified name of the port type |
| */ |
| public QName getPortTypeName() { |
| return portTypeName == null ? new QName("") : portTypeName; |
| } |
| |
| /** |
| * Sets the port type name of this Call object. This call will not set |
| * any additional fields, nor will it do any checking to verify that |
| * this port type is actually defined in the WSDL - for now anyway. |
| * |
| * @param portType Fully qualified name of the portType |
| */ |
| public void setPortTypeName(QName portType) { |
| this.portTypeName = portType; |
| } |
| |
| /** |
| * Allow the user to set the default SOAP version. For SOAP 1.2, pass |
| * SOAPConstants.SOAP12_CONSTANTS. |
| * |
| * @param soapConstants the SOAPConstants object representing the correct |
| * version |
| */ |
| public void setSOAPVersion(SOAPConstants soapConstants) { |
| msgContext.setSOAPConstants(soapConstants); |
| } |
| |
| /** |
| * Invokes a specific operation using a synchronous request-response interaction mode. The invoke method takes |
| * as parameters the object values corresponding to these defined parameter types. Implementation of the invoke |
| * method must check whether the passed parameter values correspond to the number, order and types of parameters |
| * specified in the corresponding operation specification. |
| * |
| * @param operationName - Name of the operation to invoke |
| * @param params - Parameters for this invocation |
| * |
| * @return the value returned from the other end. |
| * |
| * @throws java.rmi.RemoteException - if there is any error in the remote method invocation or if the Call |
| * object is not configured properly. |
| */ |
| public Object invoke(QName operationName, Object[] params) |
| throws java.rmi.RemoteException { |
| QName origOpName = this.operationName; |
| this.operationName = operationName; |
| try { |
| return this.invoke(params); |
| } |
| catch (AxisFault af) { |
| this.operationName = origOpName; |
| if(af.detail != null && af.detail instanceof RemoteException) { |
| throw ((RemoteException)af.detail); |
| } |
| throw af; |
| } |
| catch (java.rmi.RemoteException re) { |
| this.operationName = origOpName; |
| throw re; |
| } |
| catch (RuntimeException re) { |
| this.operationName = origOpName; |
| throw re; |
| } |
| catch (Error e) { |
| this.operationName = origOpName; |
| throw e; |
| } |
| } // invoke |
| |
| /** |
| * Invokes the operation associated with this Call object using the |
| * passed in parameters as the arguments to the method. |
| * |
| * For Messaging (ie. non-RPC) the params argument should be an array |
| * of SOAPBodyElements. <b>All</b> of them need to be SOAPBodyElements, |
| * if any of them are not this method will default back to RPC. In the |
| * Messaging case the return value will be a vector of SOAPBodyElements. |
| * |
| * @param params Array of parameters to invoke the Web Service with |
| * @return Object Return value of the operation/method - or null |
| * @throws java.rmi.RemoteException if there's an error |
| */ |
| public Object invoke(Object[] params) throws java.rmi.RemoteException { |
| long t0=0, t1=0; |
| if( tlog.isDebugEnabled() ) { |
| t0=System.currentTimeMillis(); |
| } |
| /* First see if we're dealing with Messaging instead of RPC. */ |
| /* If ALL of the params are SOAPBodyElements then we're doing */ |
| /* Messaging, otherwise just fall through to normal RPC processing. */ |
| /********************************************************************/ |
| SOAPEnvelope env = null ; |
| int i ; |
| |
| for ( i = 0 ; params != null && i < params.length ; i++ ) |
| if ( !(params[i] instanceof SOAPBodyElement) ) break ; |
| |
| if ( params != null && params.length > 0 && i == params.length ) { |
| /* ok, we're doing Messaging, so build up the message */ |
| /******************************************************/ |
| isMsg = true ; |
| env = new SOAPEnvelope(msgContext.getSOAPConstants(), |
| msgContext.getSchemaVersion()); |
| |
| for (i = 0; i < params.length; i++) { |
| env.addBodyElement((SOAPBodyElement) params[i]); |
| } |
| |
| Message msg = new Message( env ); |
| setRequestMessage(msg); |
| |
| invoke(); |
| |
| msg = msgContext.getResponseMessage(); |
| if (msg == null) { |
| if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) { |
| throw new AxisFault(Messages.getMessage("nullResponse00")); |
| } else { |
| return null; |
| } |
| } |
| |
| env = msg.getSOAPEnvelope(); |
| return( env.getBodyElements() ); |
| } |
| |
| |
| if ( operationName == null ) { |
| throw new AxisFault( Messages.getMessage("noOperation00") ); |
| } |
| try { |
| Object res=this.invoke(operationName.getNamespaceURI(), |
| operationName.getLocalPart(), params); |
| if( tlog.isDebugEnabled() ) { |
| t1=System.currentTimeMillis(); |
| tlog.debug("axis.Call.invoke: " + (t1-t0) + " " + operationName); |
| } |
| return res; |
| } |
| catch( AxisFault af) { |
| if(af.detail != null && af.detail instanceof RemoteException) { |
| throw ((RemoteException)af.detail); |
| } |
| throw af; |
| } |
| catch( Exception exp ) { |
| entLog.debug(Messages.getMessage("toAxisFault00"), exp); |
| throw AxisFault.makeFault(exp); |
| } |
| } |
| |
| /** |
| * Invokes the operation associated with this Call object using the passed |
| * in parameters as the arguments to the method. This will return |
| * immediately rather than waiting for the server to complete its |
| * processing. |
| * |
| * NOTE: the return immediately part isn't implemented yet |
| * |
| * @param params Array of parameters to invoke the Web Service with |
| * @throws JAXRPCException is there's an error |
| */ |
| public void invokeOneWay(Object[] params) { |
| try { |
| invokeOneWay = true; |
| invoke( params ); |
| } catch( Exception exp ) { |
| throw new JAXRPCException( exp.toString() ); |
| } finally { |
| invokeOneWay = false; |
| } |
| } |
| |
| /************************************************************************/ |
| /* End of core JAX-RPC stuff */ |
| /************************************************************************/ |
| |
| /** |
| * Invoke the service with a custom Message. |
| * This method simplifies invoke(SOAPEnvelope). |
| * <p> |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param msg a Message to send |
| * @throws AxisFault if there is any failure |
| */ |
| public SOAPEnvelope invoke(Message msg) throws AxisFault { |
| try { |
| setRequestMessage( msg ); |
| invoke(); |
| msg = msgContext.getResponseMessage(); |
| if (msg == null) { |
| if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) { |
| throw new AxisFault(Messages.getMessage("nullResponse00")); |
| } else { |
| return null; |
| } |
| } |
| SOAPEnvelope res = null; |
| res = msg.getSOAPEnvelope(); |
| return res; |
| } |
| catch (Exception exp) { |
| if (exp instanceof AxisFault) { |
| throw (AxisFault) exp ; |
| } |
| entLog.debug(Messages.getMessage("toAxisFault00"), exp); |
| throw new AxisFault( |
| Messages.getMessage("errorInvoking00", "\n" + exp)); |
| } |
| } |
| |
| /** |
| * Invoke the service with a custom SOAPEnvelope. |
| * <p> |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param env a SOAPEnvelope to send |
| * @throws AxisFault if there is any failure |
| */ |
| public SOAPEnvelope invoke(SOAPEnvelope env) throws AxisFault { |
| try { |
| Message msg = new Message( env ); |
| if (getProperty(CHARACTER_SET_ENCODING) != null) { |
| msg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, getProperty(CHARACTER_SET_ENCODING)); |
| } else if (msgContext.getProperty(CHARACTER_SET_ENCODING) != null) { |
| msg.setProperty(CHARACTER_SET_ENCODING, msgContext.getProperty(CHARACTER_SET_ENCODING)); |
| } |
| setRequestMessage( msg ); |
| invoke(); |
| msg = msgContext.getResponseMessage(); |
| if (msg == null) { |
| if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) { |
| throw new AxisFault(Messages.getMessage("nullResponse00")); |
| } else { |
| return null; |
| } |
| } |
| return( msg.getSOAPEnvelope() ); |
| } |
| catch( Exception exp ) { |
| if ( exp instanceof AxisFault ) { |
| throw (AxisFault) exp ; |
| } |
| |
| entLog.debug(Messages.getMessage("toAxisFault00"), exp); |
| throw AxisFault.makeFault(exp); |
| } |
| } |
| |
| |
| /** Register a Transport that should be used for URLs of the specified |
| * protocol. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param protocol the URL protocol (i.e. "tcp" for "tcp://" urls) |
| * @param transportClass the class of a Transport type which will be used |
| * for matching URLs. |
| */ |
| public static void setTransportForProtocol(String protocol, |
| Class transportClass) { |
| if (Transport.class.isAssignableFrom(transportClass)) { |
| transports.put(protocol, transportClass); |
| } |
| else { |
| throw new InternalException(transportClass.toString()); |
| } |
| } |
| |
| /** |
| * Set up the default transport URL mappings. |
| * |
| * This must be called BEFORE doing non-standard URL parsing (i.e. if you |
| * want the system to accept a "local:" URL). This is why the Options class |
| * calls it before parsing the command-line URL argument. |
| * |
| * Note: Not part of JAX-RPC specification. |
| */ |
| public static synchronized void initialize() { |
| addTransportPackage("org.apache.axis.transport"); |
| |
| setTransportForProtocol("java", |
| org.apache.axis.transport.java.JavaTransport.class); |
| setTransportForProtocol("local", |
| org.apache.axis.transport.local.LocalTransport.class); |
| setTransportForProtocol("http", HTTPTransport.class); |
| setTransportForProtocol("https", HTTPTransport.class); |
| } |
| |
| /** |
| * Cache of transport packages we've already added to the system |
| * property. |
| */ |
| private static ArrayList transportPackages = null; |
| |
| /** Add a package to the system protocol handler search path. This |
| * enables users to create their own URLStreamHandler classes, and thus |
| * allow custom protocols to be used in Axis (typically on the client |
| * command line). |
| * |
| * For instance, if you add "samples.transport" to the packages property, |
| * and have a class samples.transport.tcp.Handler, the system will be able |
| * to parse URLs of the form "tcp://host:port..." |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param packageName the package in which to search for protocol names. |
| */ |
| public static synchronized void addTransportPackage(String packageName) { |
| if (transportPackages == null) { |
| transportPackages = new ArrayList(); |
| String currentPackages = |
| AxisProperties.getProperty(TRANSPORT_PROPERTY); |
| if (currentPackages != null) { |
| StringTokenizer tok = new StringTokenizer(currentPackages, |
| "|"); |
| while (tok.hasMoreTokens()) { |
| transportPackages.add(tok.nextToken()); |
| } |
| } |
| } |
| |
| if (transportPackages.contains(packageName)) { |
| return; |
| } |
| |
| transportPackages.add(packageName); |
| |
| StringBuffer currentPackages = new StringBuffer(); |
| for (Iterator i = transportPackages.iterator(); i.hasNext();) { |
| String thisPackage = (String) i.next(); |
| currentPackages.append(thisPackage); |
| currentPackages.append('|'); |
| } |
| |
| final String transportProperty = currentPackages.toString(); |
| java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() { |
| public Object run() { |
| try { |
| System.setProperty(TRANSPORT_PROPERTY, transportProperty); |
| } catch (SecurityException se){ |
| } |
| return null; |
| } |
| }); |
| } |
| |
| /** |
| * Convert the list of objects into RPCParam's based on the paramNames, |
| * paramXMLTypes and paramModes variables. If those aren't set then just |
| * return what was passed in. |
| * |
| * @param params Array of parameters to pass into the operation/method |
| * @return Object[] Array of parameters to pass to invoke() |
| */ |
| private Object[] getParamList(Object[] params) { |
| int numParams = 0 ; |
| |
| // If we never set-up any names... then just return what was passed in |
| ////////////////////////////////////////////////////////////////////// |
| if (log.isDebugEnabled()) { |
| log.debug( "operation=" + operation); |
| if (operation != null) { |
| log.debug("operation.getNumParams()=" + |
| operation.getNumParams()); |
| } |
| } |
| if ( operation == null || operation.getNumParams() == 0 ) { |
| return( params ); |
| } |
| |
| // Count the number of IN and INOUT params, this needs to match the |
| // number of params passed in - if not throw an error |
| ///////////////////////////////////////////////////////////////////// |
| numParams = operation.getNumInParams(); |
| |
| if ( params == null || numParams != params.length ) { |
| throw new JAXRPCException( |
| Messages.getMessage( |
| "parmMismatch00", |
| (params == null) ? "no params" : "" + params.length, |
| "" + numParams |
| ) |
| ); |
| } |
| |
| log.debug( "getParamList number of params: " + params.length); |
| |
| // All ok - so now produce an array of RPCParams |
| ////////////////////////////////////////////////// |
| Vector result = new Vector(); |
| int j = 0 ; |
| ArrayList parameters = operation.getParameters(); |
| |
| for (int i = 0; i < parameters.size(); i++) { |
| ParameterDesc param = (ParameterDesc)parameters.get(i); |
| if (param.getMode() != ParameterDesc.OUT) { |
| QName paramQName = param.getQName(); |
| |
| // Create an RPCParam if param isn't already an RPCParam. |
| RPCParam rpcParam = null; |
| Object p = params[j++]; |
| if(p instanceof RPCParam) { |
| rpcParam = (RPCParam)p; |
| } else { |
| rpcParam = new RPCParam(paramQName.getNamespaceURI(), |
| paramQName.getLocalPart(), |
| p); |
| } |
| // Attach the ParameterDescription to the RPCParam |
| // so that the serializer can use the (javaType, xmlType) |
| // information. |
| rpcParam.setParamDesc(param); |
| |
| // Add the param to the header or vector depending |
| // on whether it belongs in the header or body. |
| if (param.isInHeader()) { |
| addHeader(new RPCHeaderParam(rpcParam)); |
| } else { |
| result.add(rpcParam); |
| } |
| } |
| } |
| return( result.toArray() ); |
| } |
| |
| /** |
| * Set the Transport |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param trans the Transport object we'll use to set up |
| * MessageContext properties. |
| */ |
| public void setTransport(Transport trans) { |
| transport = trans; |
| if (log.isDebugEnabled()) |
| log.debug(Messages.getMessage("transport00", "" + transport)); |
| } |
| |
| /** Get the Transport registered for the given protocol. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param protocol a protocol such as "http" or "local" which may |
| * have a Transport object associated with it. |
| * @return the Transport registered for this protocol, or null if none. |
| */ |
| public Transport getTransportForProtocol(String protocol) |
| { |
| Class transportClass = (Class)transports.get(protocol); |
| Transport ret = null; |
| if (transportClass != null) { |
| try { |
| ret = (Transport)transportClass.newInstance(); |
| } catch (InstantiationException e) { |
| } catch (IllegalAccessException e) { |
| } |
| } |
| return ret; |
| } |
| |
| /** |
| * Directly set the request message in our MessageContext. |
| * |
| * This allows custom message creation. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param msg the new request message. |
| * @throws RuntimeException containing the text of an AxisFault, if any |
| * AxisFault was thrown |
| */ |
| public void setRequestMessage(Message msg) { |
| String attachformat= (String)getProperty( |
| ATTACHMENT_ENCAPSULATION_FORMAT); |
| |
| if(null != attachformat) { |
| Attachments attachments=msg.getAttachmentsImpl(); |
| if(null != attachments) { |
| if( ATTACHMENT_ENCAPSULATION_FORMAT_MIME.equals(attachformat)) { |
| attachments.setSendType(Attachments.SEND_TYPE_MIME); |
| } else if ( ATTACHMENT_ENCAPSULATION_FORMAT_MTOM.equals(attachformat)) { |
| attachments.setSendType(Attachments.SEND_TYPE_MTOM); |
| } else if ( ATTACHMENT_ENCAPSULATION_FORMAT_DIME.equals(attachformat)) { |
| attachments.setSendType(Attachments.SEND_TYPE_DIME); |
| } |
| } |
| } |
| |
| if(null != attachmentParts && !attachmentParts.isEmpty()){ |
| try{ |
| Attachments attachments= msg.getAttachmentsImpl(); |
| if(null == attachments) { |
| throw new RuntimeException( |
| Messages.getMessage("noAttachments")); |
| } |
| |
| attachments.setAttachmentParts(attachmentParts); |
| }catch(AxisFault ex){ |
| log.info(Messages.getMessage("axisFault00"), ex); |
| throw new RuntimeException(ex.getMessage()); |
| } |
| } |
| |
| msgContext.setRequestMessage(msg); |
| attachmentParts.clear(); |
| } |
| |
| /** |
| * Directly get the response message in our MessageContext. |
| * |
| * Shortcut for having to go thru the msgContext |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @return the response Message object in the msgContext |
| */ |
| public Message getResponseMessage() { |
| return msgContext.getResponseMessage(); |
| } |
| |
| /** |
| * Obtain a reference to our MessageContext. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @return the MessageContext. |
| */ |
| public MessageContext getMessageContext () { |
| return msgContext; |
| } |
| |
| /** |
| * Add a header which should be inserted into each outgoing message |
| * we generate. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param header a SOAPHeaderElement to be inserted into messages |
| */ |
| public void addHeader(SOAPHeaderElement header) |
| { |
| if (myHeaders == null) { |
| myHeaders = new Vector(); |
| } |
| myHeaders.add(header); |
| } |
| |
| /** |
| * Clear the list of headers which we insert into each message |
| * |
| * Note: Not part of JAX-RPC specification. |
| */ |
| public void clearHeaders() |
| { |
| myHeaders = null; |
| } |
| |
| public TypeMapping getTypeMapping() |
| { |
| // Get the TypeMappingRegistry |
| TypeMappingRegistry tmr = msgContext.getTypeMappingRegistry(); |
| |
| // If a TypeMapping is not available, add one. |
| return tmr.getOrMakeTypeMapping(getEncodingStyle()); |
| } |
| |
| /** |
| * Register type mapping information for serialization/deserialization |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param javaType is the Java class of the data type. |
| * @param xmlType the xsi:type QName of the associated XML type. |
| * @param sf/df are the factories (or the Class objects of the factory). |
| */ |
| public void registerTypeMapping(Class javaType, QName xmlType, |
| SerializerFactory sf, |
| DeserializerFactory df) { |
| registerTypeMapping(javaType, xmlType, sf, df, true); |
| } |
| |
| /** |
| * Register type mapping information for serialization/deserialization |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param javaType is the Java class of the data type. |
| * @param xmlType the xsi:type QName of the associated XML type. |
| * @param sf/df are the factories (or the Class objects of the factory). |
| * @param force Indicates whether to add the information if already registered. |
| */ |
| public void registerTypeMapping(Class javaType, QName xmlType, |
| SerializerFactory sf, |
| DeserializerFactory df, |
| boolean force) { |
| TypeMapping tm = getTypeMapping(); |
| if (!force && tm.isRegistered(javaType, xmlType)) { |
| return; |
| } |
| |
| // Register the information |
| tm.register(javaType, xmlType, sf, df); |
| } |
| |
| /** |
| * register this type matting |
| * @param javaType |
| * @param xmlType |
| * @param sfClass |
| * @param dfClass |
| */ |
| public void registerTypeMapping(Class javaType, QName xmlType, |
| Class sfClass, Class dfClass) { |
| registerTypeMapping(javaType, xmlType, sfClass, dfClass, true); |
| } |
| |
| /** |
| * register a type. This only takes place if either the serializer or |
| * deserializer factory could be created. |
| * @param javaType java type to handle |
| * @param xmlType XML mapping |
| * @param sfClass class of serializer factory |
| * @param dfClass class of deserializer factory |
| * @param force |
| */ |
| public void registerTypeMapping(Class javaType, |
| QName xmlType, |
| Class sfClass, |
| Class dfClass, |
| boolean force) { |
| // Instantiate the factory using introspection. |
| SerializerFactory sf = |
| BaseSerializerFactory.createFactory(sfClass, javaType, xmlType); |
| DeserializerFactory df = |
| BaseDeserializerFactory.createFactory(dfClass, |
| javaType, |
| xmlType); |
| if (sf != null || df != null) { |
| registerTypeMapping(javaType, xmlType, sf, df, force); |
| } |
| } |
| |
| /************************************************ |
| * Invocation |
| */ |
| |
| /** Invoke an RPC service with a method name and arguments. |
| * |
| * This will call the service, serializing all the arguments, and |
| * then deserialize the return value. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param namespace the desired namespace URI of the method element |
| * @param method the method name |
| * @param args an array of Objects representing the arguments to the |
| * invoked method. If any of these objects are RPCParams, |
| * Axis will use the embedded name of the RPCParam as the |
| * name of the parameter. Otherwise, we will serialize |
| * each argument as an XML element called "arg<n>". |
| * @return a deserialized Java Object containing the return value |
| * @exception AxisFault |
| */ |
| public Object invoke(String namespace, String method, Object[] args) |
| throws AxisFault { |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Enter: Call::invoke(ns, meth, args)"); |
| } |
| |
| /** |
| * Since JAX-RPC requires us to specify all or nothing, if setReturnType |
| * was called (returnType != null) and we have args but addParameter |
| * wasn't called (paramXMLTypes == null), then toss a fault. |
| */ |
| if (getReturnType() != null && args != null && args.length != 0 |
| && operation.getNumParams() == 0) { |
| throw new AxisFault(Messages.getMessage("mustSpecifyParms")); |
| } |
| |
| RPCElement body = new RPCElement(namespace, method, getParamList(args)); |
| |
| Object ret = invoke( body ); |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Exit: Call::invoke(ns, meth, args)"); |
| } |
| |
| return ret; |
| } |
| |
| /** Convenience method to invoke a method with a default (empty) |
| * namespace. Calls invoke() above. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param method the method name |
| * @param args an array of Objects representing the arguments to the |
| * invoked method. If any of these objects are RPCParams, |
| * Axis will use the embedded name of the RPCParam as the |
| * name of the parameter. Otherwise, we will serialize |
| * each argument as an XML element called "arg<n>". |
| * @return a deserialized Java Object containing the return value |
| * @exception AxisFault |
| */ |
| public Object invoke( String method, Object [] args ) throws AxisFault |
| { |
| return invoke("", method, args); |
| } |
| |
| /** Invoke an RPC service with a pre-constructed RPCElement. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param body an RPCElement containing all the information about |
| * this call. |
| * @return a deserialized Java Object containing the return value |
| * @exception AxisFault |
| */ |
| public Object invoke( RPCElement body ) throws AxisFault { |
| if (log.isDebugEnabled()) { |
| log.debug("Enter: Call::invoke(RPCElement)"); |
| } |
| |
| /** |
| * Since JAX-RPC requires us to specify a return type if we've set |
| * parameter types, check for this case right now and toss a fault |
| * if things don't look right. |
| */ |
| if (!invokeOneWay && operation != null && |
| operation.getNumParams() > 0 && getReturnType() == null) { |
| // TCK: |
| // Issue an error if the return type was not set, but continue processing. |
| //throw new AxisFault(Messages.getMessage("mustSpecifyReturnType")); |
| log.error(Messages.getMessage("mustSpecifyReturnType")); |
| } |
| |
| SOAPEnvelope reqEnv = |
| new SOAPEnvelope(msgContext.getSOAPConstants(), |
| msgContext.getSchemaVersion()); |
| SOAPEnvelope resEnv = null ; |
| Message reqMsg = new Message( reqEnv ); |
| Message resMsg = null ; |
| Vector resArgs = null ; |
| Object result = null ; |
| |
| // Clear the output params |
| outParams = new HashMap(); |
| outParamsList = new ArrayList(); |
| |
| // Set both the envelope and the RPCElement encoding styles |
| try { |
| body.setEncodingStyle(getEncodingStyle()); |
| |
| setRequestMessage(reqMsg); |
| |
| reqEnv.addBodyElement(body); |
| reqEnv.setMessageType(Message.REQUEST); |
| |
| invoke(); |
| } catch (Exception e) { |
| entLog.debug(Messages.getMessage("toAxisFault00"), e); |
| throw AxisFault.makeFault(e); |
| } |
| |
| resMsg = msgContext.getResponseMessage(); |
| |
| if (resMsg == null) { |
| if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) { |
| throw new AxisFault(Messages.getMessage("nullResponse00")); |
| } else { |
| return null; |
| } |
| } |
| |
| resEnv = resMsg.getSOAPEnvelope(); |
| SOAPBodyElement bodyEl = resEnv.getFirstBody(); |
| if (bodyEl == null) { |
| return null; |
| } |
| |
| if (bodyEl instanceof RPCElement) { |
| try { |
| resArgs = ((RPCElement) bodyEl).getParams(); |
| } catch (Exception e) { |
| log.error(Messages.getMessage("exception00"), e); |
| throw AxisFault.makeFault(e); |
| } |
| |
| if (resArgs != null && resArgs.size() > 0) { |
| |
| // If there is no return, then we start at index 0 to create the outParams Map. |
| // If there IS a return, then we start with 1. |
| int outParamStart = 0; |
| |
| // If we have resArgs and the returnType is specified, then the first |
| // resArgs is the return. If we have resArgs and neither returnType |
| // nor paramXMLTypes are specified, then we assume that the caller is |
| // following the non-JAX-RPC AXIS shortcut of not having to specify |
| // the return, in which case we again assume the first resArgs is |
| // the return. |
| // NOTE 1: the non-JAX-RPC AXIS shortcut allows a potential error |
| // to escape notice. If the caller IS NOT following the non-JAX-RPC |
| // shortcut but instead intentionally leaves returnType and params |
| // null (ie., a method that takes no parameters and returns nothing) |
| // then, if we DO receive something it should be an error, but this |
| // code passes it through. The ideal solution here is to require |
| // this caller to set the returnType to void, but there's no void |
| // type in XML. |
| // NOTE 2: we should probably verify that the resArgs element |
| // types match the expected returnType and paramXMLTypes, but I'm not |
| // sure how to do that since the resArgs value is a Java Object |
| // and the returnType and paramXMLTypes are QNames. |
| |
| // GD 03/15/02 : We're now checking for invalid metadata |
| // config at the top of this method, so don't need to do it |
| // here. Check for void return, though. |
| |
| boolean findReturnParam = false; |
| QName returnParamQName = null; |
| if (operation != null) { |
| returnParamQName = operation.getReturnQName(); |
| } |
| |
| if (!XMLType.AXIS_VOID.equals(getReturnType())) { |
| if (returnParamQName == null) { |
| // Assume the first param is the return |
| RPCParam param = (RPCParam)resArgs.get(0); |
| result = param.getObjectValue(); |
| outParamStart = 1; |
| } else { |
| // If the QName of the return value was given to us, look |
| // through the result arguments to find the right name |
| findReturnParam = true; |
| } |
| } |
| |
| // The following loop looks at the resargs and |
| // converts the value to the appropriate return/out parameter |
| // value. If the return value is found, is value is |
| // placed in result. The remaining resargs are |
| // placed in the outParams list (note that if a resArg |
| // is found that does not match a operation parameter qname, |
| // it is still placed in the outParms list). |
| for (int i = outParamStart; i < resArgs.size(); i++) { |
| RPCParam param = (RPCParam) resArgs.get(i); |
| |
| Class javaType = getJavaTypeForQName(param.getQName()); |
| Object value = param.getObjectValue(); |
| |
| // Convert type if needed |
| if (javaType != null && value != null && |
| !javaType.isAssignableFrom(value.getClass())) { |
| value = JavaUtils.convert(value, javaType); |
| } |
| |
| // Check if this parameter is our return |
| // otherwise just add it to our outputs |
| if (findReturnParam && |
| returnParamQName.equals(param.getQName())) { |
| // found it! |
| result = value; |
| findReturnParam = false; |
| } else { |
| outParams.put(param.getQName(), value); |
| outParamsList.add(value); |
| } |
| } |
| |
| // added by scheu: |
| // If the return param is still not found, that means |
| // the returned value did not have the expected qname. |
| // The soap specification indicates that this should be |
| // accepted (and we also fail interop tests if we are strict here). |
| // Look through the outParms and find one that |
| // does not match one of the operation parameters. |
| if (findReturnParam) { |
| Iterator it = outParams.keySet().iterator(); |
| while (findReturnParam && it.hasNext()) { |
| QName qname = (QName) it.next(); |
| ParameterDesc paramDesc = |
| operation.getOutputParamByQName(qname); |
| if (paramDesc == null) { |
| // Doesn't match a paramter, so use this for the return |
| findReturnParam = false; |
| result = outParams.remove(qname); |
| } |
| } |
| } |
| |
| // If we were looking for a particular QName for the return and |
| // still didn't find it, throw an exception |
| if (findReturnParam) { |
| String returnParamName = returnParamQName.toString(); |
| throw new AxisFault(Messages.getMessage("noReturnParam", |
| returnParamName)); |
| } |
| } |
| } else { |
| // This is a SOAPBodyElement, try to treat it like a return value |
| try { |
| result = bodyEl.getValueAsType(getReturnType()); |
| } catch (Exception e) { |
| // just return the SOAPElement |
| result = bodyEl; |
| } |
| |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Exit: Call::invoke(RPCElement)"); |
| } |
| |
| // Convert type if needed |
| if (operation != null && operation.getReturnClass() != null) { |
| result = JavaUtils.convert(result, operation.getReturnClass()); |
| } |
| |
| return( result ); |
| } |
| |
| /** |
| * Get the javaType for a given parameter. |
| * |
| * @param name the QName of the parameter |
| * @return the class associated with that parameter |
| */ |
| private Class getJavaTypeForQName(QName name) { |
| if (operation == null) { |
| return null; |
| } |
| ParameterDesc param = operation.getOutputParamByQName(name); |
| return param == null ? null : param.getJavaType(); |
| } |
| |
| /** |
| * Set engine option. |
| * |
| * Note: Not part of JAX-RPC specification. |
| */ |
| public void setOption(String name, Object value) { |
| service.getEngine().setOption(name, value); |
| } |
| |
| /** |
| * Invoke this Call with its established MessageContext |
| * (perhaps because you called this.setRequestMessage()) |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @exception AxisFault |
| */ |
| public void invoke() throws AxisFault { |
| if (log.isDebugEnabled()) { |
| log.debug("Enter: Call::invoke()"); |
| } |
| |
| isNeverInvoked = false; |
| |
| Message reqMsg = null ; |
| SOAPEnvelope reqEnv = null ; |
| |
| msgContext.reset(); |
| msgContext.setResponseMessage(null); |
| msgContext.setProperty( MessageContext.CALL, this ); |
| msgContext.setProperty( WSDL_SERVICE, service ); |
| msgContext.setProperty( WSDL_PORT_NAME, getPortName() ); |
| if ( isMsg ) { |
| msgContext.setProperty( MessageContext.IS_MSG, "true" ); |
| } |
| |
| if (username != null) { |
| msgContext.setUsername(username); |
| } |
| if (password != null) { |
| msgContext.setPassword(password); |
| } |
| msgContext.setMaintainSession(maintainSession); |
| |
| if (operation != null) { |
| msgContext.setOperation(operation); |
| operation.setStyle(getOperationStyle()); |
| operation.setUse(getOperationUse()); |
| } |
| |
| if (useSOAPAction) { |
| msgContext.setUseSOAPAction(true); |
| } |
| if (SOAPActionURI != null) { |
| msgContext.setSOAPActionURI(SOAPActionURI); |
| } else { |
| msgContext.setSOAPActionURI(null); |
| } |
| if (timeout != null) { |
| msgContext.setTimeout(timeout.intValue()); |
| } |
| msgContext.setHighFidelity(!useStreaming); |
| |
| // Determine client target service |
| if (myService != null) { |
| // If we have a SOAPService kicking around, use that directly |
| msgContext.setService(myService); |
| } else { |
| if (portName != null) { |
| // No explicit service. If we have a target service name, |
| // try that. |
| msgContext.setTargetService(portName.getLocalPart()); |
| } else { |
| // No direct config, so try the namespace of the first body. |
| reqMsg = msgContext.getRequestMessage(); |
| |
| if (reqMsg != null && !((SOAPPart)reqMsg.getSOAPPart()).isBodyStream()) { |
| reqEnv = reqMsg.getSOAPEnvelope(); |
| |
| SOAPBodyElement body = reqEnv.getFirstBody(); |
| |
| if (body != null) { |
| if ( body.getNamespaceURI() == null ) { |
| throw new AxisFault("Call.invoke", |
| Messages.getMessage("cantInvoke00", body.getName()), |
| null, null); |
| } else { |
| msgContext.setTargetService(body.getNamespaceURI()); |
| } |
| } |
| } |
| } |
| } |
| if (log.isDebugEnabled()) { |
| log.debug(Messages.getMessage("targetService", |
| msgContext.getTargetService())); |
| } |
| |
| Message requestMessage = msgContext.getRequestMessage(); |
| if (requestMessage != null) { |
| try { |
| msgContext.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, requestMessage.getProperty(SOAPMessage.CHARACTER_SET_ENCODING)); |
| } catch (SOAPException e) { |
| } |
| |
| if(myHeaders != null) { |
| reqEnv = requestMessage.getSOAPEnvelope(); |
| |
| // If we have headers to insert, do so now. |
| for (int i = 0 ; myHeaders != null && i < myHeaders.size() ; i++ ) { |
| reqEnv.addHeader((SOAPHeaderElement)myHeaders.get(i)); |
| } |
| } |
| } |
| |
| // set up transport if there is one |
| if (transport != null) { |
| transport.setupMessageContext(msgContext, this, service.getEngine()); |
| } |
| else { |
| msgContext.setTransportName( transportName ); |
| } |
| |
| SOAPService svc = msgContext.getService(); |
| if (svc != null) { |
| svc.setPropertyParent(myProperties); |
| } else { |
| msgContext.setPropertyParent(myProperties); |
| } |
| |
| // For debugging - print request message |
| if (log.isDebugEnabled()) { |
| StringWriter writer = new StringWriter(); |
| try { |
| SerializationContext ctx = new SerializationContext(writer, |
| msgContext); |
| requestMessage.getSOAPEnvelope().output(ctx); |
| writer.close(); |
| } catch (Exception e) { |
| throw AxisFault.makeFault(e); |
| } finally { |
| log.debug(writer.getBuffer().toString()); |
| } |
| } |
| |
| if(!invokeOneWay) { |
| invokeEngine(msgContext); |
| } else { |
| invokeEngineOneWay(msgContext); |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Exit: Call::invoke()"); |
| } |
| } |
| |
| /** |
| * Invoke the message on the current engine and do not wait for a response. |
| * |
| * @param msgContext the <code>MessageContext</code> to use |
| * @throws AxisFault if the invocation raised a fault |
| */ |
| private void invokeEngine(MessageContext msgContext) throws AxisFault { |
| service.getEngine().invoke( msgContext ); |
| |
| if (transport != null) { |
| transport.processReturnedMessageContext(msgContext); |
| } |
| |
| Message resMsg = msgContext.getResponseMessage(); |
| |
| if (resMsg == null) { |
| if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) { |
| throw new AxisFault(Messages.getMessage("nullResponse00")); |
| } else { |
| return; |
| } |
| } |
| |
| /** This must happen before deserialization... |
| */ |
| resMsg.setMessageType(Message.RESPONSE); |
| |
| SOAPEnvelope resEnv = resMsg.getSOAPEnvelope(); |
| |
| SOAPBodyElement respBody = resEnv.getFirstBody(); |
| if (respBody instanceof SOAPFault) { |
| //we got a fault |
| if(operation == null || |
| operation.getReturnClass() == null || |
| operation.getReturnClass() != |
| javax.xml.soap.SOAPMessage.class) { |
| //unless we don't care about the return value or we want |
| //a raw message back |
| //get the fault from the body and throw it |
| throw ((SOAPFault)respBody).getFault(); |
| } |
| } |
| } |
| |
| /** |
| * Implement async invocation by running the request in a new thread |
| * @param msgContext |
| */ |
| private void invokeEngineOneWay(final MessageContext msgContext) { |
| //TODO: this is not a good way to do stuff, as it has no error reporting facility |
| //create a new class |
| Runnable runnable = new Runnable(){ |
| public void run() { |
| msgContext.setProperty(Call.ONE_WAY, Boolean.TRUE); |
| try { |
| service.getEngine().invoke( msgContext ); |
| } catch (AxisFault af){ |
| //TODO: handle errors properly |
| log.debug(Messages.getMessage("exceptionPrinting"), af); |
| } |
| msgContext.removeProperty(Call.ONE_WAY); |
| } |
| }; |
| //create a thread to run it |
| Thread thread = new Thread(runnable); |
| //run it |
| thread.start(); |
| } |
| |
| /** |
| * Get the output parameters (if any) from the last invocation. |
| * |
| * This allows named access - if you need sequential access, use |
| * getOutputValues(). |
| * |
| * @return a Map containing the output parameter values, indexed by QName |
| */ |
| public Map getOutputParams() |
| { |
| if (isNeverInvoked) { |
| throw new JAXRPCException( |
| Messages.getMessage("outputParamsUnavailable")); |
| } |
| return this.outParams; |
| } |
| |
| /** |
| * Returns a List values for the output parameters of the last |
| * invoked operation. |
| * |
| * @return Values for the output parameters. An empty List is |
| * returned if there are no output values. |
| * |
| * @throws JAXRPCException - If this method is invoked for a |
| * one-way operation or is invoked |
| * before any invoke method has been called. |
| */ |
| public List getOutputValues() { |
| if (isNeverInvoked) { |
| throw new JAXRPCException( |
| Messages.getMessage("outputParamsUnavailable")); |
| } |
| return outParamsList; |
| } |
| |
| /** |
| * Get the Service object associated with this Call object. |
| * |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @return Service the Service object this Call object is associated with |
| */ |
| public Service getService() |
| { |
| return this.service; |
| } |
| |
| /** |
| * |
| * Set the service so that it defers missing property gets to the |
| * Call. So when client-side Handlers get at the MessageContext, |
| * the property scoping will be MC -> SOAPService -> Call |
| */ |
| public void setSOAPService(SOAPService service) |
| { |
| myService = service; |
| if (service != null) { |
| // Set the service so that it defers missing property gets to the |
| // Call. So when client-side Handlers get at the MessageContext, |
| // the property scoping will be MC -> SOAPService -> Call -> Engine |
| |
| // THE ORDER OF THESE TWO CALLS IS IMPORTANT, since setting the |
| // engine on a service will set the property parent for the service |
| service.setEngine(this.service.getAxisClient()); |
| service.setPropertyParent(myProperties); |
| } |
| } |
| |
| /** |
| * Sets the client-side request and response Handlers. This is handy |
| * for programatically setting up client-side work without deploying |
| * via WSDD or the EngineConfiguration mechanism. |
| */ |
| public void setClientHandlers(Handler reqHandler, Handler respHandler) |
| { |
| // Create a SOAPService which will be used as the client-side service |
| // handler. |
| setSOAPService(new SOAPService(reqHandler, null, respHandler)); |
| } |
| |
| |
| /** |
| * This method adds an attachment. |
| * <p> |
| * Note: Not part of JAX-RPC specification. |
| * |
| * @param attachment the <code>Object</code> to attach |
| * @exception RuntimeException if there is no support for attachments |
| * |
| */ |
| public void addAttachmentPart( Object attachment){ |
| attachmentParts.add(attachment); |
| } |
| |
| /** |
| * Add a fault for this operation. |
| * <p> |
| * Note: Not part of JAX-RPC specificaion. |
| * |
| * @param qname qname of the fault |
| * @param cls class of the fault |
| * @param xmlType XML type of the fault |
| * @param isComplex true if xmlType is a complex type, false otherwise |
| */ |
| public void addFault(QName qname, Class cls, |
| QName xmlType, boolean isComplex) { |
| if (operationSetManually) { |
| throw new RuntimeException( |
| Messages.getMessage("operationAlreadySet")); |
| } |
| |
| if (operation == null) { |
| operation = new OperationDesc(); |
| } |
| |
| FaultDesc fault = new FaultDesc(); |
| fault.setQName(qname); |
| fault.setClassName(cls.getName()); |
| fault.setXmlType(xmlType); |
| fault.setComplex(isComplex); |
| operation.addFault(fault); |
| } |
| |
| /** |
| * Hand a complete OperationDesc to the Call, and note that this was |
| * done so that others don't try to mess with it by calling addParameter, |
| * setReturnType, etc. |
| * |
| * @param operation the OperationDesc to associate with this call. |
| */ |
| public void setOperation(OperationDesc operation) { |
| this.operation = operation; |
| operationSetManually = true; |
| } |
| |
| public OperationDesc getOperation() |
| { |
| return operation; |
| } |
| |
| public void clearOperation() { |
| operation = null; |
| operationSetManually = false; |
| } |
| } |