(file) Return to WsmReader.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / WsmServer

   1 martin 1.4 //%LICENSE////////////////////////////////////////////////////////////////
   2 martin 1.5 //
   3 martin 1.4 // Licensed to The Open Group (TOG) under one or more contributor license
   4            // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
   5            // this work for additional information regarding copyright ownership.
   6            // Each contributor licenses this file to you under the OpenPegasus Open
   7            // Source License; you may not use this file except in compliance with the
   8            // License.
   9 martin 1.5 //
  10 martin 1.4 // Permission is hereby granted, free of charge, to any person obtaining a
  11            // copy of this software and associated documentation files (the "Software"),
  12            // to deal in the Software without restriction, including without limitation
  13            // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  14            // and/or sell copies of the Software, and to permit persons to whom the
  15            // Software is furnished to do so, subject to the following conditions:
  16 martin 1.5 //
  17 martin 1.4 // The above copyright notice and this permission notice shall be included
  18            // in all copies or substantial portions of the Software.
  19 martin 1.5 //
  20 martin 1.4 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  21 martin 1.5 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22 martin 1.4 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  23            // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  24            // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  25            // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  26            // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27 martin 1.5 //
  28 martin 1.4 //////////////////////////////////////////////////////////////////////////
  29 kumpf  1.2 //
  30            //%////////////////////////////////////////////////////////////////////////////
  31            
  32            #include <cctype>
  33            #include <cstdio>
  34            #include <cstdlib>
  35            
  36            #include <Pegasus/Common/Config.h>
  37            #include <Pegasus/Common/MessageLoader.h>
  38 mike   1.10 #include <Pegasus/Common/Buffer.h>
  39 kumpf  1.2  #include <Pegasus/Common/StringConversion.h>
  40             #include <Pegasus/Common/XmlReader.h>
  41 mike   1.10 #include <Pegasus/WQL/WQLSelectStatement.h>
  42             #include <Pegasus/WQL/WQLParser.h>
  43 kumpf  1.2  #include <Pegasus/WsmServer/WsmConstants.h>
  44             #include <Pegasus/WsmServer/WsmFault.h>
  45             #include "WsmReader.h"
  46             
  47             PEGASUS_NAMESPACE_BEGIN
  48             
  49             ///////////////////////////////////////////////////////////////////////////////
  50             //
  51             // WsmReader
  52             //
  53             ///////////////////////////////////////////////////////////////////////////////
  54             
  55             WsmReader::WsmReader(char* text)
  56                 : _parser(text, WsmNamespaces::supportedNamespaces)
  57             {
  58             }
  59             
  60             WsmReader::~WsmReader()
  61             {
  62             }
  63             
  64 mike   1.10 void WsmReader::setHideEmptyTags(Boolean flag)
  65             {
  66                 _parser.setHideEmptyTags(flag);
  67             }
  68             
  69 kumpf  1.2  //-----------------------------------------------------------------------------
  70             //
  71             // getXmlDeclaration()
  72             //
  73             //     <?xml version="1.0" encoding="utf-8"?>
  74             //
  75             //-----------------------------------------------------------------------------
  76             Boolean WsmReader::getXmlDeclaration(
  77                 const char*& xmlVersion,
  78                 const char*& xmlEncoding)
  79             {
  80                 XmlEntry entry;
  81             
  82                 if (_parser.next(entry))
  83                 {
  84                     if ((entry.type != XmlEntry::XML_DECLARATION) ||
  85                         (strcmp(entry.text, "xml") != 0))
  86                     {
  87                         _parser.putBack(entry);
  88                         return false;
  89                     }
  90 kumpf  1.2  
  91                     entry.getAttributeValue("version", xmlVersion);
  92                     entry.getAttributeValue("encoding", xmlEncoding);
  93                     return true;
  94                 }
  95             
  96                 return false;
  97             }
  98             
  99             Boolean WsmReader::testStartTag(
 100                 XmlEntry& entry,
 101                 int nsType,
 102                 const char* tagName)
 103             {
 104                 if (!_parser.next(entry))
 105                 {
 106                     return false;
 107                 }
 108             
 109                 if ((entry.type != XmlEntry::START_TAG) ||
 110                     (entry.nsType != nsType) ||
 111 kumpf  1.2          (tagName && strcmp(entry.localName, tagName) != 0))
 112                 {
 113                     _parser.putBack(entry);
 114                     return false;
 115                 }
 116             
 117                 return true;
 118             }
 119             
 120             Boolean WsmReader::testStartOrEmptyTag(
 121                 XmlEntry& entry,
 122                 int nsType,
 123                 const char* tagName)
 124             {
 125                 if (!_parser.next(entry))
 126                 {
 127                     return false;
 128                 }
 129             
 130                 if (((entry.type != XmlEntry::START_TAG) &&
 131                      (entry.type != XmlEntry::EMPTY_TAG)) ||
 132 kumpf  1.2          (entry.nsType != nsType) ||
 133                     (tagName && strcmp(entry.localName, tagName) != 0))
 134                 {
 135                     _parser.putBack(entry);
 136                     return false;
 137                 }
 138             
 139                 return true;
 140             }
 141             
 142             Boolean WsmReader::testEndTag(
 143                 int nsType,
 144                 const char* tagName)
 145             {
 146                 XmlEntry entry;
 147             
 148                 if (!_parser.next(entry))
 149                 {
 150                     return false;
 151                 }
 152             
 153 kumpf  1.2      if ((entry.type != XmlEntry::END_TAG) ||
 154                     (entry.nsType != nsType) ||
 155                     (tagName && strcmp(entry.localName, tagName) != 0))
 156                 {
 157                     _parser.putBack(entry);
 158                     return false;
 159                 }
 160             
 161                 return true;
 162             }
 163             
 164             void WsmReader::expectStartTag(
 165                 XmlEntry& entry,
 166                 int nsType,
 167                 const char* tagName)
 168             {
 169                 if (!_parser.next(entry) ||
 170                     entry.type != XmlEntry::START_TAG ||
 171                     entry.nsType != nsType ||
 172                     strcmp(entry.localName, tagName) != 0)
 173                 {
 174 kumpf  1.2          const char* nsUri;
 175             
 176                     // The nsType must have already been declared in the XML or it must be
 177                     // a supported namespace.
 178                     XmlNamespace* ns = _parser.getNamespace(nsType);
 179                     if (ns)
 180                     {
 181                         nsUri = ns->extendedName;
 182                     }
 183                     else
 184                     {
 185                         PEGASUS_ASSERT((nsType >= 0) && (nsType < WsmNamespaces::LAST));
 186                         nsUri = WsmNamespaces::supportedNamespaces[nsType].extendedName;
 187                     }
 188             
 189                     MessageLoaderParms mlParms(
 190                         "WsmServer.WsmReader.EXPECTED_OPEN",
 191                         "Expecting a start tag for \"$0\" element in namespace \"$1\".",
 192                         tagName, nsUri);
 193                     throw XmlValidationError(_parser.getLine(), mlParms);
 194                 }
 195 kumpf  1.2  }
 196             
 197 mike   1.10 int WsmReader::expectStartTag(
 198                 XmlEntry& entry,
 199                 const char* tagName)
 200             {
 201                 if (!_parser.next(entry) ||
 202                     entry.type != XmlEntry::START_TAG ||
 203                     strcmp(entry.localName, tagName) != 0)
 204                 {
 205                     const char* nsUri;
 206                     int nsType = entry.nsType;
 207             
 208                     // The nsType must have already been declared in the XML or it must be
 209                     // a supported namespace.
 210                     XmlNamespace* ns = _parser.getNamespace(nsType);
 211                     if (ns)
 212                     {
 213                         nsUri = ns->extendedName;
 214                     }
 215                     else
 216                     {
 217                         PEGASUS_ASSERT((nsType >= 0) && (nsType < WsmNamespaces::LAST));
 218 mike   1.10             nsUri = WsmNamespaces::supportedNamespaces[nsType].extendedName;
 219                     }
 220             
 221                     MessageLoaderParms mlParms(
 222                         "WsmServer.WsmReader.EXPECTED_OPEN",
 223                         "Expecting a start tag for \"$0\" element in namespace \"$1\".",
 224                         tagName, nsUri);
 225                     throw XmlValidationError(_parser.getLine(), mlParms);
 226                 }
 227             
 228                 return entry.nsType;
 229             }
 230             
 231 kumpf  1.2  void WsmReader::expectStartOrEmptyTag(
 232                 XmlEntry& entry,
 233                 int nsType,
 234                 const char* tagName)
 235             {
 236                 if (!_parser.next(entry) ||
 237                     (entry.type != XmlEntry::START_TAG &&
 238                      entry.type != XmlEntry::EMPTY_TAG) ||
 239                     entry.nsType != nsType ||
 240                     strcmp(entry.localName, tagName) != 0)
 241                 {
 242                     const char* nsUri;
 243             
 244                     // The nsType must have already been declared in the XML or it must be
 245                     // a supported namespace.
 246                     XmlNamespace* ns = _parser.getNamespace(nsType);
 247                     if (ns)
 248                     {
 249                         nsUri = ns->extendedName;
 250                     }
 251                     else
 252 kumpf  1.2          {
 253                         PEGASUS_ASSERT((nsType >= 0) && (nsType < WsmNamespaces::LAST));
 254                         nsUri = WsmNamespaces::supportedNamespaces[nsType].extendedName;
 255                     }
 256             
 257                     MessageLoaderParms mlParms(
 258                         "WsmServer.WsmReader.EXPECTED_OPENCLOSE",
 259                         "Expecting a start tag or an empty tag for \"$0\" element in "
 260                             "namespace \"$1\".",
 261                         tagName, nsUri);
 262                     throw XmlValidationError(_parser.getLine(), mlParms);
 263                 }
 264             }
 265             
 266             void WsmReader::expectEndTag(
 267                 int nsType,
 268                 const char* tagName)
 269             {
 270                 XmlEntry entry;
 271             
 272                 if (!_parser.next(entry) ||
 273 kumpf  1.2          entry.type != XmlEntry::END_TAG ||
 274                     entry.nsType != nsType ||
 275                     strcmp(entry.localName, tagName) != 0)
 276                 {
 277                     // The nsType must have already been declared in the XML.  (Note that
 278                     // ns->localName is null for a default namespace declaration.)
 279                     XmlNamespace* ns = _parser.getNamespace(nsType);
 280                     PEGASUS_ASSERT(ns);
 281                     MessageLoaderParms mlParms(
 282                         "WsmServer.WsmReader.EXPECTED_CLOSE",
 283                         "Expecting an end tag for \"$0\" element in namespace \"$1\".",
 284                         tagName, ns->extendedName);
 285                     throw XmlValidationError(_parser.getLine(), mlParms);
 286                 }
 287             }
 288             
 289             void WsmReader::expectContentOrCData(XmlEntry& entry)
 290             {
 291                 XmlReader::expectContentOrCData(_parser, entry);
 292             }
 293             
 294 kumpf  1.2  Boolean WsmReader::next(XmlEntry& entry)
 295             {
 296                 return _parser.next(entry);
 297             }
 298             
 299             Boolean WsmReader::getAttributeValue(
 300                 Uint32 lineNumber,
 301                 XmlEntry& entry,
 302                 const char* attributeName,
 303                 String& attributeValue,
 304                 Boolean required)
 305             {
 306                 if (!entry.getAttributeValue(attributeName, attributeValue))
 307                 {
 308                     if (required)
 309                     {
 310                         MessageLoaderParms parms(
 311                             "WsmServer.WsmReader.MISSING_ATTRIBUTE",
 312                             "The attribute $0.$1 is missing.",
 313                             entry.text,
 314                             attributeName);
 315 kumpf  1.2              throw XmlValidationError(lineNumber, parms);
 316                     }
 317             
 318                     return false;
 319                 }
 320             
 321                 return true;
 322             }
 323             
 324             Boolean WsmReader::mustUnderstand(XmlEntry& entry)
 325             {
 326                 const XmlAttribute* attr = entry.findAttribute(
 327                     WsmNamespaces::SOAP_ENVELOPE, "mustUnderstand");
 328                 return (attr && (strcmp(attr->value, "true") == 0));
 329             }
 330             
 331             Boolean WsmReader::getElementStringValue(
 332                 int nsType,
 333                 const char* tagName,
 334                 String& stringValue,
 335                 Boolean required)
 336 kumpf  1.2  {
 337                 XmlEntry entry;
 338             
 339                 if (required)
 340                 {
 341                     expectStartTag(entry, nsType, tagName);
 342                 }
 343                 else if (!testStartTag(entry, nsType, tagName))
 344                 {
 345                     return false;
 346                 }
 347             
 348                 expectContentOrCData(entry);
 349 venkat.puvvada 1.7      stringValue.assign(entry.text, entry.textLen);
 350 kumpf          1.2      expectEndTag(nsType, tagName);
 351                         return true;
 352                     }
 353                     
 354                     const char* WsmReader::getElementContent(XmlEntry& entry)
 355                     {
 356                         if (entry.type == XmlEntry::EMPTY_TAG)
 357                         {
 358                             return "";
 359                         }
 360                     
 361                         expectContentOrCData(entry);
 362                         return entry.text;
 363                     }
 364                     
 365 kumpf          1.3  Uint64 WsmReader::getEnumerationContext(XmlEntry& entry)
 366                     {
 367                         const char* content = getElementContent(entry);
 368                         if (*content == '+')
 369                         {
 370                             content++;
 371                         }
 372                     
 373                         Uint64 value;
 374                         if (!StringConversion::decimalStringToUint64(content, value))
 375                         {
 376                             throw WsmFault(
 377                                 WsmFault::wsen_InvalidEnumerationContext,
 378                                 MessageLoaderParms(
 379                                     "WsmServer.WsmReader.INVALID_ENUMERATION_CONTEXT",
 380                                     "Enumeration context \"$1\" is not valid.",
 381                                     content));
 382                         }
 383                         return value;
 384                     }
 385                     
 386 kumpf          1.3  Uint32 WsmReader::getUint32ElementContent(XmlEntry& entry, const char* name)
 387                     {
 388                         const char* content = getElementContent(entry);
 389                         if (*content == '+')
 390                         {
 391                             content++;
 392                         }
 393                     
 394                         Uint64 value;
 395                         if (!StringConversion::decimalStringToUint64(content, value) ||
 396                             (value == 0) || (value > 0xFFFFFFFF))
 397                         {
 398                             throw WsmFault(
 399                                 WsmFault::wsa_InvalidMessageInformationHeader,
 400                                 MessageLoaderParms(
 401                                     "WsmServer.WsmReader.INVALID_UINT32_VALUE",
 402                                     "The $0 value \"$1\" is not a valid "
 403                                     "positive integer.",
 404                                     name, content));
 405                         }
 406                     
 407 kumpf          1.3      return value & 0xFFFFFFFF;
 408                     }
 409                     
 410 kumpf          1.2  Boolean WsmReader::getSelectorElement(WsmSelector& selector)
 411                     {
 412                         XmlEntry entry;
 413                         if (!testStartOrEmptyTag(entry, WsmNamespaces::WS_MAN, "Selector"))
 414                         {
 415                             return false;
 416                         }
 417                     
 418                         Boolean empty = entry.type == XmlEntry::EMPTY_TAG;
 419                         String name;
 420                     
 421                         getAttributeValue(_parser.getLine(), entry, "Name", name);
 422                     
 423                         if (empty)
 424                         {
 425                             selector = WsmSelector(name, String::EMPTY);
 426                         }
 427                         else
 428                         {
 429                             WsmEndpointReference endpointReference;
 430                     
 431 kumpf          1.2          if (getSelectorEPRElement(endpointReference))
 432                             {
 433                                 selector = WsmSelector(name, endpointReference);
 434                             }
 435                             else
 436                             {
 437                                 expectContentOrCData(entry);
 438 venkat.puvvada 1.7              selector = WsmSelector(name, String(entry.text, entry.textLen));
 439 kumpf          1.2          }
 440                     
 441                             expectEndTag(WsmNamespaces::WS_MAN, "Selector");
 442                         }
 443                     
 444                         return true;
 445                     }
 446                     
 447                     Boolean WsmReader::getSelectorSetElement(WsmSelectorSet& selectorSet)
 448                     {
 449                         XmlEntry entry;
 450                         if (!testStartTag(entry, WsmNamespaces::WS_MAN, "SelectorSet"))
 451                         {
 452                             return false;
 453                         }
 454                     
 455                         selectorSet.selectors.clear();
 456                     
 457                         WsmSelector selector;
 458                     
 459                         while (getSelectorElement(selector))
 460 kumpf          1.2      {
 461                             selectorSet.selectors.append(selector);
 462                         }
 463                     
 464                         // If the selector set is empty, report an error
 465                         if (selectorSet.selectors.size() == 0)
 466                         {
 467                             expectStartTag(entry, WsmNamespaces::WS_MAN, "Selector");
 468                         }
 469                     
 470                         // Note: This "should" requirement is not implemented.
 471                         // DSP0226 R5.1.2.2-4: The Selector Name attribute shall not be duplicated
 472                         // at the same level of nesting.  If this occurs, the service should return
 473                         // a wsman:InvalidSelectors fault with the following detail code:
 474                         //     http://schemas.dmtf.org/wbem/wsman/1/wsman/faultDetail/
 475                         //         DuplicateSelectors
 476                     
 477                         expectEndTag(WsmNamespaces::WS_MAN, "SelectorSet");
 478                     
 479                         return true;
 480                     }
 481 kumpf          1.2  
 482                     void WsmReader::getEPRElement(WsmEndpointReference& endpointReference)
 483                     {
 484                         XmlEntry entry;
 485                     
 486                         // DSP0227 Section 5. WS-Management default addressing model is based
 487                         // on WS-Addressing. It makes use of wsa:ReferenceParameter field
 488                         // (containing wsa:ResourceURI and wsa:SelectorSet) to identify objects.
 489                         // The use of other fields defined by WS-Addressing in not specified.
 490                     
 491                         // wsa:Address is required by WS-Addressing
 492                         getElementStringValue(
 493                             WsmNamespaces::WS_ADDRESSING,
 494                             "Address",
 495                             endpointReference.address,
 496                             true);
 497                     
 498                         expectStartTag(entry, WsmNamespaces::WS_ADDRESSING, "ReferenceParameters");
 499                     
 500                         // Though DSP0227 does not explicitly require wsa:ResourceURI to be present,
 501                         // valid targets of operations must either have a class specific
 502 kumpf          1.2      // ResourceURI to target classes/instances or all classes URI to target
 503                         // the service itself.
 504                         getElementStringValue(
 505                             WsmNamespaces::WS_MAN,
 506                             "ResourceURI",
 507                             endpointReference.resourceUri,
 508                             true);
 509                     
 510                         // wsa:SelectorSet is optional
 511                         if (testStartTag(entry, WsmNamespaces::WS_MAN, "SelectorSet"))
 512                         {
 513                             _parser.putBack(entry);
 514                             // Return value ignored; assumed to succeed because of precheck
 515                             getSelectorSetElement(*endpointReference.selectorSet);
 516                         }
 517                     
 518                         expectEndTag(WsmNamespaces::WS_ADDRESSING, "ReferenceParameters");
 519                     }
 520                     
 521                     Boolean WsmReader::getSelectorEPRElement(
 522                         WsmEndpointReference& endpointReference)
 523 kumpf          1.2  {
 524                         // EPRs in selectors have enclosing wsa:EndpointReference tags
 525                         XmlEntry entry;
 526                         if (!testStartTag(
 527                                 entry, WsmNamespaces::WS_ADDRESSING, "EndpointReference"))
 528                         {
 529                             return false;
 530                         }
 531                     
 532                         getEPRElement(endpointReference);
 533                         expectEndTag(WsmNamespaces::WS_ADDRESSING, "EndpointReference");
 534                         return true;
 535                     }
 536                     
 537                     
 538                     Boolean WsmReader::getInstanceEPRElement(
 539                         WsmEndpointReference& endpointReference)
 540                     {
 541                         XmlEntry entry;
 542                     
 543                         if (!testStartTag(entry, WsmNamespaces::WS_ADDRESSING, "Address"))
 544 kumpf          1.2      {
 545                             return false;
 546                         }
 547                         else
 548                         {
 549                             _parser.putBack(entry);
 550                         }
 551                     
 552                         getEPRElement(endpointReference);
 553                         return true;
 554                     }
 555                     
 556                     void WsmReader::skipElement(XmlEntry& entry)
 557                     {
 558                         const char* elementName = entry.text;
 559                     
 560                         if (entry.type == XmlEntry::EMPTY_TAG)
 561                         {
 562                             return;
 563                         }
 564                     
 565 kumpf          1.2      while (XmlReader::testStartTagOrEmptyTag(_parser, entry))
 566                         {
 567                             skipElement(entry);
 568                         }
 569                     
 570                         // Skip content data, if present
 571                         XmlReader::testContentOrCData(_parser, entry);
 572                     
 573                         XmlReader::expectEndTag(_parser, elementName);
 574                     }
 575                     
 576                     inline void checkDuplicateHeader(
 577                         const char* elementName,
 578                         Boolean isDuplicate)
 579                     {
 580                         // DSP0226 R13.1-9: If a request contains multiple SOAP headers with the
 581                         // same QName from WS-Management, WS-Addressing, or WS-Eventing, the
 582                         // service should not process them and should issue a
 583                         // wsa:InvalidMessageInformationHeaders fault if they are detected.
 584                         // (No SOAP headers are defined by the WS-Transfer and WS-Enumeration
 585                         // specifications.)
 586 kumpf          1.2  
 587                         if (isDuplicate)
 588                         {
 589                             throw WsmFault(
 590                                 WsmFault::wsa_InvalidMessageInformationHeader,
 591                                 MessageLoaderParms(
 592                                     "WsmServer.WsmReader.DUPLICATE_SOAP_HEADER",
 593                                     "Request contains multiple $0 SOAP Header elements.",
 594                                     elementName));
 595                         }
 596                     }
 597                     
 598                     void WsmReader::decodeRequestSoapHeaders(
 599                         String& wsaMessageId,
 600                         String& wsaTo,
 601                         String& wsaAction,
 602                         String& wsaFrom,
 603                         String& wsaReplyTo,
 604                         String& wsaFaultTo,
 605                         String& wsmResourceUri,
 606                         WsmSelectorSet& wsmSelectorSet,
 607 kumpf          1.2      Uint32& wsmMaxEnvelopeSize,
 608                         AcceptLanguageList& wsmLocale,
 609 kumpf          1.3      Boolean& wsmRequestEpr,
 610                         Boolean& wsmRequestItemCount)
 611 kumpf          1.2  {
 612                         // Note: This method does not collect headers that should appear only in
 613                         // responses: wsa:RelatesTo, wsman:RequestedEPR.
 614                     
 615                         XmlEntry entry;
 616                         Boolean gotEntry;
 617                     
 618 mike           1.10     // The wsidentify operation may send an empty header element.
 619                         _parser.setHideEmptyTags(true);
 620 kumpf          1.2      expectStartTag(entry, WsmNamespaces::SOAP_ENVELOPE, "Header");
 621 mike           1.10     _parser.setHideEmptyTags(false);
 622 kumpf          1.2  
 623                         while ((gotEntry = _parser.next(entry)) &&
 624                                ((entry.type == XmlEntry::START_TAG) ||
 625                                 (entry.type == XmlEntry::EMPTY_TAG)))
 626                         {
 627                             int nsType = entry.nsType;
 628                             const char* elementName = entry.localName;
 629                             Boolean needEndTag = (entry.type == XmlEntry::START_TAG);
 630                     
 631                             if ((nsType == WsmNamespaces::WS_ADDRESSING) &&
 632                                 (strcmp(elementName, "To") == 0))
 633                             {
 634                                 checkDuplicateHeader(entry.text, wsaTo.size());
 635                                 wsaTo = getElementContent(entry);
 636                             }
 637                             else if ((nsType == WsmNamespaces::WS_ADDRESSING) &&
 638                                 (strcmp(elementName, "From") == 0))
 639                             {
 640                                 checkDuplicateHeader(entry.text, wsaFrom.size());
 641                                 wsaFrom = getElementContent(entry);
 642                             }
 643 kumpf          1.2          else if ((nsType == WsmNamespaces::WS_ADDRESSING) &&
 644                                 (strcmp(elementName, "ReplyTo") == 0))
 645                             {
 646                                 checkDuplicateHeader(entry.text, wsaReplyTo.size());
 647                                 // ATTN: Reference parameters not handled yet.
 648                                 // DSP0226 R5.4.2-5: Any reference parameters supplied in the
 649                                 // wsa:ReplyTo address shall be included in the actual response
 650                                 // message as top-level headers as specified in WS-Addressing
 651                                 // unless the response is a fault.  If the response is a fault,
 652                                 // the service should include the reference parameters but may
 653                                 // omit these values if the resulting message size would exceed
 654                                 // the encoding limits.
 655                                 getElementStringValue(
 656                                     WsmNamespaces::WS_ADDRESSING, "Address", wsaReplyTo, true);
 657                             }
 658                             else if ((nsType == WsmNamespaces::WS_ADDRESSING) &&
 659                                 (strcmp(elementName, "FaultTo") == 0))
 660                             {
 661                                 checkDuplicateHeader(entry.text, wsaFaultTo.size());
 662                                 // ATTN: Reference parameters not handled yet.
 663                                 // DSP0226 R5.4.3-4: Any reference parameters supplied in the
 664 kumpf          1.2              // wsa:FaultTo address should be included as top-level headers in
 665                                 // the actual fault, as specified in the WS-Addressing
 666                                 // specification.  In some cases, including this information would
 667                                 // cause the fault to exceed encoding size limits, and thus may be
 668                                 // omitted in those cases.
 669                                 getElementStringValue(
 670                                     WsmNamespaces::WS_ADDRESSING, "Address", wsaFaultTo, true);
 671                             }
 672                             else if ((nsType == WsmNamespaces::WS_ADDRESSING) &&
 673                                 (strcmp(elementName, "Action") == 0))
 674                             {
 675                                 checkDuplicateHeader(entry.text, wsaAction.size());
 676                                 wsaAction = getElementContent(entry);
 677                             }
 678                             else if ((nsType == WsmNamespaces::WS_ADDRESSING) &&
 679                                 (strcmp(elementName, "MessageID") == 0))
 680                             {
 681                                 checkDuplicateHeader(entry.text, wsaMessageId.size());
 682                                 wsaMessageId = getElementContent(entry);
 683                             }
 684                             else if ((nsType == WsmNamespaces::WS_MAN) &&
 685 kumpf          1.2              (strcmp(elementName, "ResourceURI") == 0))
 686                             {
 687                                 checkDuplicateHeader(entry.text, wsmResourceUri.size());
 688                                 wsmResourceUri = getElementContent(entry);
 689                             }
 690                             else if ((nsType == WsmNamespaces::WS_MAN) &&
 691                                 (strcmp(elementName, "SelectorSet") == 0))
 692                             {
 693                                 checkDuplicateHeader(entry.text, wsmSelectorSet.selectors.size());
 694                                 _parser.putBack(entry);
 695                                 getSelectorSetElement(wsmSelectorSet);
 696                                 // The end tag has already been consumed.
 697                                 needEndTag = false;
 698                             }
 699                             else if ((nsType == WsmNamespaces::WS_MAN) &&
 700                                 (strcmp(elementName, "OperationTimeout") == 0))
 701                             {
 702                                 if (mustUnderstand(entry))
 703                                 {
 704                                     // DSP0226 R6.1-3: If the service does not support user-defined
 705                                     // timeouts, a wsman:UnsupportedFeature fault should be
 706 kumpf          1.2                  // returned with the following detail code:
 707                                     //     http://schemas.dmtf.org/wbem/wsman/faultDetail/
 708                                     //         OperationTimeout
 709                     
 710                                     throw WsmFault(
 711                                         WsmFault::wsman_UnsupportedFeature,
 712                                         String::EMPTY,
 713                                         ContentLanguageList(),
 714                                         WSMAN_FAULTDETAIL_OPERATIONTIMEOUT);
 715                                 }
 716                     
 717                                 // Note: It is not an error for a compliant service to ignore the
 718                                 // timeout value or treat it as a hint if mustUnderstand is omitted.
 719                     
 720                                 skipElement(entry);
 721                                 // The end tag, if any, has already been consumed.
 722                                 needEndTag = false;
 723                             }
 724                             else if ((nsType == WsmNamespaces::WS_MAN) &&
 725                                 (strcmp(elementName, "MaxEnvelopeSize") == 0))
 726                             {
 727 kumpf          1.2              checkDuplicateHeader(entry.text, wsmMaxEnvelopeSize > 0);
 728                     
 729                                 // DSP0226 R6.2-3: If the mustUnderstand attribute is set to
 730                                 // "false", the service may ignore the header.
 731 kumpf          1.6              wsmMaxEnvelopeSize =
 732 kumpf          1.3                  getUint32ElementContent(entry, "MaxEnvelopeSize");
 733 kumpf          1.2  
 734                                 // DSP0226 R6.2-4:  Services should reject any MaxEnvelopeSize
 735                                 // value less than 8192 octets.  This number is the safe minimum
 736                                 // in which faults can be reliably encoded for all character sets.
 737                                 // If the requested size is less than this, the service should
 738                                 // return a wsman:EncodingLimit fault with the following detail
 739                                 // code:
 740                                 //     http://schemas.dmtf.org/wbem/wsman/1/wsman/faultDetail/
 741                                 //         MinimumEnvelopeLimit
 742                     
 743 kumpf          1.3              if (wsmMaxEnvelopeSize < WSM_MIN_MAXENVELOPESIZE_VALUE)
 744 kumpf          1.2              {
 745                                     throw WsmFault(
 746                                         WsmFault::wsman_EncodingLimit,
 747                                         MessageLoaderParms(
 748                                             "WsmServer.WsmReader.MAXENVELOPESIZE_TOO_SMALL",
 749                                             "The MaxEnvelopeSize $0 is less than "
 750                                                 "minimum allowable value of $1.",
 751 kumpf          1.3                          wsmMaxEnvelopeSize, WSM_MIN_MAXENVELOPESIZE_VALUE),
 752 kumpf          1.2                      WSMAN_FAULTDETAIL_MINIMUMENVELOPELIMIT);
 753                                 }
 754                             }
 755                             else if ((nsType == WsmNamespaces::WS_MAN) &&
 756                                 (strcmp(elementName, "Locale") == 0))
 757                             {
 758                                 checkDuplicateHeader(entry.text, wsmLocale.size());
 759                     
 760                                 if (mustUnderstand(entry))
 761                                 {
 762                                     // DSP0226 R6.3-2: If the mustUnderstand attribute is set to
 763                                     // "true", the service shall ensure that the replies contain
 764                                     // localized information where appropriate, or else the service
 765                                     // shall issue a wsman:UnsupportedFeature fault with the
 766                                     // following detail code:
 767                                     //     http://schemas.dmtf.org/wbem/wsman/1/wsman/faultDetail/
 768                                     //         Locale
 769                                     // A service may always fault if wsman:Locale contains
 770                                     // s:mustUnderstand set to "true", because it may not be able
 771                                     // to ensure that the reply is localized.
 772                     
 773 kumpf          1.2                  throw WsmFault(
 774                                         WsmFault::wsman_UnsupportedFeature,
 775                                         MessageLoaderParms(
 776                                             "WsmServer.WsmReader.LOCALE_NOT_ENSURED",
 777                                             "Translation of responses to a specified locale "
 778                                                 "cannot be ensured."),
 779                                         WSMAN_FAULTDETAIL_LOCALE);
 780                                 }
 781                     
 782                                 // DSP0226 R6.3-1 If the mustUnderstand attribute is omitted or set
 783                                 // to "false", the service should use this value when composing the
 784                                 // response message and adjust any localizable values accordingly.
 785                                 // This use is recommended for most cases. The locale is treated as
 786                                 // a hint in this case.
 787                     
 788                                 // DSP0226 R6.3-3: The value of the xml:lang attribute in the
 789                                 // wsman:Locale header shall be a valid RFC 3066 language code.
 790                     
 791                                 String languageTag;
 792                                 if (getAttributeValue(
 793                                         _parser.getLine(), entry, "xml:lang", languageTag, false))
 794 kumpf          1.2              {
 795                                     wsmLocale.insert(LanguageTag(languageTag), Real32(1.0));
 796                                 }
 797                             }
 798                             else if ((nsType == WsmNamespaces::WS_MAN) &&
 799                                 (strcmp(elementName, "OptionSet") == 0))
 800                             {
 801                                 // DSP0226 R6.4-3: If the mustUnderstand attribute is omitted from
 802                                 // the OptionSet block, the service may ignore the entire
 803                                 // wsman:OptionSet block. If it is present and the service does not
 804                                 // support wsman:OptionSet, the service shall return a
 805                                 // s:NotUnderstood fault.
 806                     
 807                                 if (mustUnderstand(entry))
 808                                 {
 809                                     throw SoapNotUnderstoodFault(
 810                                         _parser.getNamespace(nsType)->extendedName, elementName);
 811                                 }
 812                     
 813                                 skipElement(entry);
 814                                 // The end tag, if any, has already been consumed.
 815 kumpf          1.2              needEndTag = false;
 816                             }
 817                             else if ((nsType == WsmNamespaces::WS_MAN) &&
 818                                 (strcmp(elementName, "RequestEPR") == 0))
 819                             {
 820                                 checkDuplicateHeader(entry.text, wsmRequestEpr);
 821                                 wsmRequestEpr = true;
 822                             }
 823                             else if ((nsType == WsmNamespaces::WS_MAN) &&
 824 kumpf          1.3              (strcmp(elementName, "RequestTotalItemsCountEstimate") == 0))
 825                             {
 826                                 checkDuplicateHeader(entry.text, wsmRequestItemCount);
 827                                 wsmRequestItemCount = true;
 828                             }
 829                             else if ((nsType == WsmNamespaces::WS_MAN) &&
 830 kumpf          1.2              (strcmp(elementName, "FragmentTransfer") == 0))
 831                             {
 832                                 // DSP0226 R7.7-1: A conformant service may support fragment-level
 833                                 // WS-Transfer.  If the service supports fragment-level access, the
 834                                 // service shall not behave as if normal WS-Transfer operations
 835                                 // were in place but shall operate exclusively on the fragments
 836                                 // specified.  If the service does not support fragment-level
 837                                 // access, it shall return a wsman:UnsupportedFeature fault with
 838                                 // the following detail code:
 839                                 //     http://schemas.dmtf.org/wbem/wsman/1/wsman/faultDetail/
 840                                 //         FragmentLevelAccess
 841                     
 842                                 if (mustUnderstand(entry))
 843                                 {
 844                                     throw WsmFault(
 845                                         WsmFault::wsman_UnsupportedFeature,
 846                                         String::EMPTY,
 847                                         ContentLanguageList(),
 848                                         WSMAN_FAULTDETAIL_FRAGMENTLEVELACCESS);
 849                                 }
 850                     
 851 kumpf          1.2              skipElement(entry);
 852                                 // The end tag, if any, has already been consumed.
 853                                 needEndTag = false;
 854                             }
 855                             else if (mustUnderstand(entry))
 856                             {
 857                                 // DSP0226 R5.2-2: If a service cannot comply with a header
 858                                 // marked with mustUnderstand="true", it shall issue an
 859                                 // s:NotUnderstood fault.
 860 kumpf          1.9              XmlNamespace* ns = _parser.getNamespace(nsType);
 861 kumpf          1.2              throw SoapNotUnderstoodFault(
 862 kumpf          1.9                  ns ? ns->extendedName : String::EMPTY, elementName);
 863 kumpf          1.2          }
 864                             else
 865                             {
 866                                 skipElement(entry);
 867                                 // The end tag, if any, has already been consumed.
 868                                 needEndTag = false;
 869                             }
 870                     
 871                             if (needEndTag)
 872                             {
 873                                 expectEndTag(nsType, elementName);
 874                             }
 875                         }
 876                     
 877                         if (gotEntry)
 878                         {
 879                             _parser.putBack(entry);
 880                         }
 881                     
 882                         expectEndTag(WsmNamespaces::SOAP_ENVELOPE, "Header");
 883                     }
 884 kumpf          1.2  
 885                     void WsmReader::getInstanceElement(WsmInstance& instance)
 886                     {
 887                         XmlEntry entry;
 888                         Boolean isInstanceElement = false;
 889                         int nsClassType = 0;
 890                         const char* classNameTag = 0;
 891                     
 892                         // The first tag should be the class name start tag.
 893                         if (_parser.next(entry) && (entry.type == XmlEntry::START_TAG))
 894                         {
 895                             XmlNamespace* ns = _parser.getNamespace(entry.nsType);
 896                             classNameTag = entry.localName;
 897                     
 898                             // Class namespace must be of the following form:
 899                             // http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/<class name>
 900                             if (ns)
 901                             {
 902 mike           1.10             const char* suffix = WsmUtils::skipHostUri(ns->extendedName);
 903                                 const char* pos = strrchr(suffix, '/');
 904                                 if ((pos == suffix +
 905                                     sizeof(WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX) - 1) &&
 906                                     (strncmp(suffix, WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX,
 907                                         sizeof(WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX) - 1) == 0) &&
 908 kumpf          1.2                  (strcmp(pos + 1, classNameTag) == 0))
 909                                 {
 910                                     // All properties must be qualified with the class namespace
 911                                     nsClassType = entry.nsType;
 912                                     instance.setClassName(String(pos + 1));
 913                                     isInstanceElement = true;
 914                                 }
 915                             }
 916                         }
 917                     
 918                         if (!isInstanceElement)
 919                         {
 920                             MessageLoaderParms mlParms(
 921                                 "WsmServer.WsmReader.EXPECTED_INSTANCE_ELEMENT",
 922                                 "Expecting an instance element.");
 923                             throw XmlValidationError(_parser.getLine(), mlParms);
 924                         }
 925                     
 926                         String propName;
 927                         WsmValue propValue;
 928                         while (getPropertyElement(nsClassType, propName, propValue))
 929 kumpf          1.2      {
 930                             instance.addProperty(WsmProperty(propName, propValue));
 931                         }
 932                     
 933                         expectEndTag(nsClassType, classNameTag);
 934                     }
 935                     
 936                     
 937                     Boolean WsmReader::getPropertyElement(
 938                         int nsType,
 939                         String& propName,
 940                         WsmValue& propValue)
 941                     {
 942                         XmlEntry entry;
 943                         const char* propNameTag = 0;
 944                         Boolean firstTime = true;
 945                     
 946                         // Initialize propValue to a null value string
 947                         propValue = WsmValue();
 948                     
 949                         // The first time we enter this loop, propNameTag is NULL. It will
 950 kumpf          1.2      // give us any tag name in the given namespace. Subsequent iterations
 951                         // will get entries with the same name as retrieved in the first
 952                         // iteration.
 953                         while (testStartOrEmptyTag(entry, nsType, propNameTag))
 954                         {
 955                             // Look for xsi:nil="true" to determine of this entry represents
 956                             // a null value.
 957                             const XmlAttribute* attr =
 958                                 entry.findAttribute(WsmNamespaces::XML_SCHEMA_INSTANCE, "nil");
 959                             Boolean isNilValue = (attr && strcmp(attr->value, "true") == 0);
 960                     
 961                             // The only time it's OK to see a null entry is on the first iteration.
 962                             // The above indicates a null property value. If a null entry appears
 963                             // in a sequence representing an array, it's an error.
 964                             if ((isNilValue || propValue.isNull()) && !firstTime)
 965                             {
 966                                 MessageLoaderParms mlParms(
 967                                     "WsmServer.WsmReader.NULL_ARRAY_ELEMENTS",
 968                                     "Setting array elements to null is not supported.");
 969                                 throw XmlValidationError(_parser.getLine(), mlParms);
 970                             }
 971 kumpf          1.2  
 972                             // If we haven't found xsi:nil="true" attribute and this is
 973                             // an empty tag, throw an exception: invalid property value.
 974                             if (entry.type == XmlEntry::EMPTY_TAG && !isNilValue)
 975                             {
 976                                 MessageLoaderParms mlParms(
 977                                     "WsmServer.WsmReader.MISSING_PROPERTY_VALUE",
 978                                     "No value specified for non-null property $0.",
 979                                     entry.text);
 980                                 throw XmlValidationError(_parser.getLine(), mlParms);
 981                             }
 982                     
 983                             if (firstTime)
 984                             {
 985                                 firstTime = false;
 986                     
 987                                 // Set the property name
 988                                 propNameTag = entry.localName;
 989                                 propName = propNameTag;
 990                     
 991                                 if (isNilValue)
 992 kumpf          1.2              {
 993                                     // A null element should be either an empty tag or a start
 994                                     // tag followed by an end tag (no content).
 995                                     if (entry.type == XmlEntry::START_TAG)
 996                                     {
 997                                         expectEndTag(nsType, propNameTag);
 998                                     }
 999                     
1000                                     // No need to set propValue - it's initialized to a null
1001                                     // string value
1002                                 }
1003                                 else
1004                                 {
1005                                     PEGASUS_ASSERT(entry.type == XmlEntry::START_TAG);
1006                                     getValueElement(propValue, nsType, propNameTag);
1007                                 }
1008                             }
1009                             else
1010                             {
1011                                 PEGASUS_ASSERT(entry.type == XmlEntry::START_TAG);
1012                                 WsmValue val;
1013 kumpf          1.2              getValueElement(val, nsType, propNameTag);
1014                                 propValue.add(val);
1015                             }
1016                         }
1017                     
1018                         // If we never entered the main loop, it means that we haven't seen the
1019                         // right initial tags to indicate a class property. In this case firstTime
1020                         // is still set to true.
1021                         return !firstTime;
1022                     }
1023                     
1024                     void WsmReader::getValueElement(
1025                         WsmValue& value, int nsType, const char* propNameTag)
1026                     {
1027                         XmlEntry entry;
1028                     
1029                         if (testEndTag(nsType, propNameTag))
1030                         {
1031                             // It's an empty tag, enter and empty sting value
1032                             value.set(String::EMPTY);
1033                         }
1034 kumpf          1.2      else
1035                         {
1036                             if (XmlReader::testContentOrCData(_parser, entry))
1037                             {
1038                                 // Simple string content
1039 venkat.puvvada 1.7              value.set(String(entry.text, entry.textLen));
1040 kumpf          1.2          }
1041                             else
1042                             {
1043                                 // The value is either an EPR or an embedded instance.
1044                                 WsmEndpointReference epr;
1045                                 if (getInstanceEPRElement(epr))
1046                                 {
1047                                     value.set(epr);
1048                                 }
1049                                 else
1050                                 {
1051                                     // This must be an embedded instance
1052                                     WsmInstance instance;
1053                                     getInstanceElement(instance);
1054                                     value.set(instance);
1055                                 }
1056                             }
1057                             expectEndTag(nsType, propNameTag);
1058                         }
1059                     }
1060                     
1061 kumpf          1.3  void WsmReader::decodeEnumerateBody(
1062 kumpf          1.6      String& expiration,
1063                         WsmbPolymorphismMode& polymorphismMode,
1064                         WsenEnumerationMode& enumerationMode,
1065                         Boolean& optimized,
1066 mike           1.10     Uint32& maxElements,
1067                         String& queryLanguage,
1068                         String& query,
1069                         SharedPtr<WQLSelectStatement>& selectStatement)
1070 kumpf          1.3  {
1071                         XmlEntry entry;
1072                         expectStartOrEmptyTag(
1073                             entry, WsmNamespaces::WS_ENUMERATION, "Enumerate");
1074                         if (entry.type != XmlEntry::EMPTY_TAG)
1075                         {
1076                             Boolean gotEntry;
1077                             while ((gotEntry = _parser.next(entry)) &&
1078                                    ((entry.type == XmlEntry::START_TAG) ||
1079                                     (entry.type == XmlEntry::EMPTY_TAG)))
1080                             {
1081                                 int nsType = entry.nsType;
1082                                 const char* elementName = entry.localName;
1083                                 Boolean needEndTag = (entry.type == XmlEntry::START_TAG);
1084 kumpf          1.6  
1085 kumpf          1.3              if ((nsType == WsmNamespaces::WS_ENUMERATION) &&
1086                                     (strcmp(elementName, "EndTo") == 0))
1087                                 {
1088 kumpf          1.6                  // DSP0226 R5.2.1-1: A conformant service is NOT REQUIRED to
1089                                     // accept a wsen:Enumerate message with an EndTo address as
1090 kumpf          1.3                  // R5.1-4 recommends not supporting the EndEnumerate message,
1091                                     // and may issue a wsman:UnsupportedFeature fault with a detail
1092                                     // code:
1093                                     //     http://schemas.dmtf.org/wbem/wsman/1/wsman/
1094                                     //         faultDetail/AddressingMode
1095                                     throw WsmFault(
1096                                         WsmFault::wsman_UnsupportedFeature,
1097                                         MessageLoaderParms(
1098                                             "WsmServer.WsmReader.ENUMERATE_END_TO_UNSUPPORTED",
1099                                             "Alternate destinations for EnumerationEnd messages "
1100                                             "are not supported."),
1101                                         WSMAN_FAULTDETAIL_ADDRESSINGMODE);
1102                                 }
1103                                 else if ((nsType == WsmNamespaces::WS_ENUMERATION) &&
1104                                     (strcmp(elementName, "Expires") == 0))
1105                                 {
1106                                     checkDuplicateHeader(entry.text, expiration.size());
1107                                     expiration = getElementContent(entry);
1108                                 }
1109 mike           1.10             else if ((nsType == WsmNamespaces::WS_MAN) &&
1110 kumpf          1.3                  (strcmp(elementName, "Filter") == 0))
1111                                 {
1112 mike           1.10                 _parser.putBack(entry);
1113                                     decodeFilter(queryLanguage, query, selectStatement);
1114                                     needEndTag = false;
1115 kumpf          1.3              }
1116                                 else if ((nsType == WsmNamespaces::WS_MAN) &&
1117                                     (strcmp(elementName, "OptimizeEnumeration") == 0))
1118                                 {
1119                                     checkDuplicateHeader(entry.text, optimized);
1120                                     optimized = true;
1121                                 }
1122                                 else if ((nsType == WsmNamespaces::WS_MAN) &&
1123                                     (strcmp(elementName, "MaxElements") == 0))
1124                                 {
1125                                     checkDuplicateHeader(entry.text, maxElements > 0);
1126                                     maxElements = getUint32ElementContent(entry, "MaxElements");
1127                                 }
1128                                 else if ((nsType == WsmNamespaces::WS_MAN) &&
1129                                     (strcmp(elementName, "EnumerationMode") == 0))
1130                                 {
1131 kumpf          1.6                  checkDuplicateHeader(entry.text,
1132 kumpf          1.3                      enumerationMode != WSEN_EM_UNKNOWN);
1133                                     const char* content = getElementContent(entry);
1134                                     if (strcmp(content, "EnumerateEPR") == 0)
1135                                     {
1136                                         enumerationMode = WSEN_EM_EPR;
1137                                     }
1138                                     else if (strcmp(content, "EnumerateObjectAndEPR") == 0)
1139                                     {
1140                                         enumerationMode = WSEN_EM_OBJECT_AND_EPR;
1141                                     }
1142                                     else
1143                                     {
1144                                         throw WsmFault(
1145                                             WsmFault::wsman_UnsupportedFeature,
1146                                             MessageLoaderParms(
1147                                                 "WsmServer.WsmReader.ENUMERATE_"
1148                                                     "ENUM_MODE_UNSUPPORTED",
1149 kumpf          1.6                              "Enumeration mode \"$0\" is not supported.",
1150 kumpf          1.3                              content),
1151                                             WSMAN_FAULTDETAIL_ENUMERATION_MODE_UNSUPPORTED);
1152                                     }
1153                                 }
1154                                 else if ((nsType == WsmNamespaces::WS_CIM_BINDING) &&
1155                                     (strcmp(elementName, "PolymorphismMode") == 0))
1156                                 {
1157 kumpf          1.6                  checkDuplicateHeader(entry.text,
1158 kumpf          1.3                      polymorphismMode != WSMB_PM_UNKNOWN);
1159                                     const char* content = getElementContent(entry);
1160                                     if (strcmp(content, "ExcludeSubClassProperties") == 0)
1161                                     {
1162                                         polymorphismMode = WSMB_PM_EXCLUDE_SUBCLASS_PROPERTIES;
1163                                     }
1164                                     else if (strcmp(content, "IncludeSubClassProperties") == 0)
1165                                     {
1166                                         polymorphismMode = WSMB_PM_INCLUDE_SUBCLASS_PROPERTIES;
1167                                     }
1168                                     else
1169                                     {
1170                                         throw WsmFault(
1171                                             WsmFault::wsmb_PolymorphismModeNotSupported,
1172                                             MessageLoaderParms(
1173                                                 "WsmServer.WsmReader.ENUMERATE_"
1174                                                     "POLYMORPHISM_MODE_UNSUPPORTED",
1175 kumpf          1.6                              "Polymorphism mode \"$0\" is not supported.",
1176 kumpf          1.3                              content));
1177                                     }
1178                                 }
1179                                 else if (mustUnderstand(entry))
1180                                 {
1181                                     // DSP0226 R5.2-2: If a service cannot comply with a header
1182                                     // marked with mustUnderstand="true", it shall issue an
1183                                     // s:NotUnderstood fault.
1184 kumpf          1.9                  XmlNamespace* ns = _parser.getNamespace(nsType);
1185 kumpf          1.3                  throw SoapNotUnderstoodFault(
1186 kumpf          1.9                      ns ? ns->extendedName : String::EMPTY, elementName);
1187 kumpf          1.3              }
1188                                 else
1189                                 {
1190                                     skipElement(entry);
1191                                     // The end tag, if any, has already been consumed.
1192                                     needEndTag = false;
1193                                 }
1194                     
1195                                 if (needEndTag)
1196                                 {
1197                                     expectEndTag(nsType, elementName);
1198                                 }
1199                             }
1200                     
1201                             if (gotEntry)
1202                             {
1203                                 _parser.putBack(entry);
1204                             }
1205                     
1206                             expectEndTag(WsmNamespaces::WS_ENUMERATION, "Enumerate");
1207                         }
1208 kumpf          1.3  }
1209                     
1210                     void WsmReader::decodePullBody(
1211 kumpf          1.6      Uint64& enumerationContext,
1212                         String& maxTime,
1213 kumpf          1.3      Uint32& maxElements,
1214                         Uint32& maxCharacters)
1215                     {
1216                         Boolean seenEnumContext = false;
1217                         XmlEntry entry;
1218 kumpf          1.8      expectStartTag(entry, WsmNamespaces::WS_ENUMERATION, "Pull");
1219                     
1220                         Boolean gotEntry;
1221                         while ((gotEntry = _parser.next(entry)) &&
1222                                ((entry.type == XmlEntry::START_TAG) ||
1223                                 (entry.type == XmlEntry::EMPTY_TAG)))
1224                         {
1225                             int nsType = entry.nsType;
1226                             const char* elementName = entry.localName;
1227                             Boolean needEndTag = (entry.type == XmlEntry::START_TAG);
1228                     
1229                             if ((nsType == WsmNamespaces::WS_ENUMERATION) &&
1230                                 (strcmp(elementName, "EnumerationContext") == 0))
1231                             {
1232                                 checkDuplicateHeader(entry.text, seenEnumContext);
1233                                 seenEnumContext = true;
1234                                 enumerationContext = getEnumerationContext(entry);
1235                             }
1236                             else if ((nsType == WsmNamespaces::WS_ENUMERATION) &&
1237                                 (strcmp(elementName, "MaxTime") == 0))
1238                             {
1239 kumpf          1.8              checkDuplicateHeader(entry.text, maxTime.size());
1240                                 maxTime = getElementContent(entry);
1241                             }
1242                             else if ((nsType == WsmNamespaces::WS_ENUMERATION) &&
1243                                 (strcmp(elementName, "MaxCharacters") == 0))
1244                             {
1245                                 checkDuplicateHeader(entry.text, maxCharacters > 0);
1246                                 maxCharacters = getUint32ElementContent(entry, "MaxCharacters");
1247                             }
1248                             else if ((nsType == WsmNamespaces::WS_ENUMERATION) &&
1249                                 (strcmp(elementName, "MaxElements") == 0))
1250                             {
1251                                 checkDuplicateHeader(entry.text, maxElements > 0);
1252                                 maxElements = getUint32ElementContent(entry, "MaxElements");
1253                             }
1254                             else if (mustUnderstand(entry))
1255                             {
1256                                 // DSP0226 R5.2-2: If a service cannot comply with a header
1257                                 // marked with mustUnderstand="true", it shall issue an
1258                                 // s:NotUnderstood fault.
1259 kumpf          1.9              XmlNamespace* ns = _parser.getNamespace(nsType);
1260 kumpf          1.8              throw SoapNotUnderstoodFault(
1261 kumpf          1.9                  ns ? ns->extendedName : String::EMPTY, elementName);
1262 kumpf          1.8          }
1263                             else
1264                             {
1265                                 skipElement(entry);
1266                                 // The end tag, if any, has already been consumed.
1267                                 needEndTag = false;
1268 kumpf          1.3          }
1269                     
1270 kumpf          1.8          if (needEndTag)
1271 kumpf          1.3          {
1272 kumpf          1.8              expectEndTag(nsType, elementName);
1273 kumpf          1.3          }
1274 kumpf          1.8      }
1275                     
1276                         if (gotEntry)
1277                         {
1278                             _parser.putBack(entry);
1279                         }
1280 kumpf          1.3  
1281 kumpf          1.8      // EnumerationContext is required; return a fault if it is missing.
1282                         if (!seenEnumContext)
1283                         {
1284                             expectStartTag(
1285                                 entry, WsmNamespaces::WS_ENUMERATION, "EnumerationContext");
1286 kumpf          1.3      }
1287 kumpf          1.8  
1288                         expectEndTag(WsmNamespaces::WS_ENUMERATION, "Pull");
1289 kumpf          1.3  }
1290                     
1291                     void WsmReader::decodeReleaseBody(Uint64& enumerationContext)
1292                     {
1293                         Boolean seenEnumContext = false;
1294                         XmlEntry entry;
1295 kumpf          1.8      expectStartTag(entry, WsmNamespaces::WS_ENUMERATION, "Release");
1296                     
1297                         Boolean gotEntry;
1298                         while ((gotEntry = _parser.next(entry)) &&
1299                                ((entry.type == XmlEntry::START_TAG) ||
1300                                 (entry.type == XmlEntry::EMPTY_TAG)))
1301                         {
1302                             int nsType = entry.nsType;
1303                             const char* elementName = entry.localName;
1304                             Boolean needEndTag = (entry.type == XmlEntry::START_TAG);
1305                     
1306                             if ((nsType == WsmNamespaces::WS_ENUMERATION) &&
1307                                 (strcmp(elementName, "EnumerationContext") == 0))
1308                             {
1309                                 checkDuplicateHeader(entry.text, seenEnumContext);
1310                                 seenEnumContext = true;
1311                                 enumerationContext = getEnumerationContext(entry);
1312                             }
1313                             else if (mustUnderstand(entry))
1314                             {
1315                                 // DSP0226 R5.2-2: If a service cannot comply with a header
1316 kumpf          1.8              // marked with mustUnderstand="true", it shall issue an
1317                                 // s:NotUnderstood fault.
1318 kumpf          1.9              XmlNamespace* ns = _parser.getNamespace(nsType);
1319 kumpf          1.8              throw SoapNotUnderstoodFault(
1320 kumpf          1.9                  ns ? ns->extendedName : String::EMPTY, elementName);
1321 kumpf          1.8          }
1322                             else
1323                             {
1324                                 skipElement(entry);
1325                                 // The end tag, if any, has already been consumed.
1326                                 needEndTag = false;
1327 kumpf          1.3          }
1328                     
1329 kumpf          1.8          if (needEndTag)
1330 kumpf          1.3          {
1331 kumpf          1.8              expectEndTag(nsType, elementName);
1332 kumpf          1.3          }
1333 kumpf          1.8      }
1334                     
1335                         if (gotEntry)
1336                         {
1337                             _parser.putBack(entry);
1338                         }
1339 kumpf          1.3  
1340 kumpf          1.8      // EnumerationContext is required; return a fault if it is missing.
1341                         if (!seenEnumContext)
1342                         {
1343                             expectStartTag(
1344                                 entry, WsmNamespaces::WS_ENUMERATION, "EnumerationContext");
1345 kumpf          1.3      }
1346 kumpf          1.8  
1347                         expectEndTag(WsmNamespaces::WS_ENUMERATION, "Release");
1348 kumpf          1.3  }
1349                     
1350 mike           1.10 void WsmReader::decodeInvokeInputBody(
1351                         const String& className,
1352                         const String& methodName,
1353                         WsmInstance& instance)
1354                     {
1355                         XmlEntry entry;
1356                     
1357                         //
1358                         // Parse the <s:Body> element. Here is an example:
1359                         //
1360                         //   <p:Foo_INPUT xmlns:p=
1361                         //     "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SomeClass">
1362                         //     <p:Arg1>
1363                         //       ...
1364                         //     </p:Arg1>
1365                         //     <p:Arg2>
1366                         //       ...
1367                         //     </p:Arg2>
1368                         //   </p:Foo_INPUT>
1369                         //
1370                     
1371 mike           1.10     // Expect <METHODNAME_INPUT>
1372                         Buffer tagName;
1373                         tagName.append(methodName.getCString(), methodName.size());
1374                         tagName.append("_INPUT", 6);
1375                     
1376                         _parser.setHideEmptyTags(true);
1377                         int nsType = expectStartTag(entry, tagName.getData());
1378                     
1379                         // The following elements are input parameter.
1380                         String name;
1381                         WsmValue value;
1382                     
1383                         while (getPropertyElement(nsType, name, value))
1384                         {
1385                             instance.addProperty(WsmProperty(name, value));
1386                         }
1387                     
1388                         // Expect </METHODNAME_INPUT>
1389                         expectEndTag(nsType, tagName.getData());
1390                         _parser.setHideEmptyTags(false);
1391                     }
1392 mike           1.10 
1393                     void WsmReader::decodeFilter(
1394                         String& queryLanguage,
1395                         String& query,
1396                         SharedPtr<WQLSelectStatement>& selectStatement)
1397                     {
1398                         // Expect "Filter" element.
1399                         _parser.setHideEmptyTags(true);
1400                         XmlEntry entry;
1401                         expectStartTag(entry, WsmNamespaces::WS_MAN, "Filter");
1402                     
1403                         // Check Filter.Dialect attribute.
1404                         {
1405                             const char* value;
1406                     
1407                             if (!entry.getAttributeValue("Dialect", value))
1408                             {
1409                                 MessageLoaderParms parms(
1410                                     "WsmServer.WsmReader.MISSING_ATTRIBUTE",
1411                                     "The attribute $0.$1 is missing.", "Filter", "Dialect");
1412                                 throw XmlValidationError(_parser.getLine(), parms);
1413 mike           1.10         }
1414                     
1415                             const char* suffix = WsmUtils::skipHostUri(value);
1416                     
1417                             if (strcmp(suffix, WSMAN_FILTER_DIALECT_WQL_SUFFIX) != 0)
1418                             {
1419                                 MessageLoaderParms parms(
1420                                     "WsmServer.WsmReader.UNSUPPORTED_FILTER_DIALECT",
1421                                     "Unsupported filter dialect: \"$0\".",
1422                                     value);
1423                                 throw WsmFault(
1424                                     WsmFault::wsen_FilterDialectRequestedUnavailable, parms);
1425                             }
1426                     
1427                             // We only support "WQL" so far.
1428                             queryLanguage = "WQL";
1429                         }
1430                     
1431                         // Expect query expression (contains the query text).
1432                     
1433                         expectContentOrCData(entry);
1434 mike           1.10     query = entry.text;
1435                     
1436                         // Compile the query filter.
1437                     
1438                         try
1439                         {
1440                             selectStatement.reset(new WQLSelectStatement);
1441                             WQLParser::parse(query, *selectStatement.get());
1442                         }
1443                         catch (ParseError& e)
1444                         {
1445                             MessageLoaderParms parms(
1446                                 "WsmServer.WsmReader.INVALID_FILTER_QUERY_EXPRESSION",
1447                                 "Invalid filter query expression: \"$0\".",
1448                                 entry.text);
1449                             throw WsmFault(WsmFault::wsen_CannotProcessFilter, parms);
1450                         }
1451                     
1452                         // Expect </Filter>
1453                     
1454                         expectEndTag(WsmNamespaces::WS_MAN, "Filter");
1455 mike           1.10     _parser.setHideEmptyTags(false);
1456                     }
1457                     
1458 kumpf          1.2  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2