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.18 CIMKeyBinding::CIMKeyBinding(const CIMName& name, const CIMValue& value)
188 {
|
189 kumpf 1.20 // ATTN-RK-20020920: Verify that real numbers cannot be keys
190 if (value.isArray() ||
191 (value.getType() == CIMTYPE_REAL32) ||
192 (value.getType() == CIMTYPE_REAL64))
193 {
194 throw TypeMismatchException();
195 }
196
|
197 kumpf 1.18 String kbValue = value.toString();
198 Type kbType;
199
200 switch (value.getType())
201 {
202 case CIMTYPE_BOOLEAN:
203 kbType = BOOLEAN;
204 break;
205 case CIMTYPE_CHAR16:
206 case CIMTYPE_STRING:
207 case CIMTYPE_DATETIME:
208 kbType = STRING;
209 break;
210 case CIMTYPE_REFERENCE:
211 kbType = REFERENCE;
212 break;
213 default:
214 kbType = NUMERIC;
215 break;
216 }
217
218 kumpf 1.18 _rep = new CIMKeyBindingRep(name, kbValue, kbType);
219 }
220
|
221 kumpf 1.16 CIMKeyBinding::~CIMKeyBinding()
|
222 kumpf 1.2 {
223 delete _rep;
224 }
225
|
226 kumpf 1.16 CIMKeyBinding& CIMKeyBinding::operator=(const CIMKeyBinding& x)
|
227 kumpf 1.2 {
228 *_rep = *x._rep;
229 return *this;
230 }
231
|
232 kumpf 1.16 const CIMName& CIMKeyBinding::getName() const
|
233 kumpf 1.2 {
234 return _rep->_name;
235 }
236
|
237 kumpf 1.16 void CIMKeyBinding::setName(const CIMName& name)
|
238 kumpf 1.2 {
239 _rep->_name = name;
240 }
241
|
242 kumpf 1.16 const String& CIMKeyBinding::getValue() const
|
243 kumpf 1.2 {
244 return _rep->_value;
245 }
246
|
247 kumpf 1.16 void CIMKeyBinding::setValue(const String& value)
|
248 kumpf 1.2 {
249 _rep->_value = value;
250 }
251
|
252 kumpf 1.16 CIMKeyBinding::Type CIMKeyBinding::getType() const
|
253 kumpf 1.2 {
254 return _rep->_type;
255 }
256
|
257 kumpf 1.16 void CIMKeyBinding::setType(CIMKeyBinding::Type type)
|
258 kumpf 1.2 {
259 _rep->_type = type;
260 }
|
261 kumpf 1.18
262 Boolean CIMKeyBinding::equal(CIMValue value)
263 {
|
264 kumpf 1.20 // ATTN-RK-20020920: Verify that real numbers cannot be keys
265 if (value.isArray() ||
266 (value.getType() == CIMTYPE_REAL32) ||
267 (value.getType() == CIMTYPE_REAL64))
268 {
269 return false;
270 }
271
|
272 kumpf 1.18 CIMValue kbValue;
273
274 try
275 {
276 switch (value.getType())
277 {
278 case CIMTYPE_CHAR16:
|
279 kumpf 1.20 if (getType() != STRING) return false;
|
280 kumpf 1.18 kbValue.set(getValue()[0]);
281 break;
282 case CIMTYPE_DATETIME:
|
283 kumpf 1.20 if (getType() != STRING) return false;
|
284 kumpf 1.18 kbValue.set(CIMDateTime(getValue()));
285 break;
286 case CIMTYPE_STRING:
|
287 kumpf 1.20 if (getType() != STRING) return false;
|
288 kumpf 1.18 kbValue.set(getValue());
289 break;
290 case CIMTYPE_REFERENCE:
|
291 kumpf 1.20 if (getType() != REFERENCE) return false;
|
292 kumpf 1.18 kbValue.set(CIMObjectPath(getValue()));
293 break;
|
294 kumpf 1.20 case CIMTYPE_BOOLEAN:
295 if (getType() != BOOLEAN) return false;
296 kbValue = XmlReader::stringToValue(0, getValue().getCString(),
297 value.getType());
298 break;
299 default: // Numerics
300 if (getType() != NUMERIC) return false;
|
301 kumpf 1.18 kbValue = XmlReader::stringToValue(0, getValue().getCString(),
302 value.getType());
303 break;
304 }
305 }
|
306 kumpf 1.19 catch (Exception&)
|
307 kumpf 1.18 {
308 return false;
309 }
310
311 return value.equal(kbValue);
312 }
|
313 kumpf 1.2
|
314 kumpf 1.16 Boolean operator==(const CIMKeyBinding& x, const CIMKeyBinding& y)
|
315 kumpf 1.2 {
316 return
|
317 kumpf 1.7 x.getName().equal(y.getName()) &&
|
318 kumpf 1.2 String::equal(x.getValue(), y.getValue()) &&
319 x.getType() == y.getType();
320 }
321
322
323 ////////////////////////////////////////////////////////////////////////////////
324 //
325 // CIMObjectPath
326 //
327 ////////////////////////////////////////////////////////////////////////////////
328
329 class CIMObjectPathRep
330 {
331 public:
332 CIMObjectPathRep()
333 {
334 }
335
336 CIMObjectPathRep(const CIMObjectPathRep& x)
337 : _host(x._host), _nameSpace(x._nameSpace),
338 _className(x._className), _keyBindings(x._keyBindings)
339 kumpf 1.2 {
340 }
341
342 CIMObjectPathRep(
343 const String& host,
|
344 kumpf 1.7 const CIMNamespaceName& nameSpace,
345 const CIMName& className,
|
346 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
347 kumpf 1.2 : _host(host), _nameSpace(nameSpace),
348 _className(className), _keyBindings(keyBindings)
349 {
350 }
351
352 ~CIMObjectPathRep()
353 {
354 }
355
356 CIMObjectPathRep& operator=(const CIMObjectPathRep& x)
357 {
358 if (&x != this)
359 {
360 _host = x._host;
361 _nameSpace = x._nameSpace;
362 _className = x._className;
363 _keyBindings = x._keyBindings;
364 }
365 return *this;
366 }
367
368 kumpf 1.2 //
369 // Contains port as well (e.g., myhost:1234).
370 //
371 String _host;
372
|
373 kumpf 1.7 CIMNamespaceName _nameSpace;
374 CIMName _className;
|
375 kumpf 1.16 Array<CIMKeyBinding> _keyBindings;
|
376 kumpf 1.2 };
377
378
379 CIMObjectPath::CIMObjectPath()
380 {
381 _rep = new CIMObjectPathRep();
382 }
383
384 CIMObjectPath::CIMObjectPath(const CIMObjectPath& x)
385 {
386 _rep = new CIMObjectPathRep(*x._rep);
387 }
388
389 CIMObjectPath::CIMObjectPath(const String& objectName)
390 {
391 // Test the objectName out to see if we get an exception
392 CIMObjectPath tmpRef;
393 tmpRef.set(objectName);
394
395 _rep = new CIMObjectPathRep(*tmpRef._rep);
396 }
397 kumpf 1.2
398 CIMObjectPath::CIMObjectPath(
399 const String& host,
|
400 kumpf 1.7 const CIMNamespaceName& nameSpace,
401 const CIMName& className,
|
402 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
403 kumpf 1.2 {
404 // Test the objectName out to see if we get an exception
405 CIMObjectPath tmpRef;
406 tmpRef.set(host, nameSpace, className, keyBindings);
407
408 _rep = new CIMObjectPathRep(*tmpRef._rep);
409 }
410
411 CIMObjectPath::~CIMObjectPath()
412 {
413 delete _rep;
414 }
415
416 CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x)
417 {
418 *_rep = *x._rep;
419 return *this;
420 }
421
422 void CIMObjectPath::clear()
423 {
424 kumpf 1.2 _rep->_host.clear();
425 _rep->_nameSpace.clear();
426 _rep->_className.clear();
427 _rep->_keyBindings.clear();
428 }
429
430 void CIMObjectPath::set(
431 const String& host,
|
432 kumpf 1.7 const CIMNamespaceName& nameSpace,
433 const CIMName& className,
|
434 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
435 kumpf 1.2 {
436 setHost(host);
437 setNameSpace(nameSpace);
438 setClassName(className);
439 setKeyBindings(keyBindings);
440 }
441
442 Boolean CIMObjectPath::_parseHostElement(
443 const String& objectName,
444 char*& p,
|
445 kumpf 1.9 String& host)
|
446 kumpf 1.2 {
447 // See if there is a host name (true if it begins with "//"):
448 // Host is of the from <hostname>-<port> and begins with "//"
449 // and ends with "/":
450
451 if (p[0] != '/' || p[1] != '/')
452 {
453 return false;
454 }
455
456 p += 2;
457
458 //----------------------------------------------------------------------
459 // Validate the hostname. Hostnames must match the following
460 // regular expression: "[A-Za-z][A-Za-z0-9-]*"
461 //----------------------------------------------------------------------
462
463 char* q = p;
464
465 if (!isalpha(*q))
|
466 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
467 kumpf 1.2
468 q++;
469
470 while (isalnum(*q) || *q == '-')
471 q++;
472
473 // We now expect a port (or default the port).
474
475 if (*q == ':')
476 {
477 q++;
478 // Check for a port number:
479
480 if (!isdigit(*q))
|
481 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
482 kumpf 1.2
483 while (isdigit(*q))
484 q++;
485
486 // Finally, assign the host name:
487
488 host.assign(p, q - p);
489 }
490 else
491 {
492 host.assign(p, q - p);
493
494 // Assign the default port number:
495
496 host.append(":");
497 host.append(PEGASUS_CIMOM_DEFAULT_PORT_STRING);
498 }
499
500 // Check for slash terminating the entire sequence:
501
502 if (*q != '/')
503 kumpf 1.2 {
504 host.clear();
|
505 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
506 kumpf 1.2 }
507
508 p = ++q;
509
510 return true;
511 }
512
513 Boolean CIMObjectPath::_parseNamespaceElement(
514 const String& objectName,
515 char*& p,
|
516 kumpf 1.7 CIMNamespaceName& nameSpace)
|
517 kumpf 1.2 {
518 // If we don't find a valid namespace name followed by a ':', we
519 // assume we're not looking at a namespace name.
520
|
521 kumpf 1.7 char* colon = strchr(p, ':');
522 if (!colon)
523 {
524 return false;
525 }
526
|
527 kumpf 1.2 //----------------------------------------------------------------------
528 // Validate the namespace path. Namespaces must match the following
529 // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*"
530 //----------------------------------------------------------------------
531
|
532 kumpf 1.7 String namespaceName = String(p, colon - p);
533 if (!CIMNamespaceName::legal(namespaceName))
|
534 kumpf 1.2 {
|
535 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
536 kumpf 1.2 }
|
537 kumpf 1.7 nameSpace = namespaceName;
|
538 kumpf 1.2
|
539 kumpf 1.7 p = colon+1;
|
540 kumpf 1.2 return true;
541 }
542
543 /**
544 ATTN: RK - Association classes have keys whose types are
545 references. These reference values must be treated specially
546 in the XML encoding, using the VALUE.REFERENCE tag structure.
547
548 Pegasus had been passing reference values simply as String
549 values. For example, EnumerateInstanceNames returned
550 KEYVALUEs of string type rather than VALUE.REFERENCEs.
551
552 I've modified the XmlReader::getKeyBindingElement() and
553 XmlWriter::appendInstanceNameElement() methods to read and write
554 the XML in the proper format. However, making that change
555 required that a CIMObjectPath object be able to distinguish
556 between a key of String type and a key of reference type.
557
558 I've modified the String format of CIMObjectPaths slightly to
559 allow efficient processing of references whose keys are also
560 of reference type. The "official" form uses the same
561 kumpf 1.2 encoding for key values of String type and of reference type,
562 and so it would be necessary to retrieve the class definition
563 and look up the types of the key properties to determine how
564 to treat the key values. This is clearly too inefficient for
565 internal transformations between CIMObjectPaths and String
566 values.
567
568 The workaround is to encode a 'R' at the beginning of the
569 value for a key of reference type (before the opening '"').
570 This allows the parser to know a priori whether the key is of
571 String or reference type.
572
573 In this example:
574
575 MyClass.Key1="StringValue",Key2=R"RefClass.KeyA="StringA",KeyB=10"
576
577 Property Key1 of class MyClass is of String type, and so it
578 gets the usual encoding. Key2 is a reference property, so
579 the extra 'R' is inserted before its encoded value. Note
580 that this algorithm is recursive, such that RefClass could
581 include KeyC of reference type, which would also get encoded
582 kumpf 1.2 with the 'R' notation.
583
584 The toString() method inserts the 'R' to provide symmetry. A
|
585 kumpf 1.16 new CIMKeyBinding type (REFERENCE) has been defined to denote
|
586 kumpf 1.2 keys in a CIMObjectPath that are of reference type. This
|
587 kumpf 1.16 CIMKeyBinding type must be used appropriately for
|
588 kumpf 1.2 CIMObjectPath::toString() to behave correctly.
589
590 A result of this change is that instances names in the
591 instance repository will include this extra 'R' character.
592 Note that for user-facing uses of the String encoding of
593 instance names (such as might appear in MOF for static
594 association instances or in the CGI client), this solution
595 is non-standard and therefore unacceptable. It is likely
596 that these points will need to process the more expensive
597 operation of retrieving the class definition to determine
598 the key property types.
599 */
600 void CIMObjectPath::_parseKeyBindingPairs(
601 const String& objectName,
602 char*& p,
|
603 kumpf 1.16 Array<CIMKeyBinding>& keyBindings)
|
604 kumpf 1.2 {
605 // Get the key-value pairs:
606
607 while (*p)
608 {
609 // Get key part:
610
|
611 kumpf 1.5 char* equalsign = strchr(p, '=');
612 if (!equalsign)
|
613 kumpf 1.2 {
|
614 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
615 kumpf 1.2 }
616
|
617 kumpf 1.5 *equalsign = 0;
|
618 kumpf 1.2
|
619 kumpf 1.17 if (!CIMName::legal(p))
|
620 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
621 kumpf 1.2
|
622 kumpf 1.17 CIMName keyName (p);
623
|
624 kumpf 1.2 // Get the value part:
625
626 String valueString;
|
627 kumpf 1.5 p = equalsign + 1;
|
628 kumpf 1.16 CIMKeyBinding::Type type;
|
629 kumpf 1.2
630 if (*p == 'R')
631 {
632 p++;
633
|
634 kumpf 1.16 type = CIMKeyBinding::REFERENCE;
|
635 kumpf 1.2
636 if (*p++ != '"')
|
637 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
638 kumpf 1.2
639 while (*p && *p != '"')
640 {
641 // ATTN: need to handle special characters here:
642
643 if (*p == '\\')
644 *p++;
645
646 valueString.append(*p++);
647 }
648
649 if (*p++ != '"')
|
650 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
651 kumpf 1.2 }
652 else if (*p == '"')
653 {
654 p++;
655
|
656 kumpf 1.16 type = CIMKeyBinding::STRING;
|
657 kumpf 1.2
658 while (*p && *p != '"')
659 {
660 // ATTN: need to handle special characters here:
661
662 if (*p == '\\')
663 *p++;
664
665 valueString.append(*p++);
666 }
667
668 if (*p++ != '"')
|
669 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
670 kumpf 1.2 }
671 else if (toupper(*p) == 'T' || toupper(*p) == 'F')
672 {
|
673 kumpf 1.16 type = CIMKeyBinding::BOOLEAN;
|
674 kumpf 1.2
675 char* r = p;
676 Uint32 n = 0;
677
678 while (*r && *r != ',')
679 {
680 *r = toupper(*r);
681 r++;
682 n++;
683 }
684
685 if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) ||
686 ((strncmp(p, "FALSE", n) == 0) && n == 5)))
|
687 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
688 kumpf 1.2
689 valueString.assign(p, n);
690
691 p = p + n;
692 }
693 else
694 {
|
695 kumpf 1.16 type = CIMKeyBinding::NUMERIC;
|
696 kumpf 1.2
697 char* r = p;
698 Uint32 n = 0;
699
700 while (*r && *r != ',')
701 {
702 r++;
703 n++;
704 }
705
706 Boolean isComma = false;
707 if (*r)
708 {
709 *r = '\0';
710 isComma = true;
711 }
712
713 Sint64 x;
714
715 if (!XmlReader::stringToSignedInteger(p, x))
|
716 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
717 kumpf 1.2
718 valueString.assign(p, n);
719
720 if (isComma)
721 {
722 *r = ',';
723 }
724
725 p = p + n;
726 }
727
|
728 kumpf 1.17 keyBindings.append(CIMKeyBinding(keyName.getString (), valueString,
729 type));
|
730 kumpf 1.2
731 if (*p)
732 {
733 if (*p++ != ',')
734 {
|
735 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
736 kumpf 1.2 }
737 }
738 }
739
740 _BubbleSort(keyBindings);
741 }
742
|
743 kumpf 1.9 void CIMObjectPath::set(const String& objectName)
|
744 kumpf 1.2 {
745 clear();
746
747 //--------------------------------------------------------------------------
748 // We will extract components from an object name. Here is an sample
749 // object name:
750 //
751 // //atp:9999/root/cimv25:TennisPlayer.first="Patrick",last="Rafter"
752 //--------------------------------------------------------------------------
753
754 // Convert to a C String first:
755
|
756 kumpf 1.14 char* p = strdup(objectName.getCString());
757 Destroyer<char> destroyer(p);
|
758 kumpf 1.2 Boolean gotHost;
759 Boolean gotNamespace;
760
761 gotHost = _parseHostElement(objectName, p, _rep->_host);
762 gotNamespace = _parseNamespaceElement(objectName, p, _rep->_nameSpace);
763
764 if (gotHost && !gotNamespace)
765 {
|
766 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
767 kumpf 1.2 }
768
769 // Extract the class name:
770
771 char* dot = strchr(p, '.');
772
773 if (!dot)
774 {
775 if (!CIMName::legal(p))
776 {
|
777 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
778 kumpf 1.2 }
779
780 // ATTN: remove this later: a reference should only be able to hold
781 // an instance name.
782
|
783 kumpf 1.17 _rep->_className = CIMName (p);
|
784 kumpf 1.2 return;
785 }
786
|
787 kumpf 1.7 String className = String(p, dot - p);
788 if (!CIMName::legal(className))
789 {
|
790 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
791 kumpf 1.7 }
792 _rep->_className = className;
|
793 kumpf 1.2
794 // Advance past dot:
795
796 p = dot + 1;
797
798 _parseKeyBindingPairs(objectName, p, _rep->_keyBindings);
799 }
800
801 CIMObjectPath& CIMObjectPath::operator=(const String& objectName)
802 {
803 set(objectName);
804 return *this;
805 }
806
807 const String& CIMObjectPath::getHost() const
808 {
809 return _rep->_host;
810 }
811
812 void CIMObjectPath::setHost(const String& host)
813 {
814 kumpf 1.2 _rep->_host = host;
815 }
816
|
817 kumpf 1.7 const CIMNamespaceName& CIMObjectPath::getNameSpace() const
|
818 kumpf 1.2 {
819 return _rep->_nameSpace;
820 }
821
|
822 kumpf 1.7 void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace)
|
823 kumpf 1.2 {
824 _rep->_nameSpace = nameSpace;
825 }
826
|
827 kumpf 1.7 const CIMName& CIMObjectPath::getClassName() const
|
828 kumpf 1.2 {
829 return _rep->_className;
830 }
831
|
832 kumpf 1.7 void CIMObjectPath::setClassName(const CIMName& className)
|
833 kumpf 1.2 {
834 _rep->_className = className;
835 }
836
|
837 kumpf 1.16 const Array<CIMKeyBinding>& CIMObjectPath::getKeyBindings() const
|
838 kumpf 1.2 {
839 return _rep->_keyBindings;
840 }
841
|
842 kumpf 1.16 void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings)
|
843 kumpf 1.2 {
844 _rep->_keyBindings = keyBindings;
845 _BubbleSort(_rep->_keyBindings);
846 }
847
|
848 kumpf 1.15 String CIMObjectPath::toString() const
|
849 kumpf 1.2 {
850 String objectName;
851
852 // Get the host:
853
|
854 kumpf 1.15 if (_rep->_host.size())
|
855 kumpf 1.2 {
856 objectName = "//";
|
857 kumpf 1.13 objectName.append(_rep->_host);
858 objectName.append("/");
|
859 kumpf 1.2 }
860
861 // Get the namespace (if we have a host name, we must write namespace):
862
|
863 kumpf 1.7 if (!_rep->_nameSpace.isNull() || _rep->_host.size())
|
864 kumpf 1.2 {
|
865 kumpf 1.17 objectName.append(_rep->_nameSpace.getString ());
|
866 kumpf 1.13 objectName.append(":");
|
867 kumpf 1.2 }
868
869 // Get the class name:
870
|
871 kumpf 1.17 objectName.append(getClassName().getString ());
|
872 kumpf 1.2
|
873 kumpf 1.9 //
874 // ATTN-CAKG-P2-20020726: The following condition does not correctly
875 // distinguish instanceNames from classNames in every case
876 // The instanceName of a singleton instance of a keyless class has no
877 // key bindings
878 //
879 if (_rep->_keyBindings.size () != 0)
|
880 kumpf 1.2 {
881 objectName.append('.');
882
883 // Append each key-value pair:
884
|
885 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings = getKeyBindings();
|
886 kumpf 1.2
887 for (Uint32 i = 0, n = keyBindings.size(); i < n; i++)
888 {
|
889 kumpf 1.17 objectName.append(keyBindings[i].getName().getString ());
|
890 kumpf 1.2 objectName.append('=');
891
892 const String& value = _escapeSpecialCharacters(
893 keyBindings[i].getValue());
894
|
895 kumpf 1.16 CIMKeyBinding::Type type = keyBindings[i].getType();
|
896 kumpf 1.2
|
897 kumpf 1.16 if (type == CIMKeyBinding::REFERENCE)
|
898 kumpf 1.2 objectName.append('R');
899
|
900 kumpf 1.16 if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
|
901 kumpf 1.2 objectName.append('"');
902
903 objectName.append(value);
904
|
905 kumpf 1.16 if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
|
906 kumpf 1.2 objectName.append('"');
907
908 if (i + 1 != n)
909 objectName.append(',');
910 }
911 }
912
913 return objectName;
914 }
915
|
916 kumpf 1.15 String CIMObjectPath::_toStringCanonical() const
|
917 kumpf 1.2 {
918 CIMObjectPath ref = *this;
919
920 // ATTN-RK-P2-20020510: Need to make hostname and namespace lower case?
921
|
922 kumpf 1.17 String classNameLower = ref._rep->_className.getString ();
|
923 kumpf 1.7 classNameLower.toLower();
924 ref._rep->_className = classNameLower;
|
925 kumpf 1.2
926 for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
927 {
|
928 kumpf 1.17 String keyBindingNameLower =
929 ref._rep->_keyBindings[i]._rep->_name.getString ();
|
930 kumpf 1.7 keyBindingNameLower.toLower();
931 ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
|
932 kumpf 1.2 }
933
|
934 kumpf 1.12 // ATTN-RK-20020826: Need to sort keys?
935
|
936 kumpf 1.15 return ref.toString();
|
937 kumpf 1.2 }
938
939 Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
940 {
941 return
942 String::equal(_rep->_host, x._rep->_host) &&
|
943 kumpf 1.7 _rep->_nameSpace.equal(x._rep->_nameSpace) &&
944 _rep->_className.equal(x._rep->_className) &&
|
945 kumpf 1.2 _rep->_keyBindings == x._rep->_keyBindings;
946 }
947
948 Uint32 CIMObjectPath::makeHashCode() const
949 {
|
950 kumpf 1.12 return HashFunc<String>::hash(_toStringCanonical());
|
951 kumpf 1.2 }
952
953 Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y)
954 {
955 return x.identical(y);
956 }
957
958 Boolean operator!=(const CIMObjectPath& x, const CIMObjectPath& y)
959 {
960 return !operator==(x, y);
961 }
962
963 PEGASUS_STD(ostream)& operator<<(
964 PEGASUS_STD(ostream)& os,
965 const CIMObjectPath& x)
966 {
967 return os << x.toString();
968 }
|
969 chip 1.1
970 PEGASUS_NAMESPACE_END
|