Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch bug584bfb7727-abstract-type Excluding Merge-Ins
This is equivalent to a diff from 150950db68 to 300b2b5c3a
2018-05-28 11:16 | Add support to translate distant namespace prefixes in attribute values or text values to local correspondances, required for abstract types. Ticket [584bfb77]: client.tcl 2.5.1, utilities.tcl 2.4.2 check-in: e406ab9e21 user: oehhar tags: trunk | |
2018-05-14 14:52 | Add support to translate distant namespace prefixes in attribute values or text values to local correspondances, required for abstract types. Ticket [584bfb77]: client.tcl 2.5.1, utilities.tcl 2.4.2 Closed-Leaf check-in: 300b2b5c3a user: oehhar tags: bug584bfb7727-abstract-type | |
2018-02-20 21:31 | First step to parse complex abstract type in wsdl. Bug [584bfb7727] check-in: 6975d0e818 user: oehhar tags: bug584bfb7727-abstract-type | |
2018-02-20 14:20 | Reduce non logging log impact by only building log message when logging. Requires tcllib log package 1.4 or included emulation. Ticket [93ebedfa] check-in: 150950db68 user: oehhar tags: trunk | |
2018-01-08 17:37 | Set package version to release version 2.5.0 check-in: 53f12a2aa1 user: oehhar tags: trunk, Release_2.5.0 | |
Changes to ClientSide.tcl.
︙ | ︙ | |||
43 44 45 46 47 48 49 | package require Tcl 8.4 package require WS::Utils 2.4 ; # dict, lassign package require tdom 0.8 package require http 2 package require log package require uri | | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | package require Tcl 8.4 package require WS::Utils 2.4 ; # dict, lassign package require tdom 0.8 package require http 2 package require log package require uri package provide WS::Client 2.5.1 namespace eval ::WS::Client { # register https only if not yet registered if {[catch { http::unregister https } lPortCmd]} { # not registered -> register on my own if {[catch { package require tls |
︙ | ︙ | |||
339 340 341 342 343 344 345 | dict set serviceArr($serviceName) $item $options($item) } foreach {name value} $args { set name [string trimleft $name {-}] dict set serviceArr($serviceName) $name $value } | | | | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | dict set serviceArr($serviceName) $item $options($item) } foreach {name value} $args { set name [string trimleft $name {-}] dict set serviceArr($serviceName) $name $value } ::log::logsubst debug {Setting Target Namespace tns1 as $target} if {[dict exists $serviceArr($serviceName) xns]} { foreach xnsItem [dict get $serviceArr($serviceName) xns] { lassign $xnsItem tns xns ::log::logsubst debug {Setting targetNamespace $tns for $xns} dict set serviceArr($serviceName) targetNamespace $tns $xns } } } ########################################################################### # |
︙ | ︙ | |||
1153 1154 1155 1156 1157 1158 1159 | } array set argument $args set first [string first {<} $wsdlXML] if {$first > 0} { set wsdlXML [string range $wsdlXML $first end] } | | | 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 | } array set argument $args set first [string first {<} $wsdlXML] if {$first > 0} { set wsdlXML [string range $wsdlXML $first end] } ::log::logsubst debug {Parsing WSDL: $wsdlXML} # save parsed document node to tmpdoc dom parse $wsdlXML tmpdoc # save transformed document handle in variable wsdlDoc $tmpdoc xslt $::WS::Utils::xsltSchemaDom wsdlDoc $tmpdoc delete # save top node in variable wsdlNode |
︙ | ︙ | |||
1256 1257 1258 1259 1260 1261 1262 | ## different URL ## # This may happen, if the element namespace prefix overwrites # a global one, like # <wsdl:definitions xmlns:q1="URI1" ...> # <xs:element xmlns:q1="URI2" type="q1:MessageQ1"/> if { [dict exists $nsDict tns $ns] && $tns ne [dict get $nsDict tns $ns] } { | | | 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 | ## different URL ## # This may happen, if the element namespace prefix overwrites # a global one, like # <wsdl:definitions xmlns:q1="URI1" ...> # <xs:element xmlns:q1="URI2" type="q1:MessageQ1"/> if { [dict exists $nsDict tns $ns] && $tns ne [dict get $nsDict tns $ns] } { ::log::logsubst debug {Namespace prefix '$ns' with different URI '$url': $nsDict} return \ -code error \ -errorcode [list WS CLIENT AMBIGNSPREFIX] \ "element namespace prefix '$ns' used again for different URI '$url'.\ Sorry, this is a current implementation limitation of TCLWS." } dict set nsDict tns $ns $tns |
︙ | ︙ | |||
1385 1386 1387 1388 1389 1390 1391 | set inputMsgType [dict get $serviceInfo operation $operationName inputs] ## Petasis, 14 July 2008: If an input message has no elements, just do ## not add any arguments... set inputMsgTypeDefinition [::WS::Utils::GetServiceTypeDef Client $serviceName $inputMsgType] if {[dict exists $inputMsgTypeDefinition definition]} { set inputFields [dict keys [dict get $inputMsgTypeDefinition definition]] } else { | | | | 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 | set inputMsgType [dict get $serviceInfo operation $operationName inputs] ## Petasis, 14 July 2008: If an input message has no elements, just do ## not add any arguments... set inputMsgTypeDefinition [::WS::Utils::GetServiceTypeDef Client $serviceName $inputMsgType] if {[dict exists $inputMsgTypeDefinition definition]} { set inputFields [dict keys [dict get $inputMsgTypeDefinition definition]] } else { ::log::logsubst debug {no definition found for inputMsgType $inputMsgType} set inputFields {} } if {$inputFields ne {}} { lappend argList [lsort -dictionary $inputFields] } set argList [join $argList] set body { set procName [lindex [info level 0] 0] set serviceName [string trim [namespace qualifiers $procName] {:}] set operationName [string trim [namespace tail $procName] {:}] set argList {} foreach var [namespace eval ::${serviceName}:: [list info args $operationName]] { lappend argList $var [set $var] } ::log::logsubst debug {::WS::Client::DoCall $serviceName $operationName $argList} ::WS::Client::DoCall $serviceName $operationName $argList } proc $procName $argList $body append procList "\n\t[list $procName $argList]" } return "$procList\n" } |
︙ | ︙ | |||
1464 1465 1466 1467 1468 1469 1470 | # which also follows redirects. # # ########################################################################### proc ::WS::Client::DoRawCall {serviceName operationName argList {headers {}}} { variable serviceArr | | | 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 | # which also follows redirects. # # ########################################################################### proc ::WS::Client::DoRawCall {serviceName operationName argList {headers {}}} { variable serviceArr ::log::logsubst debug {Entering [info level 0]} if {![info exists serviceArr($serviceName)]} { return \ -code error \ -errorcode [list WS CLIENT UNKSRV $serviceName] \ "Unknown service '$serviceName'" } set serviceInfo $serviceArr($serviceName) |
︙ | ︙ | |||
1508 1509 1510 1511 1512 1513 1514 | if {[llength $headers]} { set body [::WS::Utils::geturl_fetchbody $url -query $query -type [dict get $serviceInfo contentType] -headers $headers] } else { set body [::WS::Utils::geturl_fetchbody $url -query $query -type [dict get $serviceInfo contentType]] } | | | 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 | if {[llength $headers]} { set body [::WS::Utils::geturl_fetchbody $url -query $query -type [dict get $serviceInfo contentType] -headers $headers] } else { set body [::WS::Utils::geturl_fetchbody $url -query $query -type [dict get $serviceInfo contentType]] } ::log::logsubst debug {Leaving ::WS::Client::DoRawCall with {$body}} return $body } ########################################################################### # # Public Procedure Header - as this procedure is modified, please be sure |
︙ | ︙ | |||
1568 1569 1570 1571 1572 1573 1574 | # redirects. # # ########################################################################### proc ::WS::Client::DoCall {serviceName operationName argList {headers {}}} { variable serviceArr | | | 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 | # redirects. # # ########################################################################### proc ::WS::Client::DoCall {serviceName operationName argList {headers {}}} { variable serviceArr ::log::logsubst debug {Entering [info level 0]} if {![info exists serviceArr($serviceName)]} { return \ -code error \ -errorcode [list WS CLIENT UNKSRV $serviceName] \ "Unknown service '$serviceName'" } set serviceInfo $serviceArr($serviceName) |
︙ | ︙ | |||
1629 1630 1631 1632 1633 1634 1635 | catch {set body [$outTransform $serviceName $operationName REPLY $body]} RestoreSavedOptions $serviceName } set hadError [catch {parseResults $serviceName $operationName $body} results] if {$hadError} { lassign $::errorCode mainError subError if {$mainError eq {WSCLIENT} && $subError eq {NOSOAP}} { | | | | | | 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 | catch {set body [$outTransform $serviceName $operationName REPLY $body]} RestoreSavedOptions $serviceName } set hadError [catch {parseResults $serviceName $operationName $body} results] if {$hadError} { lassign $::errorCode mainError subError if {$mainError eq {WSCLIENT} && $subError eq {NOSOAP}} { ::log::logsubst debug {\tHTTP error $body} set results $body set errorCode [list WSCLIENT HTTPERROR $body] set errorInfo {} } else { ::log::logsubst debug {Reply was $body} set errorCode $::errorCode set errorInfo $::errorInfo } } } else { if {$outTransform ne {}} { SaveAndSetOptions $serviceName catch {set body [$outTransform $serviceName $operationName REPLY $body]} RestoreSavedOptions $serviceName } SaveAndSetOptions $serviceName set hadError [catch {parseResults $serviceName $operationName $body} results] RestoreSavedOptions $serviceName if {$hadError} { ::log::logsubst debug {Reply was $body} set errorCode $::errorCode set errorInfo $::errorInfo } } if {$hadError} { ::log::log debug "Leaving (error) ::WS::Client::DoCall" return \ -code error \ -errorcode $errorCode \ -errorinfo $errorInfo \ $results } else { ::log::logsubst debug {Leaving ::WS::Client::DoCall with {$results}} return $results } } ########################################################################### # |
︙ | ︙ | |||
1775 1776 1777 1778 1779 1780 1781 | # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::DoAsyncCall {serviceName operationName argList succesCmd errorCmd {headers {}}} { variable serviceArr | | | 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 | # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::DoAsyncCall {serviceName operationName argList succesCmd errorCmd {headers {}}} { variable serviceArr ::log::logsubst debug {Entering [info level 0]} if {![info exists serviceArr($serviceName)]} { return \ -code error \ -errorcode [list WS CLIENT UNKSRV $serviceName] \ "Unknown service '$serviceName'" } set serviceInfo $serviceArr($serviceName) |
︙ | ︙ | |||
1801 1802 1803 1804 1805 1806 1807 | if {[catch {set query [buildCallquery $serviceName $operationName $url $argList]} err]} { RestoreSavedOptions $serviceName return -code error -errorcode $::errorCode -errorinfo $::errorInfo $err } else { RestoreSavedOptions $serviceName } if {[llength $headers]} { | < | | < < | | < | | 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 | if {[catch {set query [buildCallquery $serviceName $operationName $url $argList]} err]} { RestoreSavedOptions $serviceName return -code error -errorcode $::errorCode -errorinfo $::errorInfo $err } else { RestoreSavedOptions $serviceName } if {[llength $headers]} { ::log::logsubst info {::http::geturl $url \ -query $query \ -type [dict get $serviceInfo contentType] \ -headers $headers \ -command [list ::WS::Client::asyncCallDone $serviceName $operationName $succesCmd $errorCmd]} ::http::geturl $url \ -query $query \ -type [dict get $serviceInfo contentType] \ -headers $headers \ -command [list ::WS::Client::asyncCallDone $serviceName $operationName $succesCmd $errorCmd] } else { ::log::logsubst info {::http::geturl $url \ -query $query \ -type [dict get $serviceInfo contentType] \ -command [list ::WS::Client::asyncCallDone $serviceName $operationName $succesCmd $errorCmd]} ::http::geturl $url \ -query $query \ -type [dict get $serviceInfo contentType] \ -command [list ::WS::Client::asyncCallDone $serviceName $operationName $succesCmd $errorCmd] } ::log::logsubst debug {Leaving ::WS::Client::DoAsyncCall} return; } ########################################################################### # # Public Procedure Header - as this procedure is modified, please be sure # that you update this header block. Thanks. |
︙ | ︙ | |||
2042 2043 2044 2045 2046 2047 2048 | # Version Date Programmer Comments / Changes / Reasons # ------- ---------- ---------- ------------------------------------------- # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::asyncCallDone {serviceName operationName succesCmd errorCmd token} { | | | | 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 | # Version Date Programmer Comments / Changes / Reasons # ------- ---------- ---------- ------------------------------------------- # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::asyncCallDone {serviceName operationName succesCmd errorCmd token} { ::log::logsubst debug {Entering [info level 0]} ## ## Check for errors ## set body [::http::data $token] ::log::logsubst info {\nReceived: $body} set results {} if {[::http::status $token] ne {ok} || ( [::http::ncode $token] != 200 && $body eq {} )} { set errorCode [list WS CLIENT HTTPERROR [::http::code $token]] set hadError 1 set errorInfo [FormatHTTPError $token] } else { |
︙ | ︙ | |||
2134 2135 2136 2137 2138 2139 2140 | # ------- ---------- ---------- ------------------------------------------- # 1 07/06/2006 G.Lester Initial version # 2.4.2 2017-08-31 H.Oehlmann The response node name may also be the # output name and not only the output type. # (ticket [21f41e22bc]). # 2.4.3 2017-11-03 H.Oehlmann Extended upper commit also to search # for multiple child nodes. | | > > > > | > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 | # ------- ---------- ---------- ------------------------------------------- # 1 07/06/2006 G.Lester Initial version # 2.4.2 2017-08-31 H.Oehlmann The response node name may also be the # output name and not only the output type. # (ticket [21f41e22bc]). # 2.4.3 2017-11-03 H.Oehlmann Extended upper commit also to search # for multiple child nodes. # 2.5.1 2018-05-14 H.Oehlmann Add support to translate namespace prefixes # in attribute values or text values. # Translation dict "xnsDistantToLocalDict" is # passed to ::WS::Utils::convertTypeToDict # to translate abstract types. # ########################################################################### proc ::WS::Client::parseResults {serviceName operationName inXML} { variable serviceArr ::log::logsubst debug {Entering [info level 0]} set serviceInfo $serviceArr($serviceName) set expectedMsgType [dict get $serviceInfo operation $operationName outputs] set expectedMsgTypeBase [lindex [split $expectedMsgType {:}] end] set first [string first {<} $inXML] if {$first > 0} { set inXML [string range $inXML $first end] } # parse xml and save handle in variable doc and free it when out of scope dom parse $inXML doc # save top node handle in variable top and free it if out of scope $doc documentElement top set xns { ENV http://schemas.xmlsoap.org/soap/envelope/ xsi "http://www.w3.org/2001/XMLSchema-instance" xs "http://www.w3.org/2001/XMLSchema" } foreach {prefixCur URICur} [dict get $serviceInfo targetNamespace] { lappend xns $prefixCur $URICur } ::log::logsubst debug {Using namespaces {$xns}} $doc selectNodesNamespaces $xns ## ## When arguments with tags are passed (example: abstract types), ## the upper "selectNodesNamespaces translation must be executed manually. ## Thus, we need a list of server namespace prefixes to our client namespace ## prefixes. (bug 584bfb77) ## # Example xml: # <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" # xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" # xmlns:xsd="http://www.w3.org/2001/XMLSchema" # xmlns:tns="http://www.esri.com/schemas/ArcGIS/10.3"> set xnsDistantToLocalDict {} foreach attributeCur [$top attributes] { # attributeCur is a list of "prefix local URI", # which is for xmlns tags: "prefix prefix {}". set attributeCur [lindex $attributeCur 0] # Check if this is a namespace prefix if { ! [$top hasAttribute "xmlns:$attributeCur"] } {continue} set URIServer [$top getAttribute "xmlns:$attributeCur"] # Check if it is included in xns foreach {prefixCur URICur} $xns { if {$URIServer eq $URICur} { dict set xnsDistantToLocalDict $attributeCur $prefixCur break } } } ::log::logsubst debug {Server to Client prefix dict: $xnsDistantToLocalDict} ## ## Get body tag ## set body [$top selectNodes ENV:Body] if {![llength $body]} { return \ -code error \ -errorcode [list WS CLIENT BADREPLY $inXML] \ "Bad reply type, no SOAP envelope received in: \n$inXML" } |
︙ | ︙ | |||
2221 2222 2223 2224 2225 2226 2227 | # This is not the case, if it was parsed with tclws prior 2.4.2 # *** ToDo *** This security may be removed on a major release if {[dict exists $serviceInfo operation $operationName outputsname]} { lappend nodeNameCandidateList [dict get $serviceInfo operation $operationName outputsname] } set rootNodeList [$body childNodes] | | | | | 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 | # This is not the case, if it was parsed with tclws prior 2.4.2 # *** ToDo *** This security may be removed on a major release if {[dict exists $serviceInfo operation $operationName outputsname]} { lappend nodeNameCandidateList [dict get $serviceInfo operation $operationName outputsname] } set rootNodeList [$body childNodes] ::log::logsubst debug {Have [llength $rootNodeList] node under Body} foreach rootNodeCur $rootNodeList { set rootNameCur [$rootNodeCur localName] if {$rootNameCur eq {}} { set rootNameCur [$rootNodeCur nodeName] } if {$rootNameCur in $nodeNameCandidateList} { set rootNode $rootNodeCur set rootName $rootNameCur ::log::logsubst debug {Result root name is '$rootName'} break } ::log::logsubst debug {Result root name '$rootNameCur' not in candidates '$nodeNameCandidateList'} } ## ## Exit if there is no such node ## if {![info exists rootName]} { return \ -code error \ |
︙ | ︙ | |||
2294 2295 2296 2297 2298 2299 2300 | continue } } #if {[llength $outHeaderAttrs]} { # ::WS::Utils::setAttr $node $outHeaderAttrs #} | | | < > > > > | | | | 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 | continue } } #if {[llength $outHeaderAttrs]} { # ::WS::Utils::setAttr $node $outHeaderAttrs #} ::log::logsubst debug {Calling convertTypeToDict from header node type '$outHeaderType'} lappend results [::WS::Utils::convertTypeToDict Client $serviceName $node $outHeaderType $headerRootNode 0 $xnsDistantToLocalDict] } } ## ## Call Utility function to build result list ## if {$rootName ne {}} { ::log::log debug "Calling convertTypeToDict with root node" set bodyData [::WS::Utils::convertTypeToDict \ Client $serviceName $rootNode $expectedMsgType $body 0 $xnsDistantToLocalDict] if {![llength $bodyData] && ([dict get $serviceInfo skipLevelWhenActionPresent] || [dict get $serviceInfo skipLevelOnReply])} { ::log::log debug "Calling convertTypeToDict with skipped action level (skipLevelWhenActionPresent was set)" set bodyData [::WS::Utils::convertTypeToDict \ Client $serviceName $body $expectedMsgType $body 0 $xnsDistantToLocalDict] } lappend results $bodyData } set results [join $results] $doc delete set ::errorCode {} set ::errorInfo {} |
︙ | ︙ | |||
2391 2392 2393 2394 2395 2396 2397 | ::WS::Utils::SetOption suppressNS $inSuppressNs set inTransform [dict get $serviceInfo inTransform] if {$inTransform ne {}} { set xml [$inTransform $serviceName $operationName REQUEST $xml $url $argList] } | | | 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 | ::WS::Utils::SetOption suppressNS $inSuppressNs set inTransform [dict get $serviceInfo inTransform] if {$inTransform ne {}} { set xml [$inTransform $serviceName $operationName REQUEST $xml $url $argList] } ::log::logsubst debug {Leaving ::WS::Client::buildCallquery with {$xml}} return $xml } ########################################################################### # # Private Procedure Header - as this procedure is modified, please be sure |
︙ | ︙ | |||
2439 2440 2441 2442 2443 2444 2445 | # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::buildDocLiteralCallquery {serviceName operationName url argList} { variable serviceArr | | | 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 | # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::buildDocLiteralCallquery {serviceName operationName url argList} { variable serviceArr ::log::logsubst debug {Entering [info level 0]} set serviceInfo $serviceArr($serviceName) set msgType [dict get $serviceInfo operation $operationName inputs] set url [dict get $serviceInfo location] set xnsList [dict get $serviceInfo targetNamespace] # save the document in variable doc and free it if out of scope dom createDocument "SOAP-ENV:Envelope" doc |
︙ | ︙ | |||
2522 2523 2524 2525 2526 2527 2528 | set msgType [lindex $typeInfo 1] } if {[dict get $serviceInfo skipLevelWhenActionPresent] && [dict exists $serviceInfo operation $operationName action]} { set forceNs 1 set reply $bod } else { | | | | 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 | set msgType [lindex $typeInfo 1] } if {[dict get $serviceInfo skipLevelWhenActionPresent] && [dict exists $serviceInfo operation $operationName action]} { set forceNs 1 set reply $bod } else { ::log::logsubst debug {$bod appendChild \[$doc createElement $xns:$msgType reply\]} $bod appendChild [$doc createElement $xns:$msgType reply] set forceNs 0 } ::WS::Utils::convertDictToType Client $serviceName $doc $reply $argList $xns:$msgType $forceNs set encoding [lindex [split [lindex [split [dict get $serviceInfo contentType] {:}] end] {=}] end] set xml [format {<?xml version="1.0" encoding="%s"?>} $encoding] append xml "\n" [$doc asXML -indent none -doctypeDeclaration 0] $doc delete ::log::logsubst debug {Leaving ::WS::Client::buildDocLiteralCallquery with {$xml}} return [encoding convertto $encoding $xml] } ########################################################################### # |
︙ | ︙ | |||
2583 2584 2585 2586 2587 2588 2589 | # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::buildRpcEncodedCallquery {serviceName operationName url argList} { variable serviceArr | | | 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 | # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::buildRpcEncodedCallquery {serviceName operationName url argList} { variable serviceArr ::log::logsubst debug {Entering [info level 0]} set serviceInfo $serviceArr($serviceName) set msgType [dict get $serviceInfo operation $operationName inputs] set xnsList [dict get $serviceInfo targetNamespace] dom createDocument "SOAP-ENV:Envelope" doc $doc documentElement env $env setAttribute \ |
︙ | ︙ | |||
2632 2633 2634 2635 2636 2637 2638 | ::WS::Utils::convertDictToEncodedType Client $serviceName $doc $reply $argList $msgType set encoding [lindex [split [lindex [split [dict get $serviceInfo contentType] {;}] end] {=}] end] set xml [format {<?xml version="1.0" encoding="%s"?>} $encoding] append xml "\n" [$doc asXML -indent none -doctypeDeclaration 0] $doc delete | | | 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 | ::WS::Utils::convertDictToEncodedType Client $serviceName $doc $reply $argList $msgType set encoding [lindex [split [lindex [split [dict get $serviceInfo contentType] {;}] end] {=}] end] set xml [format {<?xml version="1.0" encoding="%s"?>} $encoding] append xml "\n" [$doc asXML -indent none -doctypeDeclaration 0] $doc delete ::log::logsubst debug {Leaving ::WS::Client::buildRpcEncodedCallquery with {$xml}} return [encoding convertto $encoding $xml] } ########################################################################### # |
︙ | ︙ | |||
2687 2688 2689 2690 2691 2692 2693 | # ########################################################################### proc ::WS::Client::buildServiceInfo {wsdlNode tnsDict {serviceInfo {}} {serviceAlias {}} {serviceNumber 1}} { ## ## Need to refactor to foreach service parseService ## Service drills down to ports, which drills down to bindings and messages ## | | | 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 | # ########################################################################### proc ::WS::Client::buildServiceInfo {wsdlNode tnsDict {serviceInfo {}} {serviceAlias {}} {serviceNumber 1}} { ## ## Need to refactor to foreach service parseService ## Service drills down to ports, which drills down to bindings and messages ## ::log::logsubst debug {Entering [info level 0]} ## ## Parse Service information ## # WSDL snippet: # <definitions ...> # <service name="service1"> |
︙ | ︙ | |||
2727 2728 2729 2730 2731 2732 2733 | set serviceNameList [lrange $serviceNameList $serviceNumber-1 $serviceNumber-1] } foreach serviceNode $serviceNameList { lappend serviceInfo [parseService $wsdlNode $serviceNode $serviceAlias $tnsDict] } | | | 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 | set serviceNameList [lrange $serviceNameList $serviceNumber-1 $serviceNumber-1] } foreach serviceNode $serviceNameList { lappend serviceInfo [parseService $wsdlNode $serviceNode $serviceAlias $tnsDict] } ::log::logsubst debug {Leaving ::WS::Client::buildServiceInfo with $serviceInfo} return $serviceInfo } ########################################################################### # # Private Procedure Header - as this procedure is modified, please be sure # that you update this header block. Thanks. |
︙ | ︙ | |||
2776 2777 2778 2779 2780 2781 2782 | # # ########################################################################### proc ::WS::Client::parseService {wsdlNode serviceNode serviceAlias tnsDict} { variable serviceArr variable options | | | 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 | # # ########################################################################### proc ::WS::Client::parseService {wsdlNode serviceNode serviceAlias tnsDict} { variable serviceArr variable options ::log::logsubst debug {Entering [info level 0]} if {[string length $serviceAlias]} { set serviceName $serviceAlias } else { set serviceName [$serviceNode getAttribute name] } set addressNodeList [$serviceNode getElementsByTagNameNS http://schemas.xmlsoap.org/wsdl/soap/ address] if {[llength $addressNodeList] == 1} { |
︙ | ︙ | |||
2841 2842 2843 2844 2845 2846 2847 | foreach {key value} [dict get $serviceInfo tnsList url] { dict set serviceInfo targetNamespace $value $key } set serviceArr($serviceName) $serviceInfo set ::WS::Utils::targetNs $tmpTargetNs | | | 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 | foreach {key value} [dict get $serviceInfo tnsList url] { dict set serviceInfo targetNamespace $value $key } set serviceArr($serviceName) $serviceInfo set ::WS::Utils::targetNs $tmpTargetNs ::log::logsubst debug {Leaving [lindex [info level 0] 0] with $serviceInfo} return $serviceInfo } ########################################################################### # # Private Procedure Header - as this procedure is modified, please be sure # that you update this header block. Thanks. |
︙ | ︙ | |||
3440 3441 3442 3443 3444 3445 3446 | # which also follows redirects. # # ########################################################################### proc ::WS::Client::DoRawRestCall {serviceName objectName operationName argList {headers {}} {location {}}} { variable serviceArr | | | 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 | # which also follows redirects. # # ########################################################################### proc ::WS::Client::DoRawRestCall {serviceName objectName operationName argList {headers {}} {location {}}} { variable serviceArr ::log::logsubst debug {Entering [info level 0]} if {![info exists serviceArr($serviceName)]} { return \ -code error \ -errorcode [list WS CLIENT UNKSRV $serviceName] \ "Unknown service '$serviceName'" } set serviceInfo $serviceArr($serviceName) |
︙ | ︙ | |||
3491 3492 3493 3494 3495 3496 3497 | if {[llength $headers]} { set body [::WS::Utils::geturl_fetchbody $url -query $query -type [dict get $serviceInfo contentType] -headers $headers] } else { set body [::WS::Utils::geturl_fetchbody $url -query $query -type [dict get $serviceInfo contentType]] } | | | 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 | if {[llength $headers]} { set body [::WS::Utils::geturl_fetchbody $url -query $query -type [dict get $serviceInfo contentType] -headers $headers] } else { set body [::WS::Utils::geturl_fetchbody $url -query $query -type [dict get $serviceInfo contentType]] } ::log::logsubst debug {Leaving ::WS::Client::DoRawRestCall with {$body}} return $body } ########################################################################### # # Public Procedure Header - as this procedure is modified, please be sure |
︙ | ︙ | |||
3551 3552 3553 3554 3555 3556 3557 | # which also follows redirects. # # ########################################################################### proc ::WS::Client::DoRestCall {serviceName objectName operationName argList {headers {}} {location {}}} { variable serviceArr | | | 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 | # which also follows redirects. # # ########################################################################### proc ::WS::Client::DoRestCall {serviceName objectName operationName argList {headers {}} {location {}}} { variable serviceArr ::log::logsubst debug {Entering [info level 0]} if {![info exists serviceArr($serviceName)]} { return \ -code error \ -errorcode [list WS CLIENT UNKSRV $serviceName] \ "Unknown service '$serviceName'" } set serviceInfo $serviceArr($serviceName) |
︙ | ︙ | |||
3614 3615 3616 3617 3618 3619 3620 | parseRestResults $serviceName $objectName $operationName $body } results]} { RestoreSavedOptions $serviceName ::log::log debug "Leaving (error) ::WS::Client::DoRestCall" return -code error $results } RestoreSavedOptions $serviceName | | | 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 | parseRestResults $serviceName $objectName $operationName $body } results]} { RestoreSavedOptions $serviceName ::log::log debug "Leaving (error) ::WS::Client::DoRestCall" return -code error $results } RestoreSavedOptions $serviceName ::log::logsubst debug {Leaving ::WS::Client::DoRestCall with {$results}} return $results } ########################################################################### # # Public Procedure Header - as this procedure is modified, please be sure |
︙ | ︙ | |||
3681 3682 3683 3684 3685 3686 3687 | proc ::WS::Client::DoRestAsyncCall {serviceName objectName operationName argList succesCmd errorCmd {headers {}}} { variable serviceArr set svcHeaders [dict get $serviceArr($serviceName) headers] if {[llength $svcHeaders]} { set headers [concat $headers $svcHeaders] } | | | 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 | proc ::WS::Client::DoRestAsyncCall {serviceName objectName operationName argList succesCmd errorCmd {headers {}}} { variable serviceArr set svcHeaders [dict get $serviceArr($serviceName) headers] if {[llength $svcHeaders]} { set headers [concat $headers $svcHeaders] } ::log::logsubst debug {Entering [info level 0]} if {![info exists serviceArr($serviceName)]} { return \ -code error \ -errorcode [list WS CLIENT UNKSRV $serviceName] \ "Unknown service '$serviceName'" } set serviceInfo $serviceArr($serviceName) |
︙ | ︙ | |||
3707 3708 3709 3710 3711 3712 3713 | if {[catch {set query [buildRestCallquery $serviceName $objectName $operationName $url $argList]} err]} { RestoreSavedOptions $serviceName return -code error -errorcode $::errorCode -errorinfo $::errorInfo $err } else { RestoreSavedOptions $serviceName } if {[llength $headers]} { | < | | < < | | < | 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 | if {[catch {set query [buildRestCallquery $serviceName $objectName $operationName $url $argList]} err]} { RestoreSavedOptions $serviceName return -code error -errorcode $::errorCode -errorinfo $::errorInfo $err } else { RestoreSavedOptions $serviceName } if {[llength $headers]} { ::log::logsubst info {::http::geturl $url \ -query $query \ -type [dict get $serviceInfo contentType] \ -headers $headers \ -command [list ::WS::Client::asyncRestCallDone $serviceName $operationName $succesCmd $errorCmd]} ::http::geturl $url \ -query $query \ -type [dict get $serviceInfo contentType] \ -headers $headers \ -command [list ::WS::Client::asyncRestCallDone $serviceName $operationName $succesCmd $errorCmd] } else { ::log::logsubst info {::http::geturl $url \ -query $query \ -type [dict get $serviceInfo contentType] \ -command [list ::WS::Client::asyncRestCallDone $serviceName $operationName $succesCmd $errorCmd]} ::http::geturl $url \ -query $query \ -type [dict get $serviceInfo contentType] \ -command [list ::WS::Client::asyncRestCallDone $serviceName $operationName $succesCmd $errorCmd] } ::log::log debug "Leaving ::WS::Client::DoAsyncRestCall" return; |
︙ | ︙ | |||
3778 3779 3780 3781 3782 3783 3784 | # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::buildRestCallquery {serviceName objectName operationName url argList} { variable serviceArr | | | | 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 | # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::buildRestCallquery {serviceName objectName operationName url argList} { variable serviceArr ::log::logsubst debug {Entering [info level 0]} set serviceInfo $serviceArr($serviceName) set msgType [dict get $serviceInfo object $objectName operation $operationName inputs] set xnsList [dict get $serviceInfo targetNamespace] dom createDocument "request" doc $doc documentElement body $body setAttribute \ "method" $operationName foreach {tns target} $xnsList { #set tns [lindex $xns 0] #set target [lindex $xns 1] $body setAttribute \ xmlns:$tns $target } set xns [dict get [::WS::Utils::GetServiceTypeDef Client $serviceName $msgType] xns] ::log::logsubst debug {calling [list ::WS::Utils::convertDictToType Client $serviceName $doc $body $argList $msgType]} set options [::WS::Utils::SetOption] ::WS::Utils::SetOption UseNS 0 ::WS::Utils::SetOption genOutAttr 1 ::WS::Utils::SetOption valueAttr {} ::WS::Utils::convertDictToType Client $serviceName $doc $body $argList $msgType set encoding [lindex [split [lindex [split [dict get $serviceInfo contentType] {;}] end] {=}] end] foreach {option value} $options { |
︙ | ︙ | |||
3818 3819 3820 3821 3822 3823 3824 | set xml [encoding convertto $encoding $xml] set inTransform [dict get $serviceInfo inTransform] if {$inTransform ne {}} { set xml [$inTransform $serviceName $operationName REQUEST $xml $url $argList] } | | | 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 | set xml [encoding convertto $encoding $xml] set inTransform [dict get $serviceInfo inTransform] if {$inTransform ne {}} { set xml [$inTransform $serviceName $operationName REQUEST $xml $url $argList] } ::log::logsubst debug {Leaving ::WS::Client::buildRestCallquery with {$xml}} return $xml } ########################################################################### # |
︙ | ︙ | |||
3871 3872 3873 3874 3875 3876 3877 | # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::parseRestResults {serviceName objectName operationName inXML} { variable serviceArr | | | | 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 | # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::parseRestResults {serviceName objectName operationName inXML} { variable serviceArr ::log::logsubst debug {Entering [info level 0]} set first [string first {<} $inXML] if {$first > 0} { set inXML [string range $inXML $first end] } set serviceInfo $serviceArr($serviceName) set outTransform [dict get $serviceInfo outTransform] if {$outTransform ne {}} { set inXML [$outTransform $serviceName $operationName REPLY $inXML] } set expectedMsgType [dict get $serviceInfo object $objectName operation $operationName outputs] # save parsed xml handle in variable doc dom parse $inXML doc # save top node handle in variable top $doc documentElement top set xns {} foreach tmp [dict get $serviceInfo targetNamespace] { lappend xns $tmp } ::log::logsubst debug {Using namespaces {$xns}} set body $top set status [$body getAttribute status] ## ## See if it is a standard error packet ## if {$status ne {ok}} { |
︙ | ︙ | |||
3917 3918 3919 3920 3921 3922 3923 | ## ## Convert the packet to a dictionary ## set results {} set options [::WS::Utils::SetOption] ::WS::Utils::SetOption UseNS 0 ::WS::Utils::SetOption parseInAttr 1 | | | 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 | ## ## Convert the packet to a dictionary ## set results {} set options [::WS::Utils::SetOption] ::WS::Utils::SetOption UseNS 0 ::WS::Utils::SetOption parseInAttr 1 ::log::logsubst debug {Calling ::WS::Utils::convertTypeToDict Client $serviceName $body $expectedMsgType $body} if {$expectedMsgType ne {}} { set node [$body childNodes] set nodeName [$node nodeName] if {$objectName ne $nodeName} { return \ -code error \ -errorcode [list WS CLIENT BADRESPONSE [list $objectName $nodeName]] \ |
︙ | ︙ | |||
3984 3985 3986 3987 3988 3989 3990 | # Version Date Programmer Comments / Changes / Reasons # ------- ---------- ---------- ------------------------------------------- # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::asyncRestCallDone {serviceName objectName operationName succesCmd errorCmd token} { | | | | 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 | # Version Date Programmer Comments / Changes / Reasons # ------- ---------- ---------- ------------------------------------------- # 1 07/06/2006 G.Lester Initial version # # ########################################################################### proc ::WS::Client::asyncRestCallDone {serviceName objectName operationName succesCmd errorCmd token} { ::log::logsubst debug {Entering [info level 0]} ## ## Check for errors ## set body [::http::data $token] ::log::logsubst info {\nReceived: $body} if {[::http::status $token] ne {ok} || ( [::http::ncode $token] != 200 && $body eq {} )} { set errorCode [list WS CLIENT HTTPERROR [::http::code $token]] set hadError 1 set errorInfo [FormatHTTPError $token] } else { SaveAndSetOptions $serviceName |
︙ | ︙ |
Changes to Utilities.tcl.
︙ | ︙ | |||
75 76 77 78 79 80 81 | } } } package require tdom 0.8 package require struct::set | | | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | } } } package require tdom 0.8 package require struct::set package provide WS::Utils 2.4.2 namespace eval ::WS {} namespace eval ::WS::Utils { set ::WS::Utils::typeInfo {} set ::WS::Utils::currentSchema {} array set ::WS::Utils::importedXref {} |
︙ | ︙ | |||
1378 1379 1380 1381 1382 1383 1384 1385 1386 | # update this segment of the file header block by # adding a complete entry at the bottom of the list. # # Version Date Programmer Comments / Changes / Reasons # ------- ---------- ---------- ------------------------------------------- # 1 07/06/2006 G.Lester Initial version # # ########################################################################### | > > > | > > | 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 | # update this segment of the file header block by # adding a complete entry at the bottom of the list. # # Version Date Programmer Comments / Changes / Reasons # ------- ---------- ---------- ------------------------------------------- # 1 07/06/2006 G.Lester Initial version # # 2.4.2 2018-05-14 H.Oehlmann Add support to translate namespace prefixes # in attribute values or text values. # New parameter "xnsDistantToLocalDict". # ########################################################################### proc ::WS::Utils::convertTypeToDict { mode serviceName node type root {isArray 0} {xnsDistantToLocalDict {}} } { variable typeInfo variable mutableTypeInfo variable options if {$options(valueAttrCompatiblityMode)} { set valueAttr {} } else { |
︙ | ︙ | |||
1445 1446 1447 1448 1449 1450 1451 | } if {[string equal $partName *] && [string equal $partType *]} { ## ## Type infomation being handled dynamically for this part ## set savedTypeInfo $typeInfo parseDynamicType $mode $serviceName $node $type | | | 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 | } if {[string equal $partName *] && [string equal $partType *]} { ## ## Type infomation being handled dynamically for this part ## set savedTypeInfo $typeInfo parseDynamicType $mode $serviceName $node $type set tmp [convertTypeToDict $mode $serviceName $node $type $root 0 $xnsDistantToLocalDict] foreach partName [dict keys $tmp] { dict set results $partName [dict get $tmp $partName] } set typeInfo $savedTypeInfo continue } set partXns $xns |
︙ | ︙ | |||
1602 1603 1604 1605 1606 1607 1608 1609 | dict set results $partName $tmp } {1 0} { ## ## Non-simple non-array ## if {$options(parseInAttr)} { if {$isAbstract && [$item hasAttributeNS {http://www.w3.org/2001/XMLSchema-instance} type]} { | > > > > > > > > > > > > > > > > > | > > > | | | 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 | dict set results $partName $tmp } {1 0} { ## ## Non-simple non-array ## if {$options(parseInAttr)} { ## Translate an abstract type from the WSDL to a type given ## in the response ## Example xml response from bug 584bfb772: ## <soap:Envelope ... ## xmlns:tns="http://www.esri.com/schemas/ArcGIS/10.3"> ## <soap:Body> ## <tns:GetServerInfoResponse> ## <Result xsi:type="tns:MapServerInfo"> ## <Name>Layers</Name> ## <Description></Description> ## <FullExtent xsi:type="tns:EnvelopeN"> ## ## The element FullExtend gets type "tns:EnvelopeN". ## ## xnsDistantToLocalDict if {$isAbstract && [$item hasAttributeNS {http://www.w3.org/2001/XMLSchema-instance} type]} { # partType is now tns::EnvelopeN set partType [XNSDistantToLocal $xnsDistantToLocalDict\ [$item getAttributeNS {http://www.w3.org/2001/XMLSchema-instance} type]] # Remove this type attribute from the snippet. # So, it is not handled in the loop below. $item removeAttributeNS {http://www.w3.org/2001/XMLSchema-instance} type } foreach attrList [$item attributes] { catch { lassign $attrList attr nsAlias nsUrl if {[string equal $nsUrl $xsiNsUrl]} { set attrValue [$item getAttribute ${nsAlias}:$attr] dict set results $partName ::$attr $attrValue } elseif {![string equal $nsAlias {}]} { set attrValue [$item getAttribute ${nsAlias}:$attr] dict set results $partName $attr $attrValue } else { set attrValue [$item getAttribute $attr] dict set results $partName $attr $attrValue } } } dict set results $partName $valueAttr [convertTypeToDict $mode $serviceName $item $partType $root 0 $xnsDistantToLocalDict] } else { dict set results $partName [convertTypeToDict $mode $serviceName $item $partType $root 0 $xnsDistantToLocalDict] } } {1 1} { ## ## Non-simple array ## set partType [string trimright $partType {()}] |
︙ | ︙ | |||
1654 1655 1656 1657 1658 1659 1660 | lappend rowList $attr $attrValue } else { set attrValue [$row getAttribute $attr] lappend rowList $attr $attrValue } } } | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 | lappend rowList $attr $attrValue } else { set attrValue [$row getAttribute $attr] lappend rowList $attr $attrValue } } } lappend rowList $valueAttr [convertTypeToDict $mode $serviceName $row $partType $root 1 $xnsDistantToLocalDict] lappend tmp $rowList } else { lappend tmp [convertTypeToDict $mode $serviceName $row $partType $root 1 $xnsDistantToLocalDict] } } dict set results $partName $tmp } default { ## ## Placed here to shut up tclchecker ## } } } ::log::logsubst debug {Leaving ::WS::Utils::convertTypeToDict with result '$results'} return $results } ########################################################################### # # Private Procedure Header - as this procedure is modified, please be sure # that you update this header block. Thanks. # #>>BEGIN PRIVATE<< # # Procedure Name : ::WS::Utils::XNSDistantToLocal # # Description : Get a reference node. # # Arguments : # xnsDistantToLocalDict - Dict to translate distant to local NS prefixes # typeDistant - Type string with possible distant namespace prefix # # Returns : type with local namespace prefix # # Side-Effects : None # # Exception Conditions : None # # Pre-requisite Conditions : None # # Original Author : Harald Oehlmann # #>>END PRIVATE<< # # Maintenance History - as this file is modified, please be sure that you # update this segment of the file header block by # adding a complete entry at the bottom of the list. # # Version Date Programmer Comments / Changes / Reasons # ------- ---------- ---------- ------------------------------------------- # 2.4.2 2017-11-03 H.Oehlmann Initial version # ########################################################################### proc ::WS::Utils::XNSDistantToLocal {xnsDistantToLocalDict type} { set collonPos [string first ":" $type] # check for namespace prefix present if {-1 < $collonPos} { set prefixDistant [string range $type 0 $collonPos-1] if {[dict exists $xnsDistantToLocalDict $prefixDistant]} { set type [dict get $xnsDistantToLocalDict $prefixDistant][string range $type $collonPos end] log::logsubst debug {Mapped distant namespace prefix '$prefixDistant' to type '$type'} } else { log::logsubst warning {Distant type '$type' does not have a known namespace prefix ([dict keys $xnsDistantToLocalDict])} } } return $type } ########################################################################### # # Private Procedure Header - as this procedure is modified, please be sure # that you update this header block. Thanks. # #>>BEGIN PRIVATE<< |
︙ | ︙ | |||
2152 2153 2154 2155 2156 2157 2158 | set yajlType $simpleTypesJson([string trimright $itemType {()?}]) } else { set yajlType "string" } ::log::logsubst debug {\t\titemName = {$itemName} itemDef = {$itemDef} typeInfoList = {$typeInfoList}} set typeInfoList [lrange $typeInfoList 0 1] | | | 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 | set yajlType $simpleTypesJson([string trimright $itemType {()?}]) } else { set yajlType "string" } ::log::logsubst debug {\t\titemName = {$itemName} itemDef = {$itemDef} typeInfoList = {$typeInfoList}} set typeInfoList [lrange $typeInfoList 0 1] switch -- $typeInfoList { {0 0} { ## ## Simple non-array ## set resultValue [dict get $dict $itemName] $doc string $itemName $yajlType $resultValue } |
︙ | ︙ | |||
2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 | proc ::WS::Utils::convertDictToTypeNoNs {mode service doc parent dict type {enforceRequired 0}} { ::log::logsubst debug {Entering [info level 0]} # ::log::log debug " Parent xml: [$parent asXML]" variable typeInfo variable simpleTypes variable options variable standardAttributes if {$options(valueAttrCompatiblityMode)} { set valueAttr {} } else { set valueAttr {::value} } set typeInfoList [TypeInfo $mode $service $type] | > | 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 | proc ::WS::Utils::convertDictToTypeNoNs {mode service doc parent dict type {enforceRequired 0}} { ::log::logsubst debug {Entering [info level 0]} # ::log::log debug " Parent xml: [$parent asXML]" variable typeInfo variable simpleTypes variable options variable standardAttributes variable currentNs if {$options(valueAttrCompatiblityMode)} { set valueAttr {} } else { set valueAttr {::value} } set typeInfoList [TypeInfo $mode $service $type] |
︙ | ︙ | |||
2357 2358 2359 2360 2361 2362 2363 | } } } {1 0} { ## ## Non-simple non-array ## | | > | | | 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 | } } } {1 0} { ## ## Non-simple non-array ## $parent appendChild [$doc createElement $itemName retNode] if {$options(genOutAttr)} { set dictList [dict keys [dict get $dict $itemName]] set resultValue {} foreach attr [lindex [::struct::set intersect3 $standardAttributes $dictList] end] { if {$isAbstract && [string equal $attr {::type}]} { # *** HaO: useName is never defined set itemType [dict get $dict $useName $attr] $retNode setAttributeNS "http://www.w3.org/2001/XMLSchema-instance" xsi:type $itemType } elseif {[string equal $attr $valueAttr]} { set resultValue [dict get $dict $itemName $attr] } elseif {[string match {::*} $attr]} { set baseAttr [string range $attr 2 end] set attrValue [dict get $dict $itemName $attr] $retNode setAttributeNS "http://www.w3.org/2001/XMLSchema-instance" xsi:$baseAttr $attrValue } else { lappend attrList $attr [dict get $dict $itemName $attr] } } } else { set resultValue [dict get $dict $itemName] } if {[llength $attrList]} { ::WS::Utils::setAttr $retNode $attrList } convertDictToTypeNoNs $mode $service $doc $retNode $resultValue $itemType $enforceRequired } {1 1} { ## ## Non-simple array ## set dataList [dict get $dict $itemName] set tmpType [string trimright $itemType {()}] foreach row $dataList { $parent appendChild [$doc createElement $itemName retNode] if {$options(genOutAttr)} { set dictList [dict keys $row] set resultValue {} foreach attr [lindex [::struct::set intersect3 $standardAttributes $dictList] end] { if {$isAbstract && [string equal $attr {::type}]} { set tmpType [dict get $row $attr] $retNode setAttributeNS "http://www.w3.org/2001/XMLSchema-instance" xsi:type $tmpType |
︙ | ︙ | |||
2414 2415 2416 2417 2418 2419 2420 | } } else { set resultValue $row } if {[llength $attrList]} { ::WS::Utils::setAttr $retNode $attrList } | | | 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 | } } else { set resultValue $row } if {[llength $attrList]} { ::WS::Utils::setAttr $retNode $attrList } convertDictToTypeNoNs $mode $service $doc $retNode $resultValue $tmpType $enforceRequired } } default { ## ## Placed here to shut up tclchecker ## } |
︙ | ︙ | |||
3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 | } complexType { $middleNode setAttribute name $typeName parseComplexType $mode results $serviceName $middleNode $tns } simpleContent - complexContent { foreach child [$middleNode childNodes] { set parent [$child parent] set contentType [$child localName] ::log::logsubst debug {Content Type is {$contentType}} switch -exact -- $contentType { restriction { set nodeFound 1 | > > > > > > > > > > > > > > > > > > > > > | 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 | } complexType { $middleNode setAttribute name $typeName parseComplexType $mode results $serviceName $middleNode $tns } simpleContent - complexContent { ## ## Save simple or complex content for abstract types, which ## may have content type with no fields. [Bug 584bfb77] ## Example xml type snippet: ## <xs:complexType name="Envelope" abstract="true"> ## <xs:annotation><xs:documentation /></xs:annotation> ## <xs:complexContent mixed="false"> ## <xs:extension base="Geometry" /> ## </xs:complexContent> ## </xs:complexType> ## ... ## <xs:complexType name="Geometry"> ## <xs:annotation><xs:documentation /></xs:annotation> ## </xs:complexType> set isComplexContent [expr {$middle eq "complexContent"}] ::log::logsubst debug {isComplexContent = $isComplexContent} ## ## Loop over the components of the type ## foreach child [$middleNode childNodes] { set parent [$child parent] set contentType [$child localName] ::log::logsubst debug {Content Type is {$contentType}} switch -exact -- $contentType { restriction { set nodeFound 1 |
︙ | ︙ | |||
3457 3458 3459 3460 3461 3462 3463 | } } } ::log::logsubst debug {at end of foreach {$typeName} with {$partList}} if {[llength $partList] || $isAbstractType} { #dict set results types $tns:$typeName $partList dict set results types $typeName $partList | | > > > > > > > > | > > | 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 | } } } ::log::logsubst debug {at end of foreach {$typeName} with {$partList}} if {[llength $partList] || $isAbstractType} { #dict set results types $tns:$typeName $partList dict set results types $typeName $partList ::log:::logsubst debug {Defining $typeName as '$partList'} ## ## Add complex type definition, if: ## * there is a part list ## * or it is an abstract type announced as complex ## (see xml snipped above about [Bug 584bfb77]) ## -> will set dict typeInfo client $service tns1:envelope { ## definition {} xns tns1 abstract true} ## if { ([llength $partList] && ![string equal [lindex $partList 0] {}]) || ($isAbstractType && [info exists isComplexContent] && $isComplexContent) } { ::WS::Utils::ServiceTypeDef $mode $serviceName $typeName $partList $tns $isAbstractType } else { ::WS::Utils::ServiceSimpleTypeDef $mode $serviceName $typeName [list base $defaultType comment {}] $tns } } elseif {!$nodeFound} { #puts "Defined $typeName as simple type" |
︙ | ︙ | |||
4152 4153 4154 4155 4156 4157 4158 | array unset fieldInfoArr set fieldInfoArr(minOccurs) 0 array set fieldInfoArr $fieldDef if {$fieldInfoArr(minOccurs) && ![info exists fieldInfoArr($field)]} { ## ## Fields was required but is missing ## | | | | 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 | array unset fieldInfoArr set fieldInfoArr(minOccurs) 0 array set fieldInfoArr $fieldDef if {$fieldInfoArr(minOccurs) && ![info exists fieldInfoArr($field)]} { ## ## Fields was required but is missing ## set ::errorCode [list WS CHECK MISSREQFLD [list $typeName $field]] set result 0 } elseif {$fieldInfoArr(minOccurs) && ($fieldInfoArr(minOccurs) > [llength $fieldInfoArr($field)])} { ## ## Fields was required and present, but not enough times ## set ::errorCode [list WS CHECK MINOCCUR [list $type $field]] set result 0 } elseif {[info exists fieldInfoArr(maxOccurs)] && [string is integer fieldInfoArr(maxOccurs)] && ($fieldInfoArr(maxOccurs) < [llength $fieldInfoArr($field)])} { ## ## Fields was required and present, but too many times ## set ::errorCode [list WS CHECK MAXOCCUR [list $typeName $field]] set result 0 } elseif {[info exists fieldInfoArr($field)]} { foreach node $fieldInfoArr($field) { set result [checkTags $mode $serviceName $node $fieldInfoArr(type)] if {!$result} { break } |
︙ | ︙ | |||
4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 | set result 0 array set typeInfos { minLength 0 maxLength -1 fixed false } array set typeInfos [GetServiceTypeDef $mode $serviceName $type] foreach {var value} [array get typeInfos] { set $var $value } set result 1 if {$minLength >= 0 && [string length $value] < $minLength} { | > | | | | | 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 | set result 0 array set typeInfos { minLength 0 maxLength -1 fixed false } # returns indexes type, xns, ... array set typeInfos [GetServiceTypeDef $mode $serviceName $type] foreach {var value} [array get typeInfos] { set $var $value } set result 1 if {$minLength >= 0 && [string length $value] < $minLength} { set ::errorCode [list WS CHECK VALUE_TO_SHORT [list $type $value $minLength $typeInfo]] set result 0 } elseif {$maxLength >= 0 && [string length $value] > $maxLength} { set ::errorCode [list WS CHECK VALUE_TO_LONG [list $type $value $maxLength $typeInfo]] set result 0 } elseif {[info exists enumeration] && ([lsearch -exact $enumeration $value] == -1)} { set errorCode [list WS CHECK VALUE_NOT_IN_ENUMERATION [list $type $value $enumeration $typeInfo]] set result 0 } elseif {[info exists pattern] && (![regexp -- $pattern $value])} { set errorCode [list WS CHECK VALUE_NOT_MATCHES_PATTERN [list $type $value $pattern $typeInfo]] set result 0 } return $result } |
︙ | ︙ | |||
4320 4321 4322 4323 4324 4325 4326 | ## ## Get the type information ## set baseTypeName [string trimright $typeName {()?}] set typeInfo [GetServiceTypeDef $mode $serviceName $baseTypeName] set typeName [string trimright $typeName {?}] | | | 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 | ## ## Get the type information ## set baseTypeName [string trimright $typeName {()?}] set typeInfo [GetServiceTypeDef $mode $serviceName $baseTypeName] set typeName [string trimright $typeName {?}] set xns [dict get $typeInfo $mode $serviceName $typeName xns] foreach {field fieldDef} [dict get $typeInfo definition] { ## ## Get info about this field and its type ## array unset fieldInfoArr set fieldInfoArr(minOccurs) 0 |
︙ | ︙ | |||
4368 4369 4370 4371 4372 4373 4374 | [string is integer fieldInfoArr(maxOccurs)] && ($fieldInfoArr(maxOccurs) < $valueListLenght)} { ## ## Fields was required and present, but too many times ## set minOccurs $fieldInfoArr(maxOccurs) return \ | | | 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 | [string is integer fieldInfoArr(maxOccurs)] && ($fieldInfoArr(maxOccurs) < $valueListLenght)} { ## ## Fields was required and present, but too many times ## set minOccurs $fieldInfoArr(maxOccurs) return \ -errorcode [list WS CHECK MAXOCCUR [list $typeName $field]] \ "Field '$field' of type '$typeName' could only occur $minOccurs time(s) but occured $valueListLenght time(s)" } elseif {[dict exists $valueInfos $field]} { foreach value $valueList { $currentNode appendChild [$doc createElement $xns:$field retNode] if {$isComplex} { buildTags $mode $serviceName $fieldBaseType $value $doc $retNode } else { |
︙ | ︙ |
Changes to pkgIndex.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 | # Tcl package index file, version 1.1 # This file is generated by the "pkg_mkIndex -direct" command # and sourced either when an application starts up or # by a "package unknown" script. It invokes the # "package ifneeded" command to set up package-related # information so that packages will be loaded automatically # in response to "package require" commands. When this # script is sourced, the variable $dir must contain the # full path name of this file's directory. package ifneeded WS::AOLserver 2.4.0 [list source [file join $dir AOLserver.tcl]] package ifneeded WS::Channel 2.4.0 [list source [file join $dir ChannelServer.tcl]] | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # Tcl package index file, version 1.1 # This file is generated by the "pkg_mkIndex -direct" command # and sourced either when an application starts up or # by a "package unknown" script. It invokes the # "package ifneeded" command to set up package-related # information so that packages will be loaded automatically # in response to "package require" commands. When this # script is sourced, the variable $dir must contain the # full path name of this file's directory. package ifneeded WS::AOLserver 2.4.0 [list source [file join $dir AOLserver.tcl]] package ifneeded WS::Channel 2.4.0 [list source [file join $dir ChannelServer.tcl]] package ifneeded WS::Client 2.5.1 [list source [file join $dir ClientSide.tcl]] package ifneeded WS::Embeded 2.4.0 [list source [file join $dir Embedded.tcl]] package ifneeded WS::Server 2.4.0 [list source [file join $dir ServerSide.tcl]] package ifneeded WS::Utils 2.4.2 [list source [file join $dir Utilities.tcl]] package ifneeded WS::Wub 2.4.0 [list source [file join $dir WubServer.tcl]] package ifneeded Wsdl 2.4.0 [list source [file join $dir WubServer.tcl]] |