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