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
|