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 kumpf 1.22 #include <iostream>
|
36 kumpf 1.2 #include "HashTable.h"
37 #include "CIMObjectPath.h"
38 #include "Indentor.h"
39 #include "CIMName.h"
40 #include "Destroyer.h"
41 #include "XmlWriter.h"
42 #include "XmlReader.h"
|
43 kumpf 1.11 #include "ArrayInternal.h"
|
44 kumpf 1.2 #include "CIMOMPort.h"
|
45 chip 1.1
46 PEGASUS_NAMESPACE_BEGIN
|
47 kumpf 1.2
|
48 kumpf 1.16 #define PEGASUS_ARRAY_T CIMKeyBinding
|
49 kumpf 1.2 # include "ArrayImpl.h"
50 #undef PEGASUS_ARRAY_T
51
52 #define PEGASUS_ARRAY_T CIMObjectPath
53 # include "ArrayImpl.h"
54 #undef PEGASUS_ARRAY_T
55
56 // ATTN: KS May 2002 P0 Add resolve method to CIMObjectPath.
57 // Add a resolve method to this class to verify that the
58 // reference is correct (that the class name corresponds to a real
59 // class and that the property names are really keys and that all keys
60 // of the class or used. Also be sure that there is a valid conversion
61 // between the string value and the value of that property).
62 //
63 // ATTN: also check to see that the reference refers to a class that is the
64 // same or derived from the _className member.
65
66 ////////////////////////////////////////////////////////////////////////////////
67 //
68 // Local routines:
69 //
70 kumpf 1.2 ////////////////////////////////////////////////////////////////////////////////
71
72 static String _escapeSpecialCharacters(const String& str)
73 {
74 String result;
75
76 for (Uint32 i = 0, n = str.size(); i < n; i++)
77 {
78 switch (str[i])
79 {
|
80 kumpf 1.28 case '\\':
81 result.append("\\\\");
|
82 kumpf 1.2 break;
83
84 case '"':
|
85 kumpf 1.13 result.append("\\\"");
|
86 kumpf 1.2 break;
87
88 default:
|
89 kumpf 1.13 result.append(str[i]);
|
90 kumpf 1.2 }
91 }
92
93 return result;
94 }
95
|
96 kumpf 1.16 static void _BubbleSort(Array<CIMKeyBinding>& x)
|
97 kumpf 1.2 {
98 Uint32 n = x.size();
99
|
100 kumpf 1.24 //
101 // If the key is a reference, the keys in the reference must also be
102 // sorted
103 //
104 for (Uint32 k = 0; k < n ; k++)
105 if (x[k].getType () == CIMKeyBinding::REFERENCE)
106 {
107 CIMObjectPath tmp (x[k].getValue ());
108 Array <CIMKeyBinding> keyBindings = tmp.getKeyBindings ();
109 _BubbleSort (keyBindings);
110 tmp.setKeyBindings (keyBindings);
111 x[k].setValue (tmp.toString ());
112 }
113
|
114 kumpf 1.2 if (n < 2)
115 return;
116
117 for (Uint32 i = 0; i < n - 1; i++)
118 {
119 for (Uint32 j = 0; j < n - 1; j++)
120 {
|
121 kumpf 1.17 if (String::compareNoCase(x[j].getName().getString(),
122 x[j+1].getName().getString()) > 0)
|
123 kumpf 1.2 {
|
124 kumpf 1.16 CIMKeyBinding t = x[j];
|
125 kumpf 1.2 x[j] = x[j+1];
126 x[j+1] = t;
127 }
128 }
129 }
130 }
131
132 ////////////////////////////////////////////////////////////////////////////////
133 //
|
134 kumpf 1.16 // CIMKeyBinding
|
135 kumpf 1.2 //
136 ////////////////////////////////////////////////////////////////////////////////
137
|
138 kumpf 1.16 class CIMKeyBindingRep
|
139 kumpf 1.2 {
140 public:
|
141 kumpf 1.16 CIMKeyBindingRep()
|
142 kumpf 1.2 {
143 }
144
|
145 kumpf 1.16 CIMKeyBindingRep(const CIMKeyBindingRep& x)
|
146 kumpf 1.2 : _name(x._name), _value(x._value), _type(x._type)
147 {
148 }
149
|
150 kumpf 1.16 CIMKeyBindingRep(
|
151 kumpf 1.7 const CIMName& name,
|
152 kumpf 1.2 const String& value,
|
153 kumpf 1.16 CIMKeyBinding::Type type)
|
154 kumpf 1.2 : _name(name), _value(value), _type(type)
155 {
156 }
157
|
158 kumpf 1.16 ~CIMKeyBindingRep()
|
159 kumpf 1.2 {
160 }
161
|
162 kumpf 1.16 CIMKeyBindingRep& operator=(const CIMKeyBindingRep& x)
|
163 kumpf 1.2 {
164 if (&x != this)
165 {
166 _name = x._name;
167 _value = x._value;
168 _type = x._type;
169 }
170 return *this;
171 }
172
|
173 kumpf 1.7 CIMName _name;
|
174 kumpf 1.2 String _value;
|
175 kumpf 1.16 CIMKeyBinding::Type _type;
|
176 kumpf 1.2 };
177
178
|
179 kumpf 1.16 CIMKeyBinding::CIMKeyBinding()
|
180 kumpf 1.2 {
|
181 kumpf 1.16 _rep = new CIMKeyBindingRep();
|
182 kumpf 1.2 }
183
|
184 kumpf 1.16 CIMKeyBinding::CIMKeyBinding(const CIMKeyBinding& x)
|
185 kumpf 1.2 {
|
186 kumpf 1.16 _rep = new CIMKeyBindingRep(*x._rep);
|
187 kumpf 1.2 }
188
|
189 kumpf 1.16 CIMKeyBinding::CIMKeyBinding(const CIMName& name, const String& value, Type type)
|
190 kumpf 1.2 {
|
191 kumpf 1.16 _rep = new CIMKeyBindingRep(name, value, type);
|
192 kumpf 1.2 }
193
|
194 kumpf 1.18 CIMKeyBinding::CIMKeyBinding(const CIMName& name, const CIMValue& value)
195 {
|
196 kumpf 1.21 if (value.isArray())
|
197 kumpf 1.20 {
198 throw TypeMismatchException();
199 }
200
|
201 kumpf 1.18 String kbValue = value.toString();
202 Type kbType;
203
204 switch (value.getType())
205 {
206 case CIMTYPE_BOOLEAN:
207 kbType = BOOLEAN;
208 break;
209 case CIMTYPE_CHAR16:
210 case CIMTYPE_STRING:
211 case CIMTYPE_DATETIME:
212 kbType = STRING;
213 break;
214 case CIMTYPE_REFERENCE:
215 kbType = REFERENCE;
216 break;
217 default:
218 kbType = NUMERIC;
219 break;
220 }
221
222 kumpf 1.18 _rep = new CIMKeyBindingRep(name, kbValue, kbType);
223 }
224
|
225 kumpf 1.16 CIMKeyBinding::~CIMKeyBinding()
|
226 kumpf 1.2 {
227 delete _rep;
228 }
229
|
230 kumpf 1.16 CIMKeyBinding& CIMKeyBinding::operator=(const CIMKeyBinding& x)
|
231 kumpf 1.2 {
232 *_rep = *x._rep;
233 return *this;
234 }
235
|
236 kumpf 1.16 const CIMName& CIMKeyBinding::getName() const
|
237 kumpf 1.2 {
238 return _rep->_name;
239 }
240
|
241 kumpf 1.16 void CIMKeyBinding::setName(const CIMName& name)
|
242 kumpf 1.2 {
243 _rep->_name = name;
244 }
245
|
246 kumpf 1.16 const String& CIMKeyBinding::getValue() const
|
247 kumpf 1.2 {
248 return _rep->_value;
249 }
250
|
251 kumpf 1.16 void CIMKeyBinding::setValue(const String& value)
|
252 kumpf 1.2 {
253 _rep->_value = value;
254 }
255
|
256 kumpf 1.16 CIMKeyBinding::Type CIMKeyBinding::getType() const
|
257 kumpf 1.2 {
258 return _rep->_type;
259 }
260
|
261 kumpf 1.16 void CIMKeyBinding::setType(CIMKeyBinding::Type type)
|
262 kumpf 1.2 {
263 _rep->_type = type;
264 }
|
265 kumpf 1.18
266 Boolean CIMKeyBinding::equal(CIMValue value)
267 {
|
268 kumpf 1.21 if (value.isArray())
|
269 kumpf 1.20 {
270 return false;
271 }
272
|
273 kumpf 1.18 CIMValue kbValue;
274
275 try
276 {
277 switch (value.getType())
278 {
279 case CIMTYPE_CHAR16:
|
280 kumpf 1.20 if (getType() != STRING) return false;
|
281 kumpf 1.18 kbValue.set(getValue()[0]);
282 break;
283 case CIMTYPE_DATETIME:
|
284 kumpf 1.20 if (getType() != STRING) return false;
|
285 kumpf 1.18 kbValue.set(CIMDateTime(getValue()));
286 break;
287 case CIMTYPE_STRING:
|
288 kumpf 1.20 if (getType() != STRING) return false;
|
289 kumpf 1.18 kbValue.set(getValue());
290 break;
291 case CIMTYPE_REFERENCE:
|
292 kumpf 1.20 if (getType() != REFERENCE) return false;
|
293 kumpf 1.18 kbValue.set(CIMObjectPath(getValue()));
294 break;
|
295 kumpf 1.20 case CIMTYPE_BOOLEAN:
296 if (getType() != BOOLEAN) return false;
297 kbValue = XmlReader::stringToValue(0, getValue().getCString(),
298 value.getType());
299 break;
300 default: // Numerics
301 if (getType() != NUMERIC) return false;
|
302 kumpf 1.18 kbValue = XmlReader::stringToValue(0, getValue().getCString(),
303 value.getType());
304 break;
305 }
306 }
|
307 kumpf 1.19 catch (Exception&)
|
308 kumpf 1.18 {
309 return false;
310 }
311
312 return value.equal(kbValue);
313 }
|
314 kumpf 1.2
|
315 kumpf 1.16 Boolean operator==(const CIMKeyBinding& x, const CIMKeyBinding& y)
|
316 kumpf 1.2 {
317 return
|
318 kumpf 1.7 x.getName().equal(y.getName()) &&
|
319 kumpf 1.2 String::equal(x.getValue(), y.getValue()) &&
320 x.getType() == y.getType();
321 }
322
323
324 ////////////////////////////////////////////////////////////////////////////////
325 //
326 // CIMObjectPath
327 //
328 ////////////////////////////////////////////////////////////////////////////////
329
330 class CIMObjectPathRep
331 {
332 public:
333 CIMObjectPathRep()
334 {
335 }
336
337 CIMObjectPathRep(const CIMObjectPathRep& x)
338 : _host(x._host), _nameSpace(x._nameSpace),
339 _className(x._className), _keyBindings(x._keyBindings)
340 kumpf 1.2 {
341 }
342
343 CIMObjectPathRep(
344 const String& host,
|
345 kumpf 1.7 const CIMNamespaceName& nameSpace,
346 const CIMName& className,
|
347 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
348 kumpf 1.2 : _host(host), _nameSpace(nameSpace),
349 _className(className), _keyBindings(keyBindings)
350 {
351 }
352
353 ~CIMObjectPathRep()
354 {
355 }
356
357 CIMObjectPathRep& operator=(const CIMObjectPathRep& x)
358 {
359 if (&x != this)
360 {
361 _host = x._host;
362 _nameSpace = x._nameSpace;
363 _className = x._className;
364 _keyBindings = x._keyBindings;
365 }
366 return *this;
367 }
368
369 kumpf 1.2 //
370 // Contains port as well (e.g., myhost:1234).
371 //
372 String _host;
373
|
374 kumpf 1.7 CIMNamespaceName _nameSpace;
375 CIMName _className;
|
376 kumpf 1.16 Array<CIMKeyBinding> _keyBindings;
|
377 kumpf 1.2 };
378
379
380 CIMObjectPath::CIMObjectPath()
381 {
382 _rep = new CIMObjectPathRep();
383 }
384
385 CIMObjectPath::CIMObjectPath(const CIMObjectPath& x)
386 {
387 _rep = new CIMObjectPathRep(*x._rep);
388 }
389
390 CIMObjectPath::CIMObjectPath(const String& objectName)
391 {
392 // Test the objectName out to see if we get an exception
393 CIMObjectPath tmpRef;
394 tmpRef.set(objectName);
395
396 _rep = new CIMObjectPathRep(*tmpRef._rep);
397 }
398 kumpf 1.2
399 CIMObjectPath::CIMObjectPath(
400 const String& host,
|
401 kumpf 1.7 const CIMNamespaceName& nameSpace,
402 const CIMName& className,
|
403 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
404 kumpf 1.2 {
405 // Test the objectName out to see if we get an exception
406 CIMObjectPath tmpRef;
407 tmpRef.set(host, nameSpace, className, keyBindings);
408
409 _rep = new CIMObjectPathRep(*tmpRef._rep);
410 }
411
412 CIMObjectPath::~CIMObjectPath()
413 {
414 delete _rep;
415 }
416
417 CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x)
418 {
419 *_rep = *x._rep;
420 return *this;
421 }
422
423 void CIMObjectPath::clear()
424 {
425 kumpf 1.2 _rep->_host.clear();
426 _rep->_nameSpace.clear();
427 _rep->_className.clear();
428 _rep->_keyBindings.clear();
429 }
430
431 void CIMObjectPath::set(
432 const String& host,
|
433 kumpf 1.7 const CIMNamespaceName& nameSpace,
434 const CIMName& className,
|
435 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
436 kumpf 1.2 {
437 setHost(host);
438 setNameSpace(nameSpace);
439 setClassName(className);
440 setKeyBindings(keyBindings);
441 }
442
|
443 kumpf 1.22 Boolean _parseHostElement(
|
444 kumpf 1.2 const String& objectName,
445 char*& p,
|
446 kumpf 1.9 String& host)
|
447 kumpf 1.2 {
448 // See if there is a host name (true if it begins with "//"):
449 // Host is of the from <hostname>-<port> and begins with "//"
450 // and ends with "/":
451
452 if (p[0] != '/' || p[1] != '/')
453 {
454 return false;
455 }
456
457 p += 2;
458
459 //----------------------------------------------------------------------
|
460 chuck 1.23 // Validate the hostname. A domain is allowed after the hostname.
461 // Eg. xyz.company.com
462 // Hostnames must match the following regular expression:
463 // ^([A-Za-z][A-Za-z0-9-]*)(\.[A-Za-z][A-Za-z0-9-]*)*$
|
464 kumpf 1.2 //----------------------------------------------------------------------
465
466 char* q = p;
467
|
468 chuck 1.23 Boolean foundDot = true;
469 while (foundDot == true)
470 {
471 foundDot = false;
|
472 kumpf 1.2
|
473 chuck 1.23 if (!isalpha(*q))
474 throw MalformedObjectNameException(objectName);
|
475 kumpf 1.2
476 q++;
|
477 chuck 1.23
478 while (isalnum(*q) || *q == '-')
479 {
480 q++;
481 }
482
483 if (*q == '.')
484 {
485 q++;
486 foundDot = true;
487 }
488 }
|
489 kumpf 1.2
490 // We now expect a port (or default the port).
491
492 if (*q == ':')
493 {
494 q++;
495 // Check for a port number:
496
497 if (!isdigit(*q))
|
498 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
499 kumpf 1.2
500 while (isdigit(*q))
501 q++;
502
503 // Finally, assign the host name:
504
505 host.assign(p, q - p);
506 }
507 else
508 {
509 host.assign(p, q - p);
510
511 // Assign the default port number:
512
513 host.append(":");
514 host.append(PEGASUS_CIMOM_DEFAULT_PORT_STRING);
515 }
516
517 // Check for slash terminating the entire sequence:
518
519 if (*q != '/')
520 kumpf 1.2 {
521 host.clear();
|
522 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
523 kumpf 1.2 }
524
525 p = ++q;
526
527 return true;
528 }
529
|
530 kumpf 1.22 Boolean _parseNamespaceElement(
|
531 kumpf 1.2 const String& objectName,
532 char*& p,
|
533 kumpf 1.7 CIMNamespaceName& nameSpace)
|
534 kumpf 1.2 {
535 // If we don't find a valid namespace name followed by a ':', we
536 // assume we're not looking at a namespace name.
537
|
538 kumpf 1.7 char* colon = strchr(p, ':');
539 if (!colon)
540 {
541 return false;
542 }
543
|
544 kumpf 1.25 // A ':' as part of a keybinding value should not be interpreted as
545 // a namespace delimiter. Since keybinding pairs follow the first '.'
546 // in the object path string, the ':' delimiter only counts if it
547 // appears before the '.'.
548
549 char* dot = strchr(p, '.');
550 if (dot && (dot < colon))
551 {
552 return false;
553 }
554
|
555 kumpf 1.2 //----------------------------------------------------------------------
556 // Validate the namespace path. Namespaces must match the following
557 // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*"
558 //----------------------------------------------------------------------
559
|
560 david 1.27 String namespaceName = String(p, (Uint32)(colon - p));
|
561 kumpf 1.7 if (!CIMNamespaceName::legal(namespaceName))
|
562 kumpf 1.2 {
|
563 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
564 kumpf 1.2 }
|
565 kumpf 1.7 nameSpace = namespaceName;
|
566 kumpf 1.2
|
567 kumpf 1.7 p = colon+1;
|
568 kumpf 1.2 return true;
569 }
570
571 /**
|
572 kumpf 1.29 ATTN-RK: The DMTF specification for the string form of an
573 object path makes it impossible for a parser to distinguish
574 between a key values of String type and Reference type.
575
576 Given the ambiguity, this implementation takes a guess at the
577 type of a quoted key value. If the value can be parsed into
578 a CIMObjectPath with at least one key binding, the type is
579 set to REFERENCE. Otherwise, the type is set to STRING.
580 Note: This algorithm appears to be in line with what the Sun
581 WBEM Services implementation does.
582
583 To be totally correct, it would be necessary to retrieve the
584 class definition and look up the types of the key properties
585 to determine how to interpret the key values. This is clearly
586 too inefficient for internal transformations between
587 CIMObjectPaths and String values.
|
588 kumpf 1.2 */
|
589 kumpf 1.22 void _parseKeyBindingPairs(
|
590 kumpf 1.2 const String& objectName,
591 char*& p,
|
592 kumpf 1.16 Array<CIMKeyBinding>& keyBindings)
|
593 kumpf 1.2 {
594 // Get the key-value pairs:
595
596 while (*p)
597 {
598 // Get key part:
599
|
600 kumpf 1.5 char* equalsign = strchr(p, '=');
601 if (!equalsign)
|
602 kumpf 1.2 {
|
603 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
604 kumpf 1.2 }
605
|
606 kumpf 1.5 *equalsign = 0;
|
607 kumpf 1.2
|
608 kumpf 1.17 if (!CIMName::legal(p))
|
609 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
610 kumpf 1.2
|
611 kumpf 1.17 CIMName keyName (p);
612
|
613 kumpf 1.2 // Get the value part:
614
615 String valueString;
|
616 kumpf 1.5 p = equalsign + 1;
|
617 kumpf 1.16 CIMKeyBinding::Type type;
|
618 kumpf 1.2
|
619 kumpf 1.29 if (*p == '"')
|
620 kumpf 1.2 {
|
621 kumpf 1.29 // Could be CIMKeyBinding::STRING or CIMKeyBinding::REFERENCE
622
|
623 kumpf 1.2 p++;
624
625 while (*p && *p != '"')
626 {
627 if (*p == '\\')
|
628 kumpf 1.28 {
|
629 kumpf 1.2 *p++;
630
|
631 kumpf 1.28 if ((*p != '\\') && (*p != '"'))
632 {
633 throw MalformedObjectNameException(objectName);
634 }
635 }
636
|
637 kumpf 1.2 valueString.append(*p++);
638 }
639
640 if (*p++ != '"')
|
641 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
642 kumpf 1.2
|
643 kumpf 1.29 /*
644 Guess at the type of this quoted key value. If the value
645 can be parsed into a CIMObjectPath with at least one key
646 binding, the type is assumed to be a REFERENCE. Otherwise,
647 the type is set to STRING. (See method header for details.)
648 */
|
649 kumpf 1.16 type = CIMKeyBinding::STRING;
|
650 kumpf 1.2
|
651 kumpf 1.29 try
|
652 kumpf 1.2 {
|
653 kumpf 1.29 CIMObjectPath testForPath(valueString);
654 if (testForPath.getKeyBindings().size() > 0)
|
655 kumpf 1.28 {
|
656 kumpf 1.29 // We've found a reference value!
657 type = CIMKeyBinding::REFERENCE;
|
658 kumpf 1.28 }
|
659 kumpf 1.2 }
|
660 kumpf 1.29 catch (Exception & e)
661 {
662 // Not a reference value; leave type as STRING
663 }
|
664 kumpf 1.2 }
665 else if (toupper(*p) == 'T' || toupper(*p) == 'F')
666 {
|
667 kumpf 1.16 type = CIMKeyBinding::BOOLEAN;
|
668 kumpf 1.2
669 char* r = p;
670 Uint32 n = 0;
671
672 while (*r && *r != ',')
673 {
674 *r = toupper(*r);
675 r++;
676 n++;
677 }
678
679 if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) ||
680 ((strncmp(p, "FALSE", n) == 0) && n == 5)))
|
681 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
682 kumpf 1.2
683 valueString.assign(p, n);
684
685 p = p + n;
686 }
687 else
688 {
|
689 kumpf 1.16 type = CIMKeyBinding::NUMERIC;
|
690 kumpf 1.2
691 char* r = p;
692 Uint32 n = 0;
693
694 while (*r && *r != ',')
695 {
696 r++;
697 n++;
698 }
699
700 Boolean isComma = false;
701 if (*r)
702 {
703 *r = '\0';
704 isComma = true;
705 }
706
707 Sint64 x;
708
709 if (!XmlReader::stringToSignedInteger(p, x))
|
710 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
711 kumpf 1.2
712 valueString.assign(p, n);
713
714 if (isComma)
715 {
716 *r = ',';
717 }
718
719 p = p + n;
720 }
721
|
722 kumpf 1.17 keyBindings.append(CIMKeyBinding(keyName.getString (), valueString,
723 type));
|
724 kumpf 1.2
725 if (*p)
726 {
727 if (*p++ != ',')
728 {
|
729 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
730 kumpf 1.2 }
731 }
732 }
733
734 _BubbleSort(keyBindings);
735 }
736
|
737 kumpf 1.9 void CIMObjectPath::set(const String& objectName)
|
738 kumpf 1.2 {
739 clear();
740
741 //--------------------------------------------------------------------------
742 // We will extract components from an object name. Here is an sample
743 // object name:
744 //
745 // //atp:9999/root/cimv25:TennisPlayer.first="Patrick",last="Rafter"
746 //--------------------------------------------------------------------------
747
748 // Convert to a C String first:
749
|
750 david 1.27 CString pCString = objectName.getCStringUTF8();
|
751 kumpf 1.26 char* p = const_cast<char*>((const char*) pCString);
|
752 kumpf 1.2 Boolean gotHost;
753 Boolean gotNamespace;
754
755 gotHost = _parseHostElement(objectName, p, _rep->_host);
756 gotNamespace = _parseNamespaceElement(objectName, p, _rep->_nameSpace);
757
758 if (gotHost && !gotNamespace)
759 {
|
760 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
761 kumpf 1.2 }
762
763 // Extract the class name:
764
765 char* dot = strchr(p, '.');
766
767 if (!dot)
768 {
769 if (!CIMName::legal(p))
770 {
|
771 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
772 kumpf 1.2 }
773
774 // ATTN: remove this later: a reference should only be able to hold
775 // an instance name.
776
|
777 kumpf 1.17 _rep->_className = CIMName (p);
|
778 kumpf 1.2 return;
779 }
780
|
781 david 1.27 String className = String(p, (Uint32)(dot - p));
|
782 kumpf 1.7 if (!CIMName::legal(className))
783 {
|
784 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
785 kumpf 1.7 }
786 _rep->_className = className;
|
787 kumpf 1.2
788 // Advance past dot:
789
790 p = dot + 1;
791
792 _parseKeyBindingPairs(objectName, p, _rep->_keyBindings);
793 }
794
795 CIMObjectPath& CIMObjectPath::operator=(const String& objectName)
796 {
797 set(objectName);
798 return *this;
799 }
800
801 const String& CIMObjectPath::getHost() const
802 {
803 return _rep->_host;
804 }
805
806 void CIMObjectPath::setHost(const String& host)
807 {
808 kumpf 1.2 _rep->_host = host;
809 }
810
|
811 kumpf 1.7 const CIMNamespaceName& CIMObjectPath::getNameSpace() const
|
812 kumpf 1.2 {
813 return _rep->_nameSpace;
814 }
815
|
816 kumpf 1.7 void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace)
|
817 kumpf 1.2 {
818 _rep->_nameSpace = nameSpace;
819 }
820
|
821 kumpf 1.7 const CIMName& CIMObjectPath::getClassName() const
|
822 kumpf 1.2 {
823 return _rep->_className;
824 }
825
|
826 kumpf 1.7 void CIMObjectPath::setClassName(const CIMName& className)
|
827 kumpf 1.2 {
828 _rep->_className = className;
829 }
830
|
831 kumpf 1.16 const Array<CIMKeyBinding>& CIMObjectPath::getKeyBindings() const
|
832 kumpf 1.2 {
833 return _rep->_keyBindings;
834 }
835
|
836 kumpf 1.16 void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings)
|
837 kumpf 1.2 {
838 _rep->_keyBindings = keyBindings;
839 _BubbleSort(_rep->_keyBindings);
840 }
841
|
842 kumpf 1.15 String CIMObjectPath::toString() const
|
843 kumpf 1.2 {
844 String objectName;
845
846 // Get the host:
847
|
848 kumpf 1.15 if (_rep->_host.size())
|
849 kumpf 1.2 {
850 objectName = "//";
|
851 kumpf 1.13 objectName.append(_rep->_host);
852 objectName.append("/");
|
853 kumpf 1.2 }
854
855 // Get the namespace (if we have a host name, we must write namespace):
856
|
857 kumpf 1.7 if (!_rep->_nameSpace.isNull() || _rep->_host.size())
|
858 kumpf 1.2 {
|
859 kumpf 1.17 objectName.append(_rep->_nameSpace.getString ());
|
860 kumpf 1.13 objectName.append(":");
|
861 kumpf 1.2 }
862
863 // Get the class name:
864
|
865 kumpf 1.17 objectName.append(getClassName().getString ());
|
866 kumpf 1.2
|
867 kumpf 1.9 //
868 // ATTN-CAKG-P2-20020726: The following condition does not correctly
869 // distinguish instanceNames from classNames in every case
870 // The instanceName of a singleton instance of a keyless class has no
871 // key bindings
872 //
873 if (_rep->_keyBindings.size () != 0)
|
874 kumpf 1.2 {
875 objectName.append('.');
876
877 // Append each key-value pair:
878
|
879 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings = getKeyBindings();
|
880 kumpf 1.2
881 for (Uint32 i = 0, n = keyBindings.size(); i < n; i++)
882 {
|
883 kumpf 1.17 objectName.append(keyBindings[i].getName().getString ());
|
884 kumpf 1.2 objectName.append('=');
885
886 const String& value = _escapeSpecialCharacters(
887 keyBindings[i].getValue());
888
|
889 kumpf 1.16 CIMKeyBinding::Type type = keyBindings[i].getType();
|
890 kumpf 1.2
|
891 kumpf 1.16 if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
|
892 kumpf 1.2 objectName.append('"');
893
894 objectName.append(value);
895
|
896 kumpf 1.16 if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
|
897 kumpf 1.2 objectName.append('"');
898
899 if (i + 1 != n)
900 objectName.append(',');
901 }
902 }
903
904 return objectName;
905 }
906
|
907 kumpf 1.15 String CIMObjectPath::_toStringCanonical() const
|
908 kumpf 1.2 {
909 CIMObjectPath ref = *this;
910
911 // ATTN-RK-P2-20020510: Need to make hostname and namespace lower case?
912
|
913 kumpf 1.17 String classNameLower = ref._rep->_className.getString ();
|
914 david 1.27 classNameLower.toLower(); // ICU_TODO:
|
915 kumpf 1.7 ref._rep->_className = classNameLower;
|
916 kumpf 1.2
917 for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
918 {
|
919 kumpf 1.17 String keyBindingNameLower =
920 ref._rep->_keyBindings[i]._rep->_name.getString ();
|
921 kumpf 1.7 keyBindingNameLower.toLower();
922 ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
|
923 kumpf 1.2 }
924
|
925 kumpf 1.12 // ATTN-RK-20020826: Need to sort keys?
926
|
927 kumpf 1.15 return ref.toString();
|
928 kumpf 1.2 }
929
930 Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
931 {
932 return
933 String::equal(_rep->_host, x._rep->_host) &&
|
934 kumpf 1.7 _rep->_nameSpace.equal(x._rep->_nameSpace) &&
935 _rep->_className.equal(x._rep->_className) &&
|
936 kumpf 1.2 _rep->_keyBindings == x._rep->_keyBindings;
937 }
938
939 Uint32 CIMObjectPath::makeHashCode() const
940 {
|
941 kumpf 1.12 return HashFunc<String>::hash(_toStringCanonical());
|
942 kumpf 1.2 }
943
944 Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y)
945 {
946 return x.identical(y);
947 }
948
949 Boolean operator!=(const CIMObjectPath& x, const CIMObjectPath& y)
950 {
951 return !operator==(x, y);
952 }
953
|
954 kumpf 1.22 #ifndef PEGASUS_REMOVE_DEPRECATED
|
955 kumpf 1.2 PEGASUS_STD(ostream)& operator<<(
956 PEGASUS_STD(ostream)& os,
957 const CIMObjectPath& x)
958 {
959 return os << x.toString();
960 }
|
961 kumpf 1.22 #endif
|
962 chip 1.1
963 PEGASUS_NAMESPACE_END
|