Index: TECH/SOAP/WebClient.cls.xml =================================================================== diff -u --- TECH/SOAP/WebClient.cls.xml (revision 0) +++ TECH/SOAP/WebClient.cls.xml (revision 2465) @@ -0,0 +1,1443 @@ + + + + + +Properties of this class that begin with Http are passed through to the +%Net.HttpRequest instance used by the class. + +The only supported use of this class is as the super class for a SOAP Web Client. +Parameters, properties and methods may be used by the application.]]> +1 +%occErrors +TECH.SOAP.WebBase +3 + + + +The SOAPVERSION parameter specified the version of SOAP which is supported. +Possible values for the version are 1.1 and 1.2. The default value "" specifies +that both SOAP 1.1 and SOAP 1.2 are supported. +STRING +,1.1,1.2 +ENUM + + + + + If the web client has the parameter SOAPACTIONQUOTED=1, then the web client will +quote the SOAPAction value for SOAP 1.1. The default will be SOAPACTIONQUOTED=0 +in order to be compatible with earlier versions of Cache. +%Boolean +0 + + + +
+ +For a SOAP web client, SoapVersion specifies the SOAP version that is used +for the request.
+If SoapVersion="" (the default), then "1.1" is used if SOAPVERSION="1.1" or "" (the default). +Otherwise "1.2" is used if SOAPVERSION="1.2".
+After the response is received, it is the version of the response. +This, SoapVersion should be set before each method call.]]>
+%String +
+ + + +Deprecated. %Net.HttpRequester will always be used as the network access layer +%String + + + + + +If SoapBinary is 1, then the web client will use proprietary binary SOAP protocol. +The SoapBinary property defaults to the SOAPBINARY parameter. +%Boolean +..#SOAPBINARY +1 + + + + +Setter method to insure that first not binary message uses session cookie form binary messages +1 +value:%Boolean +%Status + + + + + +If set then we keep session cookie even if not binary session. +%Boolean +1 + + + + +Default charset for remote SOAP binary server. +This parameter is by default used to dertermine if binary message needs to be UTF8 encoded. +%String + + + + +Property to allow override of charset for remote SOAP binary server. +This parameter is used to dertermine if binary message needs to be UTF8 encoded. +The default for SoapBinaryCharset is the SOAPBINARYCHARSET parameter. +%String +..#SOAPBINARYCHARSET +1 + + + + +Property to allow the WS-Addressing namespace to be specified for requests +%String +1 + + + + +PolicyConfiguration is specified as 'Configuration class name':'Configuration name' +where 'Configuration name' comes from the name attribute of the configuration element +in the configuration class (i.e. sublcass of %SOAP.Configuration" +If PolicyConfiguration="" or is not specified, then the policy specified by the +service classname attribute is attached to this class.]]> +%String +1 + + + + +If specified, the caller assigned %Net.HttpRequest instance is used for +the web service request. +%Net.HttpRequest +1 + + + + +Content-Type to be used for transport class +%String +1 + + + + +The name of the activated TLS/SSL configuration to use for https requests. +%String +1 + + + + +If request uses an SSL connection and a SSL handshake error has occurred, +then SSLError contains text describing the SSL error. +%String + + + + +When making an SSL connection check the server identity in the certificate matches the name of the system we are connecting to. +This defaults to being on and matches based on the rules layed out in section 3.1 of RFC 2818. +%Boolean + + + + +If the GzipOutput property is set to true (1), then the output request +will be compressed using GZIP. +The default value for GzipOutput is the GZIPOUTPUT parameter. +%Boolean +..#GZIPOUTPUT +1 + + + +Timeout value.]]> +%Integer +1 + + + + +The HttpResponse property is set to the %Net.HttpResponse instance for the response to the +web service request. This property is only set when the %Net.HttpRequest object is used to +make the request, i.e. when HttpRequestor="CACHE" (the default). +%Net.HttpResponse +1 + + + + +The HTTP version we should report to the server when making the request. +Defaults to '1.1'. +%String +"1.1" +1 + + + + +If true then automatically follow redirection requests from the web server. +These are signaled by the HTTP status codes of the form 3xx. +The default is false. +%Boolean +1 + + + +Location and return the response.

+You can specify a default proxy server for this namespace or for this Caché +by setting ^SYS("HttpRequest","ProxyServer") or ^%SYS("HttpRequest","ProxyServer").]]> +%String +1 + + + + +You can specify a default proxy server for this namespace or for this Caché +by setting ^SYS("HttpRequest","ProxyPort") or ^%SYS("HttpRequest","ProxyPort").]]> +%String +1 + + + +HttpProxyServer and HttpProxyPort. If the endpoint URL +has the https: protocol, then once the tunnel is established we will negociate the SSL connection.]]> +%Boolean +1 + + + + +Use of SSL to the eventual endpoint is determined by the protocol part of +web service's location url.]]> +%Boolean +1 + + + + +HttpProxyHTTPS property is ignored since the use of SSL to the end point +is now determiend from the url. +If using a proxy server and this is true then it issues a request for an https page +rather than the normal http page. This allows a proxy server that support https to +support a secure connection from this %Net.Httprequest class. +%Boolean +1 + + + + +A user agent that wishes to authenticate itself with a proxy-- +usually, but not necessarily, after receiving a 407 response--may do +so by including an Proxy-Authorization header field with the request. The +Proxy-Authorization field value consists of credentials containing the +authentication information of the user agent for the realm of the +resource being requested.

]]> +%String +1 + + + + +The character set to send the HTTP request header in. According to the RFC the HTTP header +should only contain ASCII characters as the behaviour with characters outside this range +is unspecified. This class defaults to using UTF-8 as this leaves all the ASCII characters +unchanged. You should never need to change this parameter. +%String +1 + + + +Password are defined then this information +will be send using Basic authentication to the web server. If you manually set the +Authorization header this property will be ignored.]]> +%String +1 + + + +Username and Password are defined then this information +will be send using Basic authentication to the web server. If you manually set the +Authorization header this property will be ignored.]]> +%String +1 + + + + +If HttpAccept202=1, HTTP status 202 will treated just the same as HTTP status 200. +The HttpResponse.StatusCode property may be checked to see if 202 was actually returned.]]> +%Boolean +1 + + + + +If set to true then this will force the %Net.HttpRequest class to reuse the existing connection +to the web server if the socket is already open. If there is any error it will be reported to +the caller. This has been introduced to support reliable SOAP messaging, so should not normally +be set by other code. +%Boolean +1 +0 + + + + +Internal structure used to store the collection of headers for %Net.HttpRequest. +%String +1 +1 +1 + + + + +Do httprequest.SetHeader("MyHeader","Data to display") + +The header name is case insensitive and this class forces it to upper case so +when the Http request is issued it will output the header as:

+MYHEADER: Data to display

+Note that headers such as Content-Type, Content-Encoding, and Content-Length are +part of the entity body rather than the http main headers and as such as forwarded +to the ContentType, ContentEncoding and +trying to set the Content-Length is just ignored as this is a read only property. +Also any attempt to set the 'Connection' header is ignored at this request class +does not support persistent connections.]]> +name:%String,value:%String +%Status +1 + + + + + +Clear all previously set Http headers. +%Status +1 + + + + + +The WSSecurityLogin method adds the WS-Security Security header with /UsernameToken. +Only the /UsernameToken/Username and /UsernameToken/Password fields are supported. +Signing and/or encryption as specified by WS-Security is not supported. +These facilities are expected to be implemented by the use of SSL. +Username:%String,Password:%String +%Status +1 + + + + +1 +1 +1 + + + + + +Test for valid WS-Security 1.1 SignatureConfirmation elements in response message. +Return true if valid. +%Boolean +1 + + + + +
+ +The SecurityContextToken thus returned will be saved in the SecurityContextToken property. +Future calls to this client may use this token if needed for the WS-Policy or +by explicitly adding to SecurityOut by calling AddSecurityElement.

+ +The SecurityOut header needs to be set for proper security for the RequestSecurityToken request. +The SecurityOut header used for WS-StartSecureConversation will be cleared after when this method is complete.]]>
+RST:%SOAP.WST.RequestSecurityToken +%Status +1 + +
+ + + +Cancel the this client's current WS-SecureConversation token specified by the SecurityContextToken property. +Clear the SecurityContextToken propery. +If SecurityOut header has not been set, then a minimal SecurityOut using the token for signing is created. +The SecurityOut header used for WS-StartSecureConversation will be cleared after when this method is complete. +%Status +1 +0 { + Set target.token=SCT + } Else { + Do ..SecurityOut.AddSecurityElement(SCT) + Set sig=##class(%XML.Security.Signature).Create(SCT,,$$$SOAPWSReferenceSCT) + Do ..SecurityOut.AddSecurityElement(sig) + Set target.SecurityTokenReference=##class(%SOAP.Security.SecurityTokenReference).GetSCTReference(SCT) + } + + Set RST=##class(%SOAP.WST.RequestSecurityToken).%New() + Set RST.RequestType=$$$SOAPWSTCancel + Set RST.CancelTarget=target + + // Send request for SecurityContextToken + Set sc=..SendSOAPRequest($$$SOAPWSSCTokenCancelRequest,0,RST,"RequestSecurityToken") + + // Process response. + If $$$ISOK(sc) { + Set responseName=$$$xmlGetLocalName(RST.%ResponseDocument.DocumentId,RST.%ResponseNodeId) + If responseName="RequestSecurityTokenResponseCollection" { + Set element=##class(%SOAP.WST.RequestSecurityTokenResponseCollection).%New() + Set sc=element.XMLImport("RequestSecurityTokenResponseCollection","literal",$$$SOAPWSTNS,RST.%ResponseDocument,RST.%ResponseNodeId) + If $$$ISOK(sc) { + If element.RequestSecurityTokenResponse.Count()<1 { + Set sc=$$$ERROR($$$WSTCollectionEmptyResponse) + } Else { + // Use the first token for following messages + Set RSTR=element.RequestSecurityTokenResponse.GetAt(1) + If RSTR.RequestedTokenCancelled="" { + Set sc=$$$ERROR($$$WSTCancelResponse) + } + } + } + } Else { + Set sc=$$$ERROR($$$WSTCollectionResponseRequired,responseName) + } + } + + // Reset SecurityOut and SecurityContextToken after this request + Set ..SecurityOut="" + Set ..SecurityContextToken="" + + Quit sc +]]> + + + +
+ +The SecurityOut header needs to be set for proper security for the CreateSequence request. +The SecurityOut header used for WS-ReliableMessaging will be cleared after when this method is complete. + +If the SecurityContextToken property contains a SecurityContextToken, then this token will be +associated with the new sequence.]]>
+createSequence:%SOAP.RM.CreateSequence +%Status +1 + +
+ + + +Close this client's current WS-ReliableMessaging session specified by the RMSession property. +Clear the RMSession property. +%Status +1 + + + + + + Action is the SOAPAction for the SOAP request.
+ If OneWay is 1 (true) then no response is expected.
+ Request is the %SOAP.RequestMessage subclass instance.
+ MethodName is an optional name of the method being called which is used to select the WS-Policy.
+The response message node will be set in the ResponseDocuemtn and ResponseNodeId properties of %SOAP.RequestMessage.]]>
+action:%String,oneWay:%Boolean=0,request:%SOAP.RequestMessage,methodName:%String +%Status +1 + +
+ + + +1 +proxy:%SOAP.ProxyDescriptor,method:%String,Action:%String,OneWay:%Boolean=0 +%Status +1 +1.0 { + // Chunked output for HTTP/1.1 + Set stream=binwriter + } Else { + Set io=$io + Set stream=##class(%FileBinaryStream).%New() + Set sc=stream.Write("") ; force stream's file to open + If $$$ISERR(sc) Goto SOAPError + Set file=stream.Filename ; get filename and make current device + Use file:(/NOXY) + $$$SETIO("RAW") + Set binwriter.Chunked=0 + Do binwriter.OutputStream() + Use io + kill binwriter + If $$$ISERR(sc) Goto SOAPError + } + + #; Use transport to get response. + If transport="" { + Set transport=$this + // Try to use string for response if our built-in transport + Set responseStream="string" + } Else { + Set responseStream=##class(%GlobalBinaryStream).%New() + } + + $$$SOAPTimer("creq") + #; Make the request + Set sc=transport.DoSOAPRequest($this,Action,OneWay,stream,.responseStream) + + #; Log the response + $$$SOAPTimer("cres") + Do ##class(%SOAP.Binary).LogMessage(0,Action,responseStream,sc) + + If $$$ISERR(sc) Goto SOAPError + + #; If one-way, check for empty response + If OneWay { + If $isobject(responseStream) { + Do responseStream.Rewind() + Set len=1 + Set data=responseStream.Read(.len,.sc) + If $$$ISERR(sc) Goto SOAPError + Do responseStream.Rewind() + If len<=0 Set sc=$$$OK Goto SOAPExit + } Else { + If responseStream="" Set sc=$$$OK Goto SOAPExit + } + } + + If 'OneWay { + #; Reset any INOUT properties + Do proxy.Reset() + #; Import the SOAP response. + #; Deserialize the message class + if '$isobject(responseStream) { + set responseStream=##class(%SOAP.BufferedStream).%New(responseStream) + } + Set sc=..ReadBinaryMessage(proxy,.asUTF8,.sessionFlag,responseStream) + If $$$ISERR(sc) Goto SOAPError + #; return no session cookie, if session not wanted + If 'sessionFlag,..HttpRequest'="" Do ..HttpRequest.DeleteSessionCookie() + } + $$$SOAPTimer("cret") + Goto SOAPExit + } + + #; If in a SOAP session then add the SOAP session header + If ..SessionCookie'="" { + Set sessionHeader=##class(%SOAP.SessionHeader).%New() + Set sessionHeader.SessionCookie=..SessionCookie + Do ..HeadersOut.SetAt(sessionHeader,"CSPCHD") + } + + #; Add Sequence and SequenceAcknowledgement headers if RM session + If $isobject(..RMSession),'..RMSession.Terminated { + If ..RMSession.ResponseIdentifier'="",..RMSession.MessageNumber>0 { + Do ..HeadersOut.SetAt(##class(%SOAP.RM.SequenceAcknowledgement).CreateHeader(..RMSession,1),"SequenceAcknowledgement") + } + Set ..RMSession.MessageNumber=..RMSession.MessageNumber+1 + Do ..HeadersOut.SetAt(##class(%SOAP.RM.Sequence).CreateHeader(..RMSession,1),"Sequence") + } + + #; Find WS-Policy alternative + Set ..Action=Action + Set ..OneWay=OneWay + Set originalSecurityOut=r%SecurityOut + Set sc=##class(%SOAP.Policy).ProcessSendAlternative($this,..MethodName,.sendAlternative) + If $$$ISERR(sc) Goto SOAPError + + #; Get list of SOAP Headers + Set ..SoapHeaders=..#SOAPHEADERS + + #; Create WS-Security header with UsernameToken, if neeeded + If ..Username'="" Do ..MakeSecurityHeader() + + #; Setup WS-Addressing if required. + If '$data(sendAlternative),..AddressingOut="",$zcvt(..#WSADDRESSING,"U")="AUTO" { + Set action=##class(%SOAP.WebParameters).GetAction($classname(),..MethodName,"request") + If action="" Set action=Action + Set ..AddressingOut=##class(%SOAP.Addressing.Properties).GetDefaultRequestProperties(..Location,action,..WSANamespace) + } + + Set ..IsMTOM=0 + Set allowedVersion=..#SOAPVERSION + If allowedVersion="" { + If ..SoapVersion="" Set ..SoapVersion="1.1" + } ElseIf ..SoapVersion="" { + Set ..SoapVersion=allowedVersion + } Else { + If allowedVersion'=..SoapVersion { + Set sc=$$$ERROR($$$SOAPBadVersion,..SoapVersion) + Goto SOAPError + } + } + + #; Initialize any WS-Security operations. + Set wsRequired=..InitializeSecurity(.sc) + If $$$ISERR(sc) Goto SOAPError + + #; Check SoapVersion + If $case(..SoapVersion,"":0,"1.1":0,"1.2":0,:1) { + Set sc=$$$ERROR($$$SOAPBadVersion,..SoapVersion) + Goto SOAPError + } + + #; Create SOAP request + $$$XMLUseGlobal + Set sc=..WriteHTTPContent(proxy,proxy.%RequestName,0,wsRequired,,"") + If $$$ISERR(sc) Goto SOAPError + + #; Send SOAP request and get response + $$$SOAPTimer("creq") + If (..RMSession="") || (..RMSession.Terminated) { + Set sc=..SOAPRequestResponse(proxy,method,.retryAllowed) + + Set sequence=..HeadersIn.GetAt("Sequence") + If $classname(sequence)'="%SOAP.RM.Sequence" Set sequence="" + Set ack=..HeadersIn.GetAt("SequenceAcknowledgement") + If $classname(ack)'="%SOAP.RM.SequenceAcknowledgement" Set ack="" + + If $$$ISOK(sc), (sequence'="") || ((ack'="") && (..Action'=($$$SOAPWSRMns_"/CloseSequence")) && (..Action'=($$$SOAPWSRMns_"/TerminateSequence"))) { + Set sc=$$$ERROR($$$RMUnexpectedHeader,$select(sequence'="":"Sequence",1:"SequenceAcknowledgement")) + + } + } Else { + $$$XMLSave(streamSave) + Set ..HttpForceReuseDevice=..RMSession.SSLSecurity + For i=1:1:..RMSession.MaxRetryCount { + Set sc=..SOAPRequestResponse(proxy,method,.retryAllowed) + + If 'retryAllowed Quit + + If $$$ISOK(sc) { + Set sequence=..HeadersIn.GetAt("Sequence") + If sequence'="",$classname(sequence)'="%SOAP.RM.Sequence" Set sequence="" + + If ..RMSession.ResponseIdentifier'="" { + If '$isobject(sequence) { + Set sc=$$$ERROR($$$RMExpectedHeader) + Quit + } + If '..RMSession.CheckSCT($this) { + Set sc=$$$ERROR($$$RMUnexpectedHeader,"No SecurityContextToken, "_..RMSession.SCTIdentifier_", for Sequence with Identifier = "_sequence.Identifier) + Quit + } + If sequence.Identifier'=..RMSession.ResponseIdentifier { + Set sc=$$$ERROR($$$RMUnexpectedHeader,"Sequence with Identifier = "_sequence.Identifier) + Quit + } + If sequence.MessageNumber'=..RMSession.MessageNumber { + Set sc=$$$ERROR($$$RMUnexpectedMessageNumber) + Quit + } + $$$SOAPLogSecurity("Receive Sequence. MessageNumber="_sequence.MessageNumber) + } ElseIf $isobject(sequence) { + Set sc=$$$ERROR($$$RMUnexpectedHeader,"Sequence") + Quit + } + } + + Set ack=..HeadersIn.GetAt("SequenceAcknowledgement") + If $classname(ack)'="%SOAP.RM.SequenceAcknowledgement" Set ack="" + If $isobject(ack) { + If ack.Identifier'=..RMSession.RequestIdentifier { + Set sc=$$$ERROR($$$RMUnexpectedHeader,"SequenceAcknowledgement for Identifier "_ack.Identifier) + Quit + } + Do ack.UpdateSession(..RMSession) + $$$SOAPLogSecurity("Receive SequenceAcknowledgement.") + If ..RMSession.GetMessageState(..RMSession.MessageNumber) { + Do ..RMSession.MessageOK() + Quit + } + // Final indicates sequence terminated + If ack.Final=$c(0) Quit + } ElseIf $$$ISOK(sc) { + Do ..RMSession.MessageOK() + Quit + } + + Hang ..RMSession.RetryInterval + $$$XMLRestore(streamSave) + } + } + + $$$SOAPTimer("cret") + If $$$ISERR(sc) Goto SOAPError + +SOAPExit + If io'="" Use io + // Restore SecurityOut to a state that it can be reused for next call + If $get(wsRequired) || $isobject(r%SecurityOut) { + If $data(sendAlternative) { + // If WS-Policy created SecurityOut, Restore caller's SecurityOut + Set ..SecurityOut=originalSecurityOut + } Else { + // Just reset code created SecurityOut + Do ..ResetSecurity() + } + } + Set ..KeepSessionCookie=0 + Do ..HeadersOut.Clear() + Set ..AddressingOut="" + Set ..NamespacesOut="" + If ..Username'="" { + Set (..Username,..Password)="" + If $isobject(r%SecurityOut) { + Do r%SecurityOut.RemoveElement("UsernameToken") + } + } + Set ..ContentType="" + If error { + Set %objlasterror=sc + If $$$CheckSOAPLogInput || $$$CheckSOAPLogSecurity { + Kill err + Do $system.Status.DecomposeStatus(sc,.err) + $$$SOAPLogText("**** SOAP client return error. method="_method_", action="_Action) + $$$SOAPLogText(" "_err(1)_$c(13,10)_$c(13,10)) + } + if method'="" Ztrap "SOAP" + } + Quit sc + +SOAPError + Set error=1 + Goto SOAPExit +]]> + + + + +1 +proxy:%SOAP.ProxyDescriptor,method:%String,*retryAllowed:%Boolean +%Status +1 + + + + + +1 + +%Status +1 +1 Set request.Port=$piece(host,":",2) + If $length(Location,"?")>1 { + Set Location=##class(%CSP.Page).EscapeURL($piece(Location,"?",1),"UTF8")_"?"_$piece(Location,"?",2,$length(Location,"?")) + } Else { + Set Location=##class(%CSP.Page).EscapeURL(Location,"UTF8") + } + Set sc=request.Post($piece(Location,"/",2,$length(Location,"/"))) + If $$$ISERR(sc) Set ..SSLError=request.SSLError Quit sc + Set response=request.HttpResponse + Set ..HttpResponse=response + Set responseStream=response.Data + Set responseStatus=response.StatusCode + + #; 202 response OK for one-way messages. + If OneWay,(responseStatus="202") || (responseStatus="200") Quit $$$OK + + #; If HttpAccept202, treat status 202 as 200. + If ..HttpAccept202,responseStatus=202 Set responseStatus=200 + + #; Check response + If $case(responseStatus,"200":0,"201":0,"400":0,"500":0,:1) { + Quit $$$ERROR($$$SOAPUnexpectedStatus,response.StatusCode) + } + + If responseStream="" Quit $$$ERROR($$$SOAPNoResponseBody) + + Set responseContentType=$zcvt($piece(response.ContentType,";",1),"L") + If ..SoapBinary { + If (responseContentType'="application/octet-stream") Quit $$$ERROR($$$SOAPUnexpectedType,response.ContentType) + } Else { + If (responseContentType'="text/xml") && + (responseContentType'="application/soap+xml") && + (responseContentType'="multipart/related") { + Quit $$$ERROR($$$SOAPUnexpectedType,response.ContentType) + } + } + + Quit $$$OK +]]> + + + + + Index: TECH/SOAP/WebBase.cls.xml =================================================================== diff -u --- TECH/SOAP/WebBase.cls.xml (revision 0) +++ TECH/SOAP/WebBase.cls.xml (revision 2465) @@ -0,0 +1,2924 @@ + + + + + +The only supported use of this class is as the super class for +%SOAP.WebService and TECH.SOAP.WebClient in order to define common properties and parameters. +Parameters and properties may be used by the application.

+ +In addition to parameters, an XData block may be used to supply additional information about +the web service or web client. +The XData member may contain descriptions of the expected request and response headers. However, only one configuration +The format of the parameters element is as follows:
+

+<parameters xmlns="http://www.intersystems.com/configuration">
+   <request>
+      <header ... </header> * 
+   </request> ?
+   <response>
+      <header ... </header> * 
+   </response> ?
+   <method name="xs:NCNAME">
+      <request>
+         <header ... </header> * 
+      </request> ?
+      <response>
+         <header ... </header> * 
+      </response> ?
+   </method> *
+</parameters>
+
+Cardinality is indicated by ? (0 or 1), * (0 or more) and + (1 or more) after the ending element.
+
+The following describes the elements and attributes:
+/parameters
+    Identifies parameters root
+/parameters/request
+    The parameters for the request message corresponding to all methods for this web service or client.
+    These parameters are merged with the parameters for the individual method.
+/parameters/request/header
+    The specification of a SOAP header which may be associated with this request message.
+    The format of the header element is described below.
+/parameters/response
+    The parameters for the response message corresponding to all methods for this web service or client.
+    These parameters are merged with the parameters for the individual method.
+/parameters/response/header
+    The specification of a SOAP header which may be associated with this response message.
+    The format of the header element is described below.
+
+/parameters/method
+    The parameters for this method for this web service or client.
+/parameters/method/@name
+    The name of the method
+/parameters/method/request
+    The parameters for the request message corresponding to this method for this web service or client.
+/parameters/method/request/header
+    The specification of a SOAP header which may be associated with this request message.
+    The format of the header element is described below.
+/parameters/method/response
+    The parameters for the response message corresponding to this method for this web service or client.
+/parameters/method/response/header
+    The specification of a SOAP header which may be associated with this response message.
+    The format of the header element is described below.
+
+The definition of the header element is as follows:
+<header name="s:string" 
+           namespace="s:string"
+           class="s:string"
+           alias="s:string"? 
+/>
+
+.../header/@name
+    The required element name of the header.
+.../header/@namespace
+    The required namespace of the header.
+.../header/@class
+    The required name of the Cache class that corresponds to the header.
+.../header/@alias
+    The optional alias to be used for this header in the HeadersIn array.
+    The default is the element name specified in the name attribute.
+
]]> +1 +%soap,%xmlDOM,%occSAX,%sySystem +%systemInclude,%soap +%RegisteredObject +3 + + + + + + + +The ARGUMENTSTYLE parameter may be used to specify a message format in which +each request message part (not the elements of the part's type) is an argument +and each response message part is a return value or output argument. +The use of the message or wrapped format is specified by the ARGUMENTSTYLE parameter +of the web service or web client class. +The default value for ARGUMENTSTYLE is "wrapped" or "". +Message style arguments are indicated by a value of "message". +The ARGUMENTSTYLE parameter will be ignored if the SoapBindingStyle is not document. +STRING +,message,wrapped +ENUM + + + + +NAMESPACE - Should be an unique URI +Override this parameter in the subclass with the unique namespace URI +of your organization. +Override this parameter in the subclass. +http://tempuri.org + + + + +The RESPONSENAMESPACE parameter for SOAP client and SOAP service classes allows +the SOAP request and SOAP response messages when SoapBindingStyle="rpc" +to each be in a different namespace. The RESPONSENAMESPACE parameter specifies +the namespace for the SOAP response message descriptor class. +If RESPONSENAMESPACE is not specified the default is the NAMESPACE parameter. + +The RESPONSENAMESPACE parameter applies to all methods in the class and is not +overridden by the SoapNameSpace method keyword. + + + + +ELEMENTQUALIFIED controls the format of the SOAP body. +The ELEMENTQUALIFIED specification reflects the elementFormDefault attribute of the +schema element for the TYPENAMESPACE in the WSDL defining the SOAP service. +To maintain compatibility, ELEMENTQUALIFIED will default to 1 (true) for SoapBodyUse="literal" +and will default to 0 (false) for SoapBodyUse="encoded". +These were the values always previously assumed for the elementFormDefault attribute. +BOOLEAN + + + + +ATTRIBUTEQUALIFIED controls the format of the SOAP body. +The ATTRIBUTEQUALIFIED specification reflects the attributeFormDefault attribute of the +schema element for the TYPENAMESPACE in the WSDL defining the SOAP service. +ATTRIBUTEQUALIFIED defaults ot 0 if not specified. +BOOLEAN + + + + +TYPENAMESPACE specifies the XML namespace for the types used for +the method arguments and return types in this web client or +web service. If TYPENAMESPACE is not specified or is "", +then the default namespace used for the types is from +the NAMESPACE parameter. +Override this parameter in the subclass. + + + + +The RESPONSETYPENAMESPACE parameter for SOAP client and SOAP service classes allows +the SOAP request and SOAP response message parts when SoapBindingStyle="document" +to each be in a different namespace. The RESPONSETYPENAMESPACE parameter specifies +the namespace for the SOAP response message descriptor class. +If RESPONSETYPENAMESPACE is not specified the default is the TYPENAMESPACE parameter. + +The RESPONSETYPENAMESPACE parameter applies to all methods in the class and is not +overridden by the SoapTypeNameSpace method keyword. + + + + +Specifies if part elements of messages in the WSDL use type or element attribute. +XMLELEMENT defaults to 1 for "literal" WSDL and to 0 for "encoded" WSDL. +BOOLEAN + + + + + +If XMLIGNORENULL is set = 1, then both missing tags in the XML and empty +strings are input as "", and both "" and $c(0) are output as empty tags +(i.e. <tag />).
+ +If XMLIGNORENULL is set = "inputonly", then both missing tags in the XML and empty +strings are input as "". Output of "" and $c(0) are for XMLIGNORENULL = 0: +$c(0) is output as an empty tag (i.e. <tag />) and "" is output as no tag.
+ +XMLIGNORENULL specified in the web client or service class specifies +XMLIGNORENULL for the SOAP messages used for each web method.]]>
+STRING +,0,1,inputonly +ENUM +
+ + + +The SOAPVERSION parameter specified the version of SOAP which is supported. +Possible values for the version are 1.1 and 1.2. The value "" specifies +that both SOAP 1.1 and SOAP 1.2 are supported. +STRING +,1.1,1.2 +ENUM + + + + +The XMLIGNOREINVALIDTAG parameter allows the programmer to control handling of unexpected +elements in the XML input. +By default (XMLIGNOREINVALIDTAG = 0), will treat an unexpected element as an error. +If XMLIGNOREINVALIDTAG is set = 1, then unexpected elements will be ignored. +BOOLEAN +1 +0 + + + +
]]>
+%String +
+ + + +Action for this web service call +%String +1 +1 + + + + +SOAPBINARY - If = 1, then binary SOAP messages will be supported. +BOOLEAN + + + + +SERVICENAME - Should be the name of the service for which this is a proxy. +Override this parameter in the subclass. + + + + +SOAPPREFIX allows override of the default SOAP prefix. Default is SOAP-ENV. +The prefix must be specified without the trailing ":". +STRING +SOAP-ENV + + + + +Checking the existence of REQUIRED properties and arguments is off by default. +To turn on REQUIRED checking. set the SOAPCHECKREQUIRED parameter to 1 (default is 0). +BOOLEAN +0 + + + +%Boolean +0 + + + + +OUTPUTTYPEATTRIBUTE allows the programmer to force the xsi:type attribute to be included +in all elements of a SOAP message which is a web client request or web service response. +BOOLEAN +0 + + + +ReferencesInline is true (1), then encoded objects are exported inline. +By default, SOAP encoded XMLExport of a class uses idref's for class instances referenced by +a class that is being exported. This change allows the referenced class instances to be exported +inline as for "literal" format.]]> +%Boolean +1 + + + + +If REFERENCESINLINE is true (1), then encoded objects are exported inline. +By default, SOAP encoded XMLExport of a class uses idref's for class instances referenced by +a class that is being exported. This change allows the referenced class instances to be exported +inline as for "literal" format. +If the ReferencesInline property is specified, then it will override the REFERENCESINLINE parameter. +BOOLEAN +0 + + + +Base64LineBreaks is true (1), then remove line breaks +from base64 encoded XML output for all properties of type %Binary or %xsd.base64Binary. +The default is 0 which will be to not include line breaks. +If this property is specified, then it will override the BASE64LINEBREAKS parameter.]]> +%Boolean +1 + + + + +If BASE64LINEBREAKS is true (1), then remove line breaks +from base64 encoded XML output for all properties of type %Binary or %xsd.base64Binary. +The default is 0 which will be to not include line breaks. +If the Base64LineBreaks property is specified, then it will override the BASE64LINEBREAKS parameter. +BOOLEAN +0 + + + + +The Transport property may be set to an instance of a transport class which will +provide a DoSoapRequest method that will take a request and obtain the response +using its transport. +%RegisteredObject +1 + + + + +Location property. Initialized to LOCATION parameter. +%String +..#LOCATION +1 + + + + +Timeout property. Controls timeout waiting, in seconds, for response. +%Integer +1 + + + + +For a web service, this is the SOAP Fault to return. + The SoapFault property may be set before calling Process to return a SOAP fault. +For a web client, when the response message is a SOAP fault, then ZTRAP is throw and + SoapFault is the corresponding %SOAP.Fault instance. +%SOAP.Fault +1 + + + + +SAXFlags property. The flags passed to the SAX parser. +%Integer +$$$SAXFULLDEFAULT-$$$SAXVALIDATIONSCHEMA +1 + + + + +The name of method that is called. +The method name is used to determine which WS-Policy applies and which headers are expected to be received. +%String +1 +1 + + + + +A list of supported SOAP headers is specified as a comma separated list of input header +specifications. Each specification is of the form "headerName:headerClass" where +headerName is the element name of the supported header and +headerClass is the %SOAP.Header subclass that corresponds to that header. +This list defines all headers supported in the SOAP request. + + + + +%String +1 +1 + + + + +Any SOAP header in the SOAP request that is found in the SOAPHEADERS list or header element +of parameters XData is imported as a %SOAP.Header subclass and added to the HeadersIn array. +The web method may then act on these headers as appropriate. +%SOAP.Header +array +1 + + + + +Any web service or web client method may add instances of any %SOAP.Header subclass to this array. +The index is arbitrary but is usually the element name of the header. +The corresponding headers are then added to the SOAP response message. +This collection of headers is cleared after each method call. +%SOAP.Header +array +1 + + + + +WSADDRESSING parameter controls automatic generation of WS-Addressing headers. +STRING +,OFF,AUTO +OFF +ENUM + + + + +WS-Addressing properties of the input message. +AddressingIn will be = "", unless some WS-Addressing headers are +encountered in the SOAP headers. +%SOAP.Addressing.Properties + + + + +WS-Addressing properties for the output message. +SOAP headers will be constructed from these properties. +%SOAP.Addressing.Properties + + + + +Namespaces for message to be output. +%XML.Namespaces +1 +1 + + + + +The XML namespace used for the security header. +SecurityNamespace is set based on WS-Security namespace used for an input message +or may be set to control the WS-Security namespace used for an output message. +%String +1 + + + + +The wsu:Id attribute to be added to the Body element when writing a SOAP message. +%String +1 + + + + + +The xml:id attribute to be added to the Body element when writing a SOAP message. +Usually wsu:Id will be used, but in certain cases xml:id is needed. +%String +1 + + + + + +OneWay is true if no body is to be sent. +%Boolean +1 +1 + + + + +Return the value of the BodyId property. +Populate the BodyId property if it is not yet set. +%String + + + + + +- The default value of IGNORE will ignore any WS-Security headers in the input +except for the UsernameToken which can always be used to login the user.
+- The value of ALLOW will cause the WS-Security header to be verified on input.
+- The value of REQUIRE will require the presence of the WS-Security header and +verify the header on input.
+- The value of IGNOREALL will ignore any WS-Security headers in the input +including the UsernameToken.

+- The value of NOHEADER will REALLY ignore any WS-Security headers in the input +including the UsernameToken.

+ +Note that if validation of the Security header is enabled (ALLOW or REQUIRE), +then a CA file, named cache.cer, containing the trusted root X509 certificates +should be put in the Cache Mgr directory if signature verification or decryption +is to be performed. An optional Certificate Revocation List (cache.crl) may +also be put in the Cache Mgr directory.]]>
+%STRING +ALLOW,NOHEADER,IGNORE,IGNOREALL,REQUIRE +IGNORE +ENUM +
+ + + +The WS-Security header associated with the received SOAP message. +SecurityIn will = "" unless a Security heaader is present in the message. +%SOAP.Security.Header +1 + + + +
+ +Any combination of Timestamp, UsernameToken and Signature elements may be included +in the Security header.
+To add a Timestamp element:
+ do ..SecurityOut.AddSecurityElement(##class(%SOAP.Security.Timestamp).Create(interval))
+ The interval argument is the time in seconds between Created and Expires times. + If interval is not specified, then the default is 300 seconds.

+ +To add a UsernameToken element:
+ do ..SecurityOut.AddSecurityElement(##class(%SOAP.Security.UsernameToken).Create(username,password))
+ The UsernameToken added using the above call will be used for all subsequent calls. + The WSSecurityLogin method should be used to add the UsernameToken just for the next call.

+ +To add a Signature element:
+ set x509=##class(%SYS.X509Credentials).GetByAlias(x509Alias)
+ set cert=##class(%SOAP.Security.BinarySecurityToken).CreateX509Token(x509)
+ do ..SecurityOut.AddSecurityElement(cert)
+ do ..SecurityOut.AddSecurityElement(##class(%XML.Security.Signature).CreateX509(cert))
+ The configName argument is the name of a SSL/TLS Configuration, specified using the System Management Portal, + that contains the certificate file and private key file/password used for signing. + The private key password may be included with the configuration name as + "name|password" instead of in the configuration. + For initial release the configuration name is that of an SSL/TLS Configuration. + BEWARE that this is subject to change in future releases.]]>
+%SOAP.Security.Header +1 +
+ + +1 +%SOAP.Security.Header + + + + +1 +s:%SOAP.Security.Header +%Status + + + + + +Return SecurityOut if defined, else "". +1 +%SOAP.Security.Header + + + + +
+ +For a web client this is the SecurityContextToken that was obtained by the call to the StartSecureConversation +call that started the session. This call will save the SecureConversation token from the +RequestSecurityTokenResponse in this property.

+ +For a web service this is the SecurityContextToken that was used to secure the request message. +

+Future request or response messages may use this token if needed for the WS-Policy or +by explicitly adding to SecurityOut by calling AddSecurityElement.]]>
+%SOAP.WSSC.SecurityContextToken +1 +
+ + +
+ +For a web client this is the sequence that was created by the call to the %StartRMSession +method that started the sequence. This call will save the $SYS.RMSession object from the +CreateSequenceResponse in this property.

+ +For a web service this is the $SYS.RMSession that was used for the request message.]]>
+%SYS.RMSession +1 +
+ + + +The Attachments property of %SOAP.WebService will contain any attachments as +%Net.MIMEPart instances when a multipart/related SOAP request is received. +The SOAP message itself will be executed as for any SOAP message. + +If any %Net.MIMEPart instances are in the Attachments property list collection in +TECH.SOAP.WebClient, then the SOAP request will be sent as a multpart/related MIME message +per the SOAP with Attachments specification. +%Net.MIMEPart +list +1 + + + + +The Content-Id of the SOAP part of the SOAP with Attachments package for SOAP requests. +ContentId is used only in conjunction with the Attachments property. +Set to the received Content-Id by the web service. +Set before calling a web client method to set the Content-Id. +%String +1 + + + + +The Content-Location of the SOAP part of the SOAP with Attachments package for SOAP requests. +ContentLocation is used only in conjunction with the Attachments property. +Set to the received Content-Location by the web service. +Set before calling a web client method to set the Content-Location. +%String +1 + + + + +If any %Net.MIMEPart instances are in the ResponseAttachments property list collection in +%SOAP.WebService, then the SOAP response will be sent as a multpart/related MIME message +per the SOAP with Attachments specification. + +The ResponseAttachments property of TECH.SOAP.WebClient will contain any attachments as +%Net.MIMEPart instances when a multipart/related SOAP response is received. +The SOAP message itself will be executed as for any SOAP message. +%Net.MIMEPart +list +1 + + + + +The Content-Id of the SOAP part of the SOAP with Attachments package for SOAP responses. +ResponseContentId is used only in conjunction with the ResponseAttachments property. +Set to the received Content-Id by the web client. +Set during the web service method to set the Content-Id. +%String +1 + + + + +The Content-Location of the SOAP part of the SOAP with Attachments package for SOAP responses. +ResponseContentLocation is used only in conjunction with the ResponseAttachments property. +Set to the received Content-Location by the web client. +Set during the web service method to set the Content-Location. +%String +1 + + + +MTOMRequired which controls use +of MTOM optimization.]]> +BOOLEAN +0 + + + + +For a web client, MTOMRequired=1 means that the SOAP request will be a MTOM package. +A web client will always be able to process a response as an MTOM package independent of the value of MTOMRequired.
+For a web service, MTOMRequired=1 means that the SOAP response will always be an +MTOM package even if the request was not MTOM. MTOMRequired may be set in the +web method being called or in the OnPreWebMethod callback. A web service will always respond with +an MTOM package if the request was an MTOM package independent of the value of MTOMRequired.
+The default for the MTOMRequired property is the value of the +MTOMREQUIRED parameter.]]>
+%Boolean +..#MTOMREQUIRED +1 +
+ + + +IsMTOM is set to true if an MTOM package was received. +%Boolean + + + + +This property contains the session cookie to be included in the Cache proprietary +SOAP session header to maintain the Cache SOAP session. +SessionCookie will be set from the Cache SOAP session header received in the SOAP request. +%String +1 + + + + +Clear client HTTP cookies when setting SessionCookie from user code +1 +value:%String +%Status + + + + + +Set SessionCookie directly for internal use +1 +value:%String + + + + + +Note that Cache security login is based on the UsernameToken element of the Security header.
+For a web client, if Username is set then a UsernameToken will be included +in the Security header based on the Username and Password properties.
+For a web service, Username is set based on the username contained in the +UsernameToken in the Security header of the message. +For a request message Username is based on the WS-Security SOAP header in the request.]]>
+%String +1 +
+ + + +Note that Cache security login is based on the UsernameToken element of the Security header.
+For a web client, if Username is set then a UsernameToken will be included +in the Security header based on the Username and Password properties.
+For a web service, Password is set based on the password contained in the +UsernameToken in the Security header of the message.]]>
+%String +1 +
+ + + +If the GZIPOUTPUT parameter is set to true (1), then output (request for client, +response for service) will be compressed using GZIP. +For a web client, this may be overridden by setting the GzipOutput +property of the web client class. +BOOLEAN + + + + +
+  Method test(..... [WebMethod] ; for a client
+  { 
+     Set ..WriteSOAPBodyMethod="override" 
+     Do ..WebMethod("test").Invoke(..... 
+     Set ..WriteSOAPBodyMethod="" 
+  } 
+
+ + or + +
+  Method test(..... [WebMethod] ; for a service
+  { 
+     Set ..WriteSOAPBodyMethod="override" 
+     ; service method follows
+     .....
+  } 
+
+The signature of the override method is
+
+  Method override(proxy As %SOAP.ProxyDescriptor, tag As %String)
+
+The override method uses the Write command to output the body.]]>
+%String +1 +
+ + + +Control use of BOM for request message. +Comma separated list of message start parts: +BOM to include BOM, DCL to include XML declaration. +%String +"DCL" +1 + + + + +Policy alternative for client output of request and service input of request. +First alternative checked for response. +%String +1 +1 +1 + + + + +After the %SOAP.WebService Initialize method is called, this property contains the %XML.Document +instance for the parsed SOAP request. +After the TECH.SOAP.WebClient parses the response, this property contains the %XML.Document +instance for the parsed SOAP response. +%XML.Document +1 + + + + +1 +1 +text:%String,outputRaw:%Boolean=0 +1 + + + + + +1 +1 +var:%String +1 + + + + + +1 +1 +isService:%Boolean,action:%String,inputStream,status:%Status +1 +W"),! + } + // Try to log just headers if requested + If ^ISCSOAP("Log")["h",..LogHeaders(inputStream) Quit + // Log entire message otherwise + If $isobject(inputStream) { + Do inputStream.OutputToDevice() + Do inputStream.Rewind() + } Else { + Write inputStream + } + } Catch ex { + Set error="Error during SOAP logging: "_ex.DisplayString() + } + + If error'="" { + $$$SevereError(error) + $$$SevereError("SOAP logging will be terminated.") + // turn off logging + Kill ^ISCSOAP("Log") + } + + If open Close file + If io'="" Use io + Quit +]]> + + + + +1 +1 +isService:%Boolean,action:%String,outputStream,description:%String +1 + + + + + +Log only the beginning of the SOAP message up to the end of the SOAP headers. +Return true if Headers found and output/ +1 +1 +stream +1 +%Boolean +1 +",pos) + // If malformed, then cannot output just Headers + If pos=0 Quit + } + + // Look for required Envelope element + Set env=$zstrip($translate($extract(buffer,pos,pos+100),$c(9,10,13,160)," "),"",1) + If (($length(env,":")=1) && (env="",pos) + } Else { + // If no Envelope, then cannot output just Headers + Set pos=0 + } + } Else { + // If no Envelope, then cannot output just Headers + Set pos=0 + } + // If malformed, then cannot output just Headers + If pos=0 Quit + + // Stream as expected + Set result=1 + + // Look for Headers element + Set header=$zstrip($translate($extract(buffer,pos,pos+100),$c(9,10,13,160)," "),"",1) + If (($length(header,":")=1) && (header="",pos) + } + } + // If no Header, then just output Envelope + If hdrpos=0 { + Write $extract(buffer,1,pos-1),$c(13,10) + Quit + } + Set endheader="",pos) + If pos'=0 { + Set pos=pos-1 + } Else { + Set pos=$length(buffer) + } + Quit + } + } + // If end of headers found, write until end of headers and quit + If pos'=0 { + Write $extract(buffer,1,pos),$c(13,10) + Quit + } + + // If /Header not found, then write the entire buffer and get the next buffer + Write buffer + If stream=0 { + Set buffer=$$$XMLRead(32000) + } ElseIf $isobject(stream) { + Set buffer=stream.Read(32000) + } Else { + Set buffer="" + } + Set hdrpos=1 + } + } Catch { + } + + If stream=0 { + $$$XMLRewind + } ElseIf $isobject(stream) { + Do stream.Rewind() + } + + Quit result +]]> + + + + +1 +1 +1 +expression +1 + + + + + +Write the entire HTTP content for a SOAP request or response. +If a web client, then always write the HTTP content to a stream. +If a web service, then write the HTTP content to the current TCP device. +1 + +%Status +1 +0) || responseMTOM { + Set mimeAttachments=##class(%Net.MIMEPart).%New() + For i=1:1:numAttachments Do mimeAttachments.Parts.Insert(attachments.GetAt(i)) + Set contentid=..ContentId + If responseMTOM { + If contentid="" { + Set mimeAttachments.ContentId=$tr($system.Util.CreateGUID(),"-",".") + Set contentid="0."_mimeAttachments.ContentId + } Else { + Set mimeAttachments.ContentId=contentid + } + Set contentType= + "multipart/related; type=""application/xop+xml""; boundary="_mimeAttachments.Boundary_ + "; start=""<"_contentid_">""; start-info="""_soaptype_"""" + } Else { + Set contentType="multipart/related; type="""_soaptype_"""; boundary="_mimeAttachments.Boundary + If contentid'="" Set contentType=contentType_"; start=<"_contentid_">" + } + If 'isService,soap12 Set contentType=contentType_"; action="""_..Action_"""" + Set mimeAttachments.ContentType=contentType + If $isobject(response) { + If response.GetHeader("MIME-Version")="" { + Do response.SetHeader("MIME-Version","1.0") + } + Set response.ContentType=contentType + Set response.CharSet=$select($$$XMLIsWrite:"utf-8",1:"") + Do response.WriteHTTPHeader(.OutputBody) + } + } Else { + Set mimeAttachments="" + Set contentType=""_soaptype_"; charset=UTF-8" + If 'isService,soap12 Set contentType=contentType_"; action="""_..Action_"""" + If $isobject(response) { + If ..SoapVersion="1.2" Set response.ContentType=soaptype + Do response.WriteHTTPHeader(.OutputBody) + } + } + + If 'isService Set ..ContentType=contentType + + #; Save space for MIME headers for part containing SOAP envelope + If mimeAttachments'="" { + If $$$XMLIsWrite { + Do ..WriteStartAttachments(mimeAttachments.Boundary,soaptype,isService,contentid,contentLocation) + } Else { + $$$XMLUseNext + } + } + + #; Setup Security header binary line breaks + If ..Base64LineBreaks="" Set ..Base64LineBreaks=..#BASE64LINEBREAKS + If $isobject(r%SecurityOut) { + Set r%SecurityOut.Base64LineBreaks=..Base64LineBreaks + } + + #; Setup encoded inline property for body and headers + If ..ReferencesInline="" Set ..ReferencesInline=..#REFERENCESINLINE + + #; Output the SOAP envelope + Set sc=..WriteSOAPMessage(body,tag,isService,mimeAttachments,.bodyStream) + If $$$ISERR(sc) Goto HTTPError + If wsRequired { + If $$$CheckSOAPLogSecurity { + Do ..LogOutput(isService,..Action,0,"Before WS-Security applied") + } + + #; Pass attchments through to signing code. + New %cspsoapmimeAttachments + Set %cspsoapmimeAttachments=mimeAttachments + + #; If signing or encryption needed, then add these security elements + #; to the WS-Security header. + If $isobject(r%SecurityOut) { + Set sc=r%SecurityOut.Perform() + If $$$ISERR(sc) Goto HTTPError + } + #; Perform operation for any custom security headers + Set sc=$$$OK + Set headerName="" + For { + If $$$ISERR(sc) Quit + Set header=..HeadersOut.GetNext(.headerName) + If headerName="" Quit + If $parameter(header,"CUSTOMSECURITY") { + Set sc=header.Perform() + If $$$ISERR(sc) Quit + } + } + If $$$ISERR(sc) Goto HTTPError + + } + $$$SOAPTimer($select(isService:"s",1:"c")_"wperform") + $$$XMLUseLast + + #; Output MIME parts for attachments + If mimeAttachments'="" { + #; Output Attachments + Set writer=##class(%Net.MIMEWriter).%New() + If $$$XMLIsWrite { + $$$SETIO("RAW") + Set sc=writer.WriteMIMEBody(mimeAttachments) + If $$$ISERR(sc) Goto HTTPError + + } Else { + Do writer.OutputToStream(0) ;; output to internal SOAP buffer. + Set sc=writer.WriteMIMEBody(mimeAttachments) + If $$$ISERR(sc) Goto HTTPError + $$$XMLUseNext + + #; Go back and output MIME headers + Set saveIndex=$$$XMLCurrentIndex + Set $$$XMLCurrentIndex=1 + $$$XMLSetTerminator($c(13,10)) + Do ..WriteStartAttachments(mimeAttachments.Boundary,soaptype,isService,contentid,contentLocation) + $$$XMLSetDefaultTerminator + Set $$$XMLCurrentIndex=saveIndex + } + } + + If logOutput Do ..LogOutput(isService,..Action,0) + +HTTPError + Quit sc +]]> + + + + +Output the start of the first MIME block for attachments +1 +boundary:%String,soaptype:%String,isService:%Boolean,contentid:%String,contentLocation:%String +1 +") + $$$XMLWriteLine + } + If ..ContentLocation'="" { + $$$XMLSetBuffer("Content-Location: "_contentLocation) + $$$XMLWriteLine + } + $$$XMLSetBuffer("") + $$$XMLWriteLine +]]> + + + + +1 +body:%SOAP.Descriptor,tag:%String,isService:%Boolean,mimeAttachments:%Net.MIMEPart,bodyStream:%CharacterStream +%Status +1 +0)) { + Set sc=..WriteSOAPHeaders(bodyUse,namespaces,mimeAttachments) + If $$$ISERR(sc) Quit sc + } + $$$SOAPTimer(%SOAPTimerChar_"wsec") + + If 'isService || 'oneWay { // If one-way service response with headers, then no body. + $$$XMLSetBuffer(" <"_..#SOAPPREFIX_":Body") + Set securityHeader=r%SecurityOut + If ..BodyId'="" { + $$$XMLAppendBuffer(" wsu:Id="""_..BodyId_"""") + Set ..BodyId="" + } + If ..BodyXmlId'="" { + $$$XMLAppendBuffer(" xml:id="""_..BodyXmlId_"""") + Set ..BodyXmlId="" + } + If (bodyUse="encoded") && (..SoapVersion="1.1") { + $$$XMLAppendBuffer(" "_..#SOAPPREFIX_":encodingStyle='"_$$$SOAPENCns_"'") + } + $$$XMLAppendBuffer(">") + $$$XMLWrite + + $$$XMLUseNext + If $isobject(r%SecurityOut),'$$$XMLIsWrite { + Set r%SecurityOut.BodyBufferIndex=$$$XMLCurrentIndex + } + If ..WriteSOAPBodyMethod'="" { + If $$$XMLIsWrite { + Set sc=$method($this,..WriteSOAPBodyMethod,body,tag) + } Else { + Set bodyStream=##class(%FileBinaryStream).%New() + Set sc=bodyStream.Write("") ; force stream's file to open + If $$$ISOK(sc) { + Set io=$io + Set file=bodyStream.Filename ; get filename and make current device + Use file:(/NOXY) + $$$SETIO("UTF8") + Set sc=$method($this,..WriteSOAPBodyMethod,body,tag) + Use io + $$$XMLSetStream(bodyStream) + } + } + } Else { + If $data(bodyStream) { + If $$$XMLIsWrite { + If $isobject(bodyStream) { + Set sc=bodyStream.OutputToDevice() + } Else { + Write bodyStream + } + } Else { + // Need to convert to UTF-8 now since the rest of the envelope is UTF-8 + Set responseBody=##class(%GlobalCharacterStream).%New() + Set sc=bodyStream.Rewind() + While $$$ISOK(sc)&&'bodyStream.AtEnd { + Set sc=responseBody.Write($zcvt(bodyStream.Read(.len),"O","UTF8")) + } + $$$XMLSetStream(responseBody) + } + } Else { + Set format=bodyUse + If bare { + Set format=format_",group" + } Else { + If (bodyUse="encoded") && (..SoapVersion'="1.1") { + Set attrs($increment(attrs))=..#SOAPPREFIX_":encodingStyle" + Set attrs(attrs,0)=$$$SOAP12ENCns + Set format="encoded12" + } + If forceTNS Set tag="tns:"_tag + } + Set namespaces.AttributeQualified=''..#ATTRIBUTEQUALIFIED + If ..ReferencesInline Set format=format_",inline" + If ..Base64LineBreaks Set format=format_",base64linebreaks" + Set sc=body.XMLExport(tag,format,namespaces,.attrs,,,,,,,mimeAttachments) + $$$XMLUseNext + } + } + If $$$ISERR(sc) Quit sc + + $$$XMLSetBuffer("") + $$$XMLWriteLine + } Else { + $$$XMLSetBuffer(" <"_..#SOAPPREFIX_":Body>") + $$$XMLWriteLine + } + $$$SOAPTimer(%SOAPTimerChar_"wbody") + + If mimeAttachments'="" $$$XMLSetTerminator($c(13,10)) + Do ..EndSOAPEnvelope() + If mimeAttachments'="" $$$XMLSetDefaultTerminator + + Quit $$$OK +]]> + + + +
+ +prefix is the optional preferred prefix for this namespace. +If no prefix is specified, a unique prefix will be computed.

+ +A schemaLocation attribute value for the first definition +of this namespace may also specified.

+ +If allowMultiplePrefixes is true then multiple prefixes may be defined for the same namespace. +The default is false which will override the previously defined prefix for the same namespace.]]>
+namespace:%String,prefix:%String,schemaLocation:%String,allowMultiplePrefixes:%Boolean +%Status + +
+ + + +1 + +1 +") $$$XMLWriteLine + $$$XMLSetBuffer("<"_..#SOAPPREFIX_":Envelope xmlns:"_..#SOAPPREFIX_"='"_soapns_"'") + $$$XMLAppendBuffer(" xmlns:xsi='"_$$$XSIns_"'") + $$$XMLAppendBuffer(" xmlns:s='"_$$$XSDns_"'") + If bodyUse="encoded" { + Set soapenc=$select(..SoapVersion="1.2":$$$SOAP12ENCns,1:$$$SOAPENCns) + $$$XMLAppendBuffer(" xmlns:SOAP-ENC='"_soapenc_"'") + Do namespaces.AddNamespace(soapenc,"SOAP-ENC") + } + If (bindingStyle="rpc") && (namespace'=typeNamespace) Set forcePrefix=1 + If forcePrefix || (bindingStyle="rpc"),namespaces.GetPrefix(namespace)="" { + $$$XMLAppendBuffer(" xmlns:tns='"_namespace_"'") + Do namespaces.AddNamespace(namespace,"tns") + } + If forcePrefix || (bodyUse="encoded") || + ((bindingStyle="document")&&('elementQualified||attributeQualified)&&(typeNamespace'="")), + namespaces.GetPrefix(typeNamespace)="" { + $$$XMLAppendBuffer(" xmlns:types='"_typeNamespace_"'") + Do namespaces.AddNamespace(typeNamespace,"types") + } + If ..AddressingOut'="" { + Set addrNamespace=..AddressingOut.Namespace() + $$$XMLAppendBuffer(" xmlns:wsa='"_addrNamespace_"'") + Do namespaces.AddNamespace(addrNamespace,"wsa") + } + If $isobject(r%SecurityOut) && (r%SecurityOut.SecurityElement.Count()>0) { + $$$XMLAppendBuffer(" xmlns:wsse='"_$$$SOAPWSSEns_"'") + Do namespaces.AddNamespace($$$SOAPWSSEns,"wsse") + $$$XMLAppendBuffer(" xmlns:wsu='"_$$$SOAPWSUns_"'") + Do namespaces.AddNamespace($$$SOAPWSUns,"wsu") + } ElseIf namespace=$$$SOAPWSTNS { + $$$XMLAppendBuffer(" xmlns:wsu='"_$$$SOAPWSUns_"'") + Do namespaces.AddNamespace($$$SOAPWSUns,"wsu") + } + Set ns="" + For { + Set ns=namespaces.GetNextDefinedNamespace(ns) + If ns="" Quit + $$$XMLAppendBuffer(" xmlns:"_namespaces.GetPrefix(ns)_"='"_ns_"'") + } + $$$XMLAppendBuffer(">") + $$$XMLWriteLine + Do namespaces.DefineAllNamespacePrefixes() + Set namespaces.CurrentNamespace="" + Set namespaces.DefaultNamespace=typeNamespace + Set namespaces.ElementQualified=elementQualified + Quit $$$OK +]]> + + + + +1 +1 +1 +") + $$$XMLWriteLine +]]> + + + + +1 +bodyUse:%String,namespaces:%XML.Namespaces,mimeAttachments:%Net.MIMEPart +%Status +1 +") + $$$XMLWriteLine + $$$XMLUseNext + While header'="" { + Set typeNamespace=..#TYPENAMESPACE + If typeNamespace="" Set typeNamespace=..#NAMESPACE + Set headerObj=..HeadersOut.GetAt(header) + Set fmt=bodyUse + If ..ReferencesInline Set fmt=fmt_",inline" + If ..Base64LineBreaks Set fmt=fmt_",base64linebreaks" + Set sc=headerObj.WriteHeader(,fmt,typeNamespace,..#ELEMENTQUALIFIED,..#SOAPPREFIX,..SoapVersion,namespaces,mimeAttachments) + If $$$ISERR(sc) Quit + $$$XMLUseNext + Set header=..HeadersOut.Next(header) + } + + // Write WS-Addressing headers + If ..AddressingOut'="" { + Set sc=..AddressingOut.WriteSOAPHeaders(namespaces,..#SOAPPREFIX,..SoapVersion) + If $$$ISERR(sc) Quit sc + } + + // Write WS-Security header + If security { + Set sc=r%SecurityOut.WriteSecurityHeader(namespaces,..#SOAPPREFIX,..SoapVersion,mimeAttachments) + If $$$ISERR(sc) Quit sc + $$$XMLUseNext + } + + $$$XMLSetBuffer(" ") + $$$XMLWriteLine + + Quit sc +]]> + + + + +Determine if any security processing is required and initialize. +1 +*sc:%Status +%Boolean +1 + + + + + +Reset any security headers +1 +1 + + + + + +Error check the SOAP envelope and find the message element. +If all is OK, status of $$$OK is returned and message is set to the index of message node. +1 +1 + +%Status +1 + + + + + +Process the SOAP envelope. +1 +1 + +%Status +1 + + + + + +1 +1 + +1 +%Status +1 + + + + + +1 +1 + +1 +%Boolean +1 + + + + + +1 +1 +objectgenerator +1 +") + Quit + } + + #; SOAP 1.2 rpc:result element. + #; Note that even if the service is specified as SOAP 1.1, + #; it will respond to a SOAP 1.2 request. + If tBindingStyle="rpc" { + If tServiceClass { + Set tXMLIO="OUT" + If elementref=0 { + Set initval=$get(tReturnArgs(1,2,"XMLNAME")) + } Else { + Set initval="""types:"_$extract($get(tReturnArgs(1,2,"XMLNAME")),2,*) + } + } Else { + Set tXMLIO="IN" + Set initval="" + } + Kill propParms + Set propParms("MAXLEN")="" + Set propParms("XMLNAME")="result" + Set propParms("XMLPROJECTION")="XELEMENT" + Set ref=$lb($$$SOAP12RPC,1) + Set sc=$$CreateProperty(tClassDef,tClassDefName,"%result12","%Library.String","",.propParms,.propseq,tXMLIO,initval,0,ref) + } + + #; Create the result property + Set required=$get(tReturnArgs(1,2,"REQUIRED")) + Set sc=$$Argument(.tReturnArgs,1,tServiceClass,elementref,$select(tServiceClass:(required=""),1:''required)) + If $$$ISERR(sc) Quit + } + + #; Initialize for building parameter lists. + Set (tMarshall,tParams,tOutParams,tResetParams)="" + + #; Generate the properties corresponding to each argument + For tP=1:1:tFormalArgs { + Set sc=$$Argument(.tFormalArgs,tP,tServiceClass,elementref,0) + If $$$ISERR(sc) Quit + + #; Build parameter lists. + If tServiceClass { + Set tParams=tParams_"."_tName_"," + } Else { + If $extract(tName)="%" Set sc=$$$ERROR($$$SOAPClientNoPercent,tName) Quit + If tXMLIO["OUT" { + Set tMarshall=tMarshall_".."_tName_"=$get("_tName_")," + } + If tXMLIO["IN" { + Set tOutParams=tOutParams_tName_"=.."_tName_"," + } + If tXMLIO="INOUT" { + Set tResetParams=tResetParams_".."_tName_"=""""," + } + } + } + If $$$ISERR(sc) Quit + +#define wl(%line) Do tMethodDef.Implementation.WriteLine(%line) + + #; If Web Client, create the Invoke and Reset methods + Set seqNumber=0 + If 'tServiceClass { + Set $Extract(tMarshall,$Length(tMarshall))="" + Set $Extract(tOutParams,$Length(tOutParams))="" + Set $Extract(tResetParams,$Length(tResetParams))="" + Set tMethodDef=##class(%Dictionary.MethodDefinition).%New(tClassDefName_":Invoke") + If tMethodDef="" Set sc=$$$ERROR($$$CannotCreateObject,"%Dictionary.MethodDefinition") Quit + Set tMethodDef.ServerOnly=1 + Set tMethodDef.FormalSpec=$select(tClassMethod:"",1:"%Client,")_ + "%Action"_ + $select(tFormalSpec="":"",1:","_tFormalSpec)_ + $select(tClassMethod:",%Location",1:"") + If tReturnType'="" { + Set tMethodDef.ReturnType=tReturnType + Set tMethodDef.ReturnTypeParams=tReturnTypeParams + } + If tMarshall'="" $$$wl(" Set "_tMarshall) + If tClassMethod { + $$$wl(" New %Client Set %Client=##class("_%class_").%New()") + $$$wl(" If $get(%Location)'="""" Set %Client.Location=%Location") + } + $$$wl(" Do %Client.InvokeClient($this,"""_tMethod_""",%Action"_$select(SoapOneWay:",1",1:"")_")") + If tOutParams'="" $$$wl(" Set "_tOutParams) + If tReturnType'="" { + $$$wl(" Quit .."_tResultName) + } Else { + $$$wl(" Quit") + } + Set tMethodDef.SequenceNumber=$increment(seqNumber) + Set sc=tClassDef.Methods.Insert(tMethodDef) + If $$$ISERR(sc) Quit + + Set tMethodDef=##class(%Dictionary.MethodDefinition).%New(tClassDefName_":Reset") + If tMethodDef="" Set sc=$$$ERROR($$$CannotCreateObject,"%Dictionary.MethodDefinition") Quit + Set tMethodDef.ServerOnly=1 + Set tMethodDef.FormalSpec="" + Set tMethodDef.ReturnType="" + If tResetParams'="" $$$wl(" Set "_tResetParams) + $$$wl(" Quit") + Set tMethodDef.SequenceNumber=$increment(seqNumber) + Set sc=tClassDef.Methods.Insert(tMethodDef) + If $$$ISERR(sc) Quit + } + + #; If Query, create the method to return the associated dataset + If tIsQuery(tI) { + Set $Extract(tParams,$Length(tParams))="" + Set tMethodDef=##class(%Dictionary.MethodDefinition).%New(tClassDefName_":"_tMethod) + If tMethodDef=$$$NULLOREF Set sc=$$$ERROR($$$CannotCreateObject,"%Dictionary.MethodDefinition") Quit + Set tMethodDef.ProcedureBlock=1 + Set tMethodDef.ClassMethod=1 + Set tMethodDef.FormalSpec=tFormalSpec + Set tMethodDef.ReturnType=tClassDefName_".DS" + $$$wl(" Set result=##class("_tClassDefName_".DS).%New()") + $$$wl(" Do result.SetArgs("_tParams_")") + $$$wl(" Quit result") + Set tMethodDef.SequenceNumber=$increment(seqNumber) + Set sc=tClassDef.Methods.Insert(tMethodDef) + If $$$ISERR(sc) Quit + } + + #; Create the Parameters + If tBindingStyle="rpc" { + Set sc=$$CreateParameter(tClassDef,tClassDefName,"ELEMENTQUALIFIED",0) + If $$$ISERR(sc) Quit + } ElseIf elementqualified'="" { + Set sc=$$CreateParameter(tClassDef,tClassDefName,"ELEMENTQUALIFIED",elementqualified) + If $$$ISERR(sc) Quit + } + + Set tPValue=$select(tBindingStyle="rpc":tMethodExportNamespace,1:tMethodExportTypeNamespace) + Set sc=$$CreateParameter(tClassDef,tClassDefName,"NAMESPACE",tPValue) + If $$$ISERR(sc) Quit + + Set sc=$$CreateParameter(tClassDef,tClassDefName,"SOAPBINDINGSTYLE",tBindingStyle) + If $$$ISERR(sc) Quit + + Set sc=$$CreateParameter(tClassDef,tClassDefName,"SOAPBODYUSE",tBodyUse(tI)) + If $$$ISERR(sc) Quit + + If tIsQuery(tI) { + #; Method will be in descriptor class for queries + Set sc=$$CreateParameter(tClassDef,tClassDefName,"SOAPCLASSNAME",tClassDefName) + If $$$ISERR(sc) Quit + } + + If SoapOneWay { + Set sc=$$CreateParameter(tClassDef,tClassDefName,"SOAPONEWAY",1) + If $$$ISERR(sc) Quit + } + + Set sc=$$CreateParameter(tClassDef,tClassDefName,"SUPPRESSDOCUMENTATION",1) + If $$$ISERR(sc) Quit + + Set sc=$$CreateParameter(tClassDef,tClassDefName,"TYPENAMESPACE",tTypeNamespace) + If $$$ISERR(sc) Quit + + Set sc=$$CreateParameter(tClassDef,tClassDefName,"XMLDEFAULTREFERENCE",tXMLDefaultReference) + If $$$ISERR(sc) Quit + + If classElement'="" { + Set sc=$$CreateParameter(tClassDef,tClassDefName,"XMLELEMENT",classElement) + If $$$ISERR(sc) Quit + } + + If tXMLIgnoreInvalidTag { + Set sc=$$CreateParameter(tClassDef,tClassDefName,"XMLIGNOREINVALIDTAG",tXMLIgnoreInvalidTag) + If $$$ISERR(sc) Quit + } + + If tXMLIgnoreNull'="" { + Set sc=$$CreateParameter(tClassDef,tClassDefName,"XMLIGNORENULL",tXMLIgnoreNull) + If $$$ISERR(sc) Quit + } + + Set tPValue=$select(tBindingStyle="rpc":tMethodImportNamespace,1:tMethodImportTypeNamespace) + Set sc=$$CreateParameter(tClassDef,tClassDefName,"XMLIMPORTNAMESPACE",tPValue) + If $$$ISERR(sc) Quit + + If bare { + Set sc=$$CreateParameter(tClassDef,tClassDefName,"XMLMAPPING","sequence") + If $$$ISERR(sc) Quit + } + + Set sc=$$CreateParameter(tClassDef,tClassDefName,"XMLRESULTNAME",tResultName) + If $$$ISERR(sc) Quit + + #; Mark this class for deletion when the web class is deleted. + Set tClassDef.GeneratedBy=%class_".cls" + + Set sc = tClassDef.%Save() If $$$ISERR(sc) Quit + + #; Now queue the generated class for compilation + Do QueueClass^%occCompile(tClassDefName) + $$$comClassArraySet(%class,$$$cCLASSclasses,tClassDefName_".CLS","") + + #; If Query, create dataset class + If tIsQuery(tI) { + Set tClassDefName=tClassDefName_".DS" + + #; Delete any pre-existing definition + If $$$defClassDefined(tClassDefName) { + Set sc=$$Delete^%apiOBJ(tClassDefName,"-d") If $$$ISERR(sc) Quit + } + + Set tClassDef=##class(%Dictionary.ClassDefinition).%New(tClassDefName) + If tClassDef=$$$NULLOREF Set sc=$$$ERROR($$$CannotCreateObject,"%Dictionary.ClassDefinition") Quit + Set tClassDef.Super="%XML.DataSet" + If tClassHidden Set tClassDef.Hidden=1 + #; Force ClassVersion to 25 since LegacyInstanceContext is not needed + Set tClassDef.ClassVersion=25 + Set seqNumber=0 + + Set sc=$$CreateParameter(tClassDef,tClassDefName,"CLASSNAME",%class) + If $$$ISERR(sc) Quit + + Set tPValue=tTypeNamespace + If $extract(tPValue,$length(tPValue))'="/" Set tPValue=tPValue_"/" + Set tPValue=tPValue_tMethod_"_DataSet" + Set sc=$$CreateParameter(tClassDef,tClassDefName,"NAMESPACE",tPValue) + If $$$ISERR(sc) Quit + + Set sc=$$CreateParameter(tClassDef,tClassDefName,"QUERYNAME",tMethod) + If $$$ISERR(sc) Quit + + If tXMLIgnoreNull'="" { + Set sc=$$CreateParameter(tClassDef,tClassDefName,"XMLIGNORENULL",tXMLIgnoreNull) + If $$$ISERR(sc) Quit + } + + Set sc=$$CreateParameter(tClassDef,tClassDefName,"XMLNAME",tMethod_"_DataSet") + If $$$ISERR(sc) Quit + + Set sc=$$CreateParameter(tClassDef,tClassDefName,"XMLTYPE",tMethod_"_DataSet") + If $$$ISERR(sc) Quit + + #; Mark this class for deletion when the web class is deleted. + Set tClassDef.GeneratedBy=%class_".cls" + + Set sc = tClassDef.%Save() If $$$ISERR(sc) Quit + + #; Now queue the generated class for compilation + Do QueueClass^%occCompile(tClassDefName) + $$$comClassArraySet(%class,$$$cCLASSclasses,tClassDefName_".CLS","") + } + } + + #; Parse and save parameters XData block + #; Also save parameter indices produced in this method + If $$$ISOK(sc) { + Set sc=##class(%SOAP.WebParameters).ParseParameters(%compiledclass,methodInheritance,.webMethodIndex,.soapActionIndex,.requestNameIndex,.parameters) + } + If $$$ISOK(sc) { + Merge $$$SOAPParametersNode(%class)=parameters + } + + Quit sc + +#; Create property for an argument from formap spec or return t +Argument(FormalArgs,index,ServiceClass,elementref,forceRequired) + #; Just use the unique part of the argument name + Set tName=$extract(FormalArgs(index),1,$$$MAXVARIABLELENGTH) + Set type=$get(FormalArgs(index,2)) + Set tCollection="" + Kill propParms + If type'="" { + Set normtype=$$$NormalizeClassname(type) + If (normtype="%Library.ListOfObjects") || (normtype="%Library.ListOfDataTypes") { + Set eltype=$get(FormalArgs(index,2,"ELEMENTTYPE")) + If eltype'="" { + Set type=$extract(eltype,2,*-1) + Kill FormalArgs(index,2,"ELEMENTTYPE") + Set tCollection="list" + } + } ElseIf (normtype="%Library.ArrayOfObjects") || (normtype="%Library.ArrayOfDataTypes") { + Set eltype=$get(FormalArgs(index,2,"ELEMENTTYPE")) + If eltype'="" { + Set type=$extract(eltype,2,*-1) + Kill FormalArgs(index,2,"ELEMENTTYPE") + Set tCollection="array" + } + } ElseIf (normtype="%Library.CharacterStream") { + Set type="%Library.GlobalCharacterStream" + } ElseIf (normtype="%Library.BinaryStream") { + Set type="%Library.GlobalBinaryStream" + } + Set sc=$$NormalizeClassnameByCom^%occName(.tType,type,%class) + If $$$ISERR(sc) Quit sc + } Else { + Set tType="%Library.String" + } + #; Set XMLIO parameter for property + If $get(FormalArgs(index,1))="&" { + Set tXMLIO="INOUT" + } ElseIf $get(FormalArgs(index,1))="*" { + Set tXMLIO=$select(ServiceClass:"OUT",1:"IN") + } Else { + Set tXMLIO=$select(ServiceClass:"IN",1:"OUT") + } + If forceRequired { + #; Return property of service is always required. + Set required=1 + } Else { + #; Process REQUIRED parameter for input arguments of web service + Set required=$get(FormalArgs(index,2,"REQUIRED")) + If required'="" { + Set required=''required + } + } + Kill FormalArgs(index,2,"REQUIRED") + #; Add MAXLEN="" for strings + Merge propParms=FormalArgs(index,2) + If ((tType="%Library.String") || (tType="%xsd.string")) && ('$data(propParms("MAXLEN"))) { + Set propParms("MAXLEN")="" + } + #; If property name shortened to < 31 characters, then add XMLNAME + If tName'=FormalArgs(index) { + Set propParms("XMLNAME")=FormalArgs(index) + } + #; Create a property for this argument of the specfied type + Set sc=$$CreateProperty(tClassDef,tClassDefName,tName,tType,tCollection,.propParms,.propseq,tXMLIO,"",required,elementref) + Quit sc + +#; Create a property for the specified name +CreateProperty(ClassDef, ClassDefName, Name, Type, Collection, propParms, propseq, XMLIO, InitialExpression, required, elementref) + Set PropDef=##class(%Dictionary.PropertyDefinition).%New(ClassDefName_":"_Name) + If PropDef=$$$NULLOREF Quit $$$ERROR($$$CannotCreateObject,"%Dictionary.PropertyDefinition") + Set PropDef.Type=Type + Set PropDef.Collection = Collection + Set PropDef.SequenceNumber=$increment(propseq) + If $get(InitialExpression)'="" Set PropDef.InitialExpression=InitialExpression + If $get(XMLIO)'="" Do PropDef.Parameters.SetAt(XMLIO,"XMLIO") + Set parm=$order(propParms("")) + While parm'="" { + Set value=propParms(parm) + If $extract(value)="""" Set value=$extract(value,2,*-1) + Do PropDef.Parameters.SetAt(value,parm) + Set parm=$order(propParms(parm)) + } + If (elementref'=0) && (PropDef.Parameters.GetAt("XMLREF")="") && (PropDef.Parameters.GetAt("XMLELEMENTREF")="") { + Do PropDef.Parameters.SetAt(1,"XMLREF") + If $list(elementref,1)="" { + Do PropDef.Parameters.RemoveAt("REFNAMESPACE") + } Else { + Do PropDef.Parameters.SetAt($list(elementref,1),"REFNAMESPACE") + } + If $list(elementref,2)="" { + Do PropDef.Parameters.RemoveAt("REFELEMENTQUALIFIED") + } Else { + Do PropDef.Parameters.SetAt($list(elementref,2),"REFELEMENTQUALIFIED") + } + } + If required'="" Set PropDef.Required=required + Quit ClassDef.Properties.Insert(PropDef) + +#; Create a parameter of the specified name with the specified value +CreateParameter(ClassDef, ClassDefName, PName, PValue) + Set ParamDef=##class(%Dictionary.ParameterDefinition).%New(ClassDefName_":"_PName) + If ParamDef=$$$NULLOREF Quit $$$ERROR($$$CannotCreateObject,"%Dictionary.ParameterDefinition") + Set ParamDef.SequenceNumber=$increment(seqNumber) + Set ParamDef.Default=PValue + Quit ClassDef.Parameters.Insert(ParamDef) +]]> + + + + +1 +1 +Operation:%String,RequestTag:%String +%SOAP.Descriptor +1 + + + + + +Normalize name to comply with Cache constraints +1 +pName,pMaxLen,isMethod:%Boolean +%String +1 +pMaxLen { + Set tVowelCount=0,tLen=$Length(pName) + For tI=tLen:-1:1 { + If "AEIOUaeiou"[$Extract(pName,tI) Set $Extract(pName,tI)="+",tVowelCount=tVowelCount+1 + If tLen-tVowelCount=pMaxLen Quit + } + } + Set pName=$Translate(pName,"+","") + + Quit $extract(pName,1,pMaxLen) +]]> + + + +1 +msgClass:%SOAP.Descriptor,isRequest:%Boolean,asUTF8:%Boolean,sessionFlag:%Boolean +%SOAP.Binary +1 + + + + +1 + +%Status +1 + + +
+ + +