1 kumpf 1.2 //%/////////////////////////////////////////////////////////////////////////////
|
2 chip 1.1 //
|
3 kumpf 1.6 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
|
5 chip 1.1 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
|
12 kumpf 1.6 //
|
13 chip 1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
14 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 //==============================================================================
23 //
|
24 kumpf 1.2 // Author: Mike Brasher (mbrasher@bmc.com)
|
25 chip 1.1 //
|
26 kumpf 1.2 // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
27 chip 1.1 //
28 //%/////////////////////////////////////////////////////////////////////////////
29
|
30 kumpf 1.2 #include <Pegasus/Common/Config.h>
31 #include <cctype>
32 #include <cstring>
33 #include "HashTable.h"
34 #include "CIMObjectPath.h"
35 #include "Indentor.h"
36 #include "CIMName.h"
37 #include "Destroyer.h"
38 #include "XmlWriter.h"
39 #include "XmlReader.h"
40 #include "Array.h"
41 #include "CIMOMPort.h"
|
42 chip 1.1
43 PEGASUS_NAMESPACE_BEGIN
|
44 kumpf 1.2
45 #define PEGASUS_ARRAY_T KeyBinding
46 # include "ArrayImpl.h"
47 #undef PEGASUS_ARRAY_T
48
49 #define PEGASUS_ARRAY_T CIMObjectPath
50 # include "ArrayImpl.h"
51 #undef PEGASUS_ARRAY_T
52
53 // ATTN: KS May 2002 P0 Add resolve method to CIMObjectPath.
54 // Add a resolve method to this class to verify that the
55 // reference is correct (that the class name corresponds to a real
56 // class and that the property names are really keys and that all keys
57 // of the class or used. Also be sure that there is a valid conversion
58 // between the string value and the value of that property).
59 //
60 // ATTN: also check to see that the reference refers to a class that is the
61 // same or derived from the _className member.
62
63 ////////////////////////////////////////////////////////////////////////////////
64 //
65 kumpf 1.2 // Local routines:
66 //
67 ////////////////////////////////////////////////////////////////////////////////
68
69 static String _escapeSpecialCharacters(const String& str)
70 {
71 String result;
72
73 for (Uint32 i = 0, n = str.size(); i < n; i++)
74 {
75 switch (str[i])
76 {
77 case '\n':
78 result += "\\n";
79 break;
80
81 case '\r':
82 result += "\\r";
83 break;
84
85 case '\t':
86 kumpf 1.2 result += "\\t";
87 break;
88
89 case '"':
90 result += "\\\"";
91 break;
92
93 default:
94 result += str[i];
95 }
96 }
97
98 return result;
99 }
100
101 static void _BubbleSort(Array<KeyBinding>& x)
102 {
103 Uint32 n = x.size();
104
105 if (n < 2)
106 return;
107 kumpf 1.2
108 for (Uint32 i = 0; i < n - 1; i++)
109 {
110 for (Uint32 j = 0; j < n - 1; j++)
111 {
112 if (String::compareNoCase(x[j].getName(), x[j+1].getName()) > 0)
113 {
114 KeyBinding t = x[j];
115 x[j] = x[j+1];
116 x[j+1] = t;
117 }
118 }
119 }
120 }
121
122 ////////////////////////////////////////////////////////////////////////////////
123 //
124 // KeyBinding
125 //
126 ////////////////////////////////////////////////////////////////////////////////
127
128 kumpf 1.2 class KeyBindingRep
129 {
130 public:
131 KeyBindingRep()
132 {
133 }
134
135 KeyBindingRep(const KeyBindingRep& x)
136 : _name(x._name), _value(x._value), _type(x._type)
137 {
138 }
139
140 KeyBindingRep(
|
141 kumpf 1.7 const CIMName& name,
|
142 kumpf 1.2 const String& value,
143 KeyBinding::Type type)
144 : _name(name), _value(value), _type(type)
145 {
146 }
147
148 ~KeyBindingRep()
149 {
150 }
151
152 KeyBindingRep& operator=(const KeyBindingRep& x)
153 {
154 if (&x != this)
155 {
156 _name = x._name;
157 _value = x._value;
158 _type = x._type;
159 }
160 return *this;
161 }
162
|
163 kumpf 1.7 CIMName _name;
|
164 kumpf 1.2 String _value;
165 KeyBinding::Type _type;
166 };
167
168
169 KeyBinding::KeyBinding()
170 {
171 _rep = new KeyBindingRep();
172 }
173
174 KeyBinding::KeyBinding(const KeyBinding& x)
175 {
176 _rep = new KeyBindingRep(*x._rep);
177 }
178
|
179 kumpf 1.7 KeyBinding::KeyBinding(const CIMName& name, const String& value, Type type)
|
180 kumpf 1.2 {
181 _rep = new KeyBindingRep(name, value, type);
182 }
183
184 KeyBinding::~KeyBinding()
185 {
186 delete _rep;
187 }
188
189 KeyBinding& KeyBinding::operator=(const KeyBinding& x)
190 {
191 *_rep = *x._rep;
192 return *this;
193 }
194
|
195 kumpf 1.7 const CIMName& KeyBinding::getName() const
|
196 kumpf 1.2 {
197 return _rep->_name;
198 }
199
|
200 kumpf 1.7 void KeyBinding::setName(const CIMName& name)
|
201 kumpf 1.2 {
202 _rep->_name = name;
203 }
204
205 const String& KeyBinding::getValue() const
206 {
207 return _rep->_value;
208 }
209
210 void KeyBinding::setValue(const String& value)
211 {
212 _rep->_value = value;
213 }
214
215 KeyBinding::Type KeyBinding::getType() const
216 {
217 return _rep->_type;
218 }
219
220 void KeyBinding::setType(KeyBinding::Type type)
221 {
222 kumpf 1.2 _rep->_type = type;
223 }
224
225 const char* KeyBinding::typeToString(KeyBinding::Type type)
226 {
227 switch (type)
228 {
229 case KeyBinding::BOOLEAN:
230 return "boolean";
231
232 case KeyBinding::STRING:
233 return "string";
234
235 case KeyBinding::NUMERIC:
236 return "numeric";
237
238 case KeyBinding::REFERENCE:
239 default:
240 PEGASUS_ASSERT(false);
241 }
242
243 kumpf 1.2 return "unknown";
244 }
245
246 Boolean operator==(const KeyBinding& x, const KeyBinding& y)
247 {
248 return
|
249 kumpf 1.7 x.getName().equal(y.getName()) &&
|
250 kumpf 1.2 String::equal(x.getValue(), y.getValue()) &&
251 x.getType() == y.getType();
252 }
253
254
255 ////////////////////////////////////////////////////////////////////////////////
256 //
257 // CIMObjectPath
258 //
259 ////////////////////////////////////////////////////////////////////////////////
260
261 class CIMObjectPathRep
262 {
263 public:
264 CIMObjectPathRep()
265 {
266 }
267
268 CIMObjectPathRep(const CIMObjectPathRep& x)
269 : _host(x._host), _nameSpace(x._nameSpace),
270 _className(x._className), _keyBindings(x._keyBindings)
271 kumpf 1.2 {
272 }
273
274 CIMObjectPathRep(
275 const String& host,
|
276 kumpf 1.7 const CIMNamespaceName& nameSpace,
277 const CIMName& className,
|
278 kumpf 1.2 const Array<KeyBinding>& keyBindings)
279 : _host(host), _nameSpace(nameSpace),
280 _className(className), _keyBindings(keyBindings)
281 {
282 }
283
284 ~CIMObjectPathRep()
285 {
286 }
287
288 CIMObjectPathRep& operator=(const CIMObjectPathRep& x)
289 {
290 if (&x != this)
291 {
292 _host = x._host;
293 _nameSpace = x._nameSpace;
294 _className = x._className;
295 _keyBindings = x._keyBindings;
296 }
297 return *this;
298 }
299 kumpf 1.2
300 //
301 // Contains port as well (e.g., myhost:1234).
302 //
303 String _host;
304
|
305 kumpf 1.7 CIMNamespaceName _nameSpace;
306 CIMName _className;
|
307 kumpf 1.2 Array<KeyBinding> _keyBindings;
308 };
309
310
311 CIMObjectPath::CIMObjectPath()
312 {
313 _rep = new CIMObjectPathRep();
314 }
315
316 CIMObjectPath::CIMObjectPath(const CIMObjectPath& x)
317 {
318 _rep = new CIMObjectPathRep(*x._rep);
319 }
320
321 CIMObjectPath::CIMObjectPath(const String& objectName)
322 {
323 // Test the objectName out to see if we get an exception
324 CIMObjectPath tmpRef;
325 tmpRef.set(objectName);
326
327 _rep = new CIMObjectPathRep(*tmpRef._rep);
328 kumpf 1.2 }
329
330 CIMObjectPath::CIMObjectPath(const char* objectName)
331 {
332 // Test the objectName out to see if we get an exception
333 CIMObjectPath tmpRef;
334 tmpRef.set(objectName);
335
336 _rep = new CIMObjectPathRep(*tmpRef._rep);
337 }
338
339 CIMObjectPath::CIMObjectPath(
340 const String& host,
|
341 kumpf 1.7 const CIMNamespaceName& nameSpace,
342 const CIMName& className,
|
343 kumpf 1.2 const Array<KeyBinding>& keyBindings)
344 {
345 // Test the objectName out to see if we get an exception
346 CIMObjectPath tmpRef;
347 tmpRef.set(host, nameSpace, className, keyBindings);
348
349 _rep = new CIMObjectPathRep(*tmpRef._rep);
350 }
351
352 CIMObjectPath::~CIMObjectPath()
353 {
354 delete _rep;
355 }
356
357 CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x)
358 {
359 *_rep = *x._rep;
360 return *this;
361 }
362
363 void CIMObjectPath::clear()
364 kumpf 1.2 {
365 _rep->_host.clear();
366 _rep->_nameSpace.clear();
367 _rep->_className.clear();
368 _rep->_keyBindings.clear();
369 }
370
371 void CIMObjectPath::set(
372 const String& host,
|
373 kumpf 1.7 const CIMNamespaceName& nameSpace,
374 const CIMName& className,
|
375 kumpf 1.8 const Array<KeyBinding>& keyBindings)
|
376 kumpf 1.2 {
377 setHost(host);
378 setNameSpace(nameSpace);
379 setClassName(className);
380 setKeyBindings(keyBindings);
381 }
382
383 Boolean CIMObjectPath::_parseHostElement(
384 const String& objectName,
385 char*& p,
386 String& host) throw(IllformedObjectName)
387 {
388 // See if there is a host name (true if it begins with "//"):
389 // Host is of the from <hostname>-<port> and begins with "//"
390 // and ends with "/":
391
392 if (p[0] != '/' || p[1] != '/')
393 {
394 return false;
395 }
396
397 kumpf 1.2 p += 2;
398
399 //----------------------------------------------------------------------
400 // Validate the hostname. Hostnames must match the following
401 // regular expression: "[A-Za-z][A-Za-z0-9-]*"
402 //----------------------------------------------------------------------
403
404 char* q = p;
405
406 if (!isalpha(*q))
407 throw IllformedObjectName(objectName);
408
409 q++;
410
411 while (isalnum(*q) || *q == '-')
412 q++;
413
414 // We now expect a port (or default the port).
415
416 if (*q == ':')
417 {
418 kumpf 1.2 q++;
419 // Check for a port number:
420
421 if (!isdigit(*q))
422 throw IllformedObjectName(objectName);
423
424 while (isdigit(*q))
425 q++;
426
427 // Finally, assign the host name:
428
429 host.assign(p, q - p);
430 }
431 else
432 {
433 host.assign(p, q - p);
434
435 // Assign the default port number:
436
437 host.append(":");
438 host.append(PEGASUS_CIMOM_DEFAULT_PORT_STRING);
439 kumpf 1.2 }
440
441 // Check for slash terminating the entire sequence:
442
443 if (*q != '/')
444 {
445 host.clear();
446 throw IllformedObjectName(objectName);
447 }
448
449 p = ++q;
450
451 return true;
452 }
453
454 Boolean CIMObjectPath::_parseNamespaceElement(
455 const String& objectName,
456 char*& p,
|
457 kumpf 1.7 CIMNamespaceName& nameSpace)
|
458 kumpf 1.2 {
459 // If we don't find a valid namespace name followed by a ':', we
460 // assume we're not looking at a namespace name.
461
|
462 kumpf 1.7 char* colon = strchr(p, ':');
463 if (!colon)
464 {
465 return false;
466 }
467
|
468 kumpf 1.2 //----------------------------------------------------------------------
469 // Validate the namespace path. Namespaces must match the following
470 // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*"
471 //----------------------------------------------------------------------
472
|
473 kumpf 1.7 String namespaceName = String(p, colon - p);
474 if (!CIMNamespaceName::legal(namespaceName))
|
475 kumpf 1.2 {
|
476 kumpf 1.7 throw IllformedObjectName(objectName);
|
477 kumpf 1.2 }
|
478 kumpf 1.7 nameSpace = namespaceName;
|
479 kumpf 1.2
|
480 kumpf 1.7 p = colon+1;
|
481 kumpf 1.2 return true;
482 }
483
484 /**
485 ATTN: RK - Association classes have keys whose types are
486 references. These reference values must be treated specially
487 in the XML encoding, using the VALUE.REFERENCE tag structure.
488
489 Pegasus had been passing reference values simply as String
490 values. For example, EnumerateInstanceNames returned
491 KEYVALUEs of string type rather than VALUE.REFERENCEs.
492
493 I've modified the XmlReader::getKeyBindingElement() and
494 XmlWriter::appendInstanceNameElement() methods to read and write
495 the XML in the proper format. However, making that change
496 required that a CIMObjectPath object be able to distinguish
497 between a key of String type and a key of reference type.
498
499 I've modified the String format of CIMObjectPaths slightly to
500 allow efficient processing of references whose keys are also
501 of reference type. The "official" form uses the same
502 kumpf 1.2 encoding for key values of String type and of reference type,
503 and so it would be necessary to retrieve the class definition
504 and look up the types of the key properties to determine how
505 to treat the key values. This is clearly too inefficient for
506 internal transformations between CIMObjectPaths and String
507 values.
508
509 The workaround is to encode a 'R' at the beginning of the
510 value for a key of reference type (before the opening '"').
511 This allows the parser to know a priori whether the key is of
512 String or reference type.
513
514 In this example:
515
516 MyClass.Key1="StringValue",Key2=R"RefClass.KeyA="StringA",KeyB=10"
517
518 Property Key1 of class MyClass is of String type, and so it
519 gets the usual encoding. Key2 is a reference property, so
520 the extra 'R' is inserted before its encoded value. Note
521 that this algorithm is recursive, such that RefClass could
522 include KeyC of reference type, which would also get encoded
523 kumpf 1.2 with the 'R' notation.
524
525 The toString() method inserts the 'R' to provide symmetry. A
526 new KeyBinding type (REFERENCE) has been defined to denote
527 keys in a CIMObjectPath that are of reference type. This
528 KeyBinding type must be used appropriately for
529 CIMObjectPath::toString() to behave correctly.
530
531 A result of this change is that instances names in the
532 instance repository will include this extra 'R' character.
533 Note that for user-facing uses of the String encoding of
534 instance names (such as might appear in MOF for static
535 association instances or in the CGI client), this solution
536 is non-standard and therefore unacceptable. It is likely
537 that these points will need to process the more expensive
538 operation of retrieving the class definition to determine
539 the key property types.
540 */
541 void CIMObjectPath::_parseKeyBindingPairs(
542 const String& objectName,
543 char*& p,
544 kumpf 1.2 Array<KeyBinding>& keyBindings) throw(IllformedObjectName)
545 {
546 // Get the key-value pairs:
547
548 while (*p)
549 {
550 // Get key part:
551
|
552 kumpf 1.5 char* equalsign = strchr(p, '=');
553 if (!equalsign)
|
554 kumpf 1.2 {
555 throw IllformedObjectName(objectName);
556 }
557
|
558 kumpf 1.5 *equalsign = 0;
|
559 kumpf 1.7 CIMName keyString(p);
|
560 kumpf 1.2
561 if (!CIMName::legal(keyString))
562 throw IllformedObjectName(objectName);
563
564 // Get the value part:
565
566 String valueString;
|
567 kumpf 1.5 p = equalsign + 1;
|
568 kumpf 1.2 KeyBinding::Type type;
569
570 if (*p == 'R')
571 {
572 p++;
573
574 type = KeyBinding::REFERENCE;
575
576 if (*p++ != '"')
577 throw IllformedObjectName(objectName);
578
579 while (*p && *p != '"')
580 {
581 // ATTN: need to handle special characters here:
582
583 if (*p == '\\')
584 *p++;
585
586 valueString.append(*p++);
587 }
588
589 kumpf 1.2 if (*p++ != '"')
590 throw IllformedObjectName(objectName);
591 }
592 else if (*p == '"')
593 {
594 p++;
595
596 type = KeyBinding::STRING;
597
598 while (*p && *p != '"')
599 {
600 // ATTN: need to handle special characters here:
601
602 if (*p == '\\')
603 *p++;
604
605 valueString.append(*p++);
606 }
607
608 if (*p++ != '"')
609 throw IllformedObjectName(objectName);
610 kumpf 1.2 }
611 else if (toupper(*p) == 'T' || toupper(*p) == 'F')
612 {
613 type = KeyBinding::BOOLEAN;
614
615 char* r = p;
616 Uint32 n = 0;
617
618 while (*r && *r != ',')
619 {
620 *r = toupper(*r);
621 r++;
622 n++;
623 }
624
625 if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) ||
626 ((strncmp(p, "FALSE", n) == 0) && n == 5)))
627 throw IllformedObjectName(objectName);
628
629 valueString.assign(p, n);
630
631 kumpf 1.2 p = p + n;
632 }
633 else
634 {
635 type = KeyBinding::NUMERIC;
636
637 char* r = p;
638 Uint32 n = 0;
639
640 while (*r && *r != ',')
641 {
642 r++;
643 n++;
644 }
645
646 Boolean isComma = false;
647 if (*r)
648 {
649 *r = '\0';
650 isComma = true;
651 }
652 kumpf 1.2
653 Sint64 x;
654
655 if (!XmlReader::stringToSignedInteger(p, x))
656 throw IllformedObjectName(objectName);
657
658 valueString.assign(p, n);
659
660 if (isComma)
661 {
662 *r = ',';
663 }
664
665 p = p + n;
666 }
667
668 keyBindings.append(KeyBinding(keyString, valueString, type));
669
670 if (*p)
671 {
672 if (*p++ != ',')
673 kumpf 1.2 {
674 throw IllformedObjectName(objectName);
675 }
676 }
677 }
678
679 _BubbleSort(keyBindings);
680 }
681
682 void CIMObjectPath::set(const String& objectName) throw(IllformedObjectName)
683 {
684 clear();
685
686 //--------------------------------------------------------------------------
687 // We will extract components from an object name. Here is an sample
688 // object name:
689 //
690 // //atp:9999/root/cimv25:TennisPlayer.first="Patrick",last="Rafter"
691 //--------------------------------------------------------------------------
692
693 // Convert to a C String first:
694 kumpf 1.2
|
695 kumpf 1.4 char* p = objectName.allocateCString();
|
696 kumpf 1.2 ArrayDestroyer<char> destroyer(p);
697 Boolean gotHost;
698 Boolean gotNamespace;
699
700 gotHost = _parseHostElement(objectName, p, _rep->_host);
701 gotNamespace = _parseNamespaceElement(objectName, p, _rep->_nameSpace);
702
703 if (gotHost && !gotNamespace)
704 {
705 throw IllformedObjectName(objectName);
706 }
707
708 // Extract the class name:
709
710 char* dot = strchr(p, '.');
711
712 if (!dot)
713 {
714 if (!CIMName::legal(p))
715 {
716 throw IllformedObjectName(objectName);
717 kumpf 1.2 }
718
719 // ATTN: remove this later: a reference should only be able to hold
720 // an instance name.
721
|
722 kumpf 1.7 _rep->_className = p;
|
723 kumpf 1.2 return;
724 }
725
|
726 kumpf 1.7 String className = String(p, dot - p);
727 if (!CIMName::legal(className))
728 {
729 throw IllformedObjectName(objectName);
730 }
731 _rep->_className = className;
|
732 kumpf 1.2
733 // Advance past dot:
734
735 p = dot + 1;
736
737 _parseKeyBindingPairs(objectName, p, _rep->_keyBindings);
738 }
739
740 CIMObjectPath& CIMObjectPath::operator=(const String& objectName)
741 {
742 set(objectName);
743 return *this;
744 }
745
746 CIMObjectPath& CIMObjectPath::operator=(const char* objectName)
747 {
748 set(objectName);
749 return *this;
750 }
751
752 const String& CIMObjectPath::getHost() const
753 kumpf 1.2 {
754 return _rep->_host;
755 }
756
757 void CIMObjectPath::setHost(const String& host)
758 {
759 _rep->_host = host;
760 }
761
|
762 kumpf 1.7 const CIMNamespaceName& CIMObjectPath::getNameSpace() const
|
763 kumpf 1.2 {
764 return _rep->_nameSpace;
765 }
766
|
767 kumpf 1.7 void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace)
|
768 kumpf 1.2 {
769 _rep->_nameSpace = nameSpace;
770 }
771
|
772 kumpf 1.7 const CIMName& CIMObjectPath::getClassName() const
|
773 kumpf 1.2 {
774 return _rep->_className;
775 }
776
|
777 kumpf 1.7 void CIMObjectPath::setClassName(const CIMName& className)
|
778 kumpf 1.2 {
779 _rep->_className = className;
780 }
781
782 const Array<KeyBinding>& CIMObjectPath::getKeyBindings() const
783 {
784 return _rep->_keyBindings;
785 }
786
787 void CIMObjectPath::setKeyBindings(const Array<KeyBinding>& keyBindings)
788 {
789 _rep->_keyBindings = keyBindings;
790 _BubbleSort(_rep->_keyBindings);
791 }
792
793 String CIMObjectPath::toString(Boolean includeHost) const
794 {
795 String objectName;
796
797 // Get the host:
798
799 kumpf 1.2 if (_rep->_host.size() && includeHost)
800 {
801 objectName = "//";
802 objectName += _rep->_host;
803 objectName += "/";
804 }
805
806 // Get the namespace (if we have a host name, we must write namespace):
807
|
808 kumpf 1.7 if (!_rep->_nameSpace.isNull() || _rep->_host.size())
|
809 kumpf 1.2 {
810 objectName += _rep->_nameSpace;
811 objectName += ":";
812 }
813
814 // Get the class name:
815
816 objectName.append(getClassName());
817
818 if (isInstanceName())
819 {
820 objectName.append('.');
821
822 // Append each key-value pair:
823
824 const Array<KeyBinding>& keyBindings = getKeyBindings();
825
826 for (Uint32 i = 0, n = keyBindings.size(); i < n; i++)
827 {
828 objectName.append(keyBindings[i].getName());
829 objectName.append('=');
830 kumpf 1.2
831 const String& value = _escapeSpecialCharacters(
832 keyBindings[i].getValue());
833
834 KeyBinding::Type type = keyBindings[i].getType();
835
836 if (type == KeyBinding::REFERENCE)
837 objectName.append('R');
838
839 if (type == KeyBinding::STRING || type == KeyBinding::REFERENCE)
840 objectName.append('"');
841
842 objectName.append(value);
843
844 if (type == KeyBinding::STRING || type == KeyBinding::REFERENCE)
845 objectName.append('"');
846
847 if (i + 1 != n)
848 objectName.append(',');
849 }
850 }
851 kumpf 1.2
852 return objectName;
853 }
854
855 String CIMObjectPath::toStringCanonical(Boolean includeHost) const
856 {
857 CIMObjectPath ref = *this;
858
859 // ATTN-RK-P2-20020510: Need to make hostname and namespace lower case?
860
|
861 kumpf 1.7 String classNameLower = ref._rep->_className;
862 classNameLower.toLower();
863 ref._rep->_className = classNameLower;
|
864 kumpf 1.2
865 for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
866 {
|
867 kumpf 1.7 String keyBindingNameLower = ref._rep->_keyBindings[i]._rep->_name;
868 keyBindingNameLower.toLower();
869 ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
|
870 kumpf 1.2 }
871
872 return ref.toString(includeHost);
873 }
874
875 CIMObjectPath CIMObjectPath::clone() const
876 {
877 return CIMObjectPath(*this);
878 }
879
880 Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
881 {
882 return
883 String::equal(_rep->_host, x._rep->_host) &&
|
884 kumpf 1.7 _rep->_nameSpace.equal(x._rep->_nameSpace) &&
885 _rep->_className.equal(x._rep->_className) &&
|
886 kumpf 1.2 _rep->_keyBindings == x._rep->_keyBindings;
887 }
888
889 Uint32 CIMObjectPath::makeHashCode() const
890 {
891 return HashFunc<String>::hash(toStringCanonical());
892 }
893
894 Boolean CIMObjectPath::isInstanceName() const
895 {
896 return _rep->_keyBindings.size() != 0;
897 }
898
899 KeyBindingArray CIMObjectPath::getKeyBindingArray()
900 {
901 return KeyBindingArray();
902 }
903
904
905 Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y)
906 {
907 kumpf 1.2 return x.identical(y);
908 }
909
910 Boolean operator!=(const CIMObjectPath& x, const CIMObjectPath& y)
911 {
912 return !operator==(x, y);
913 }
914
915 PEGASUS_STD(ostream)& operator<<(
916 PEGASUS_STD(ostream)& os,
917 const CIMObjectPath& x)
918 {
919 return os << x.toString();
920 }
|
921 chip 1.1
922 PEGASUS_NAMESPACE_END
|