1 karl 1.30 //%2003////////////////////////////////////////////////////////////////////////
|
2 chip 1.1 //
|
3 karl 1.30 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Development
4 // Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
|
7 chip 1.1 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
|
14 kumpf 1.6 //
|
15 chip 1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
16 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
17 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
18 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
19 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 //==============================================================================
25 //
|
26 kumpf 1.2 // Author: Mike Brasher (mbrasher@bmc.com)
|
27 chip 1.1 //
|
28 kumpf 1.2 // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
29 kumpf 1.9 // Carol Ann Krug Graves, Hewlett-Packard Company
30 // (carolann_graves@hp.com)
|
31 chip 1.1 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
|
34 kumpf 1.2 #include <Pegasus/Common/Config.h>
35 #include <cctype>
36 #include <cstring>
|
37 kumpf 1.22 #include <iostream>
|
38 kumpf 1.2 #include "HashTable.h"
39 #include "CIMObjectPath.h"
40 #include "Indentor.h"
41 #include "CIMName.h"
42 #include "Destroyer.h"
43 #include "XmlWriter.h"
44 #include "XmlReader.h"
|
45 kumpf 1.11 #include "ArrayInternal.h"
|
46 chip 1.1
47 PEGASUS_NAMESPACE_BEGIN
|
48 kumpf 1.2
|
49 kumpf 1.16 #define PEGASUS_ARRAY_T CIMKeyBinding
|
50 kumpf 1.2 # include "ArrayImpl.h"
51 #undef PEGASUS_ARRAY_T
52
53 #define PEGASUS_ARRAY_T CIMObjectPath
54 # include "ArrayImpl.h"
55 #undef PEGASUS_ARRAY_T
56
57 // ATTN: KS May 2002 P0 Add resolve method to CIMObjectPath.
58 // Add a resolve method to this class to verify that the
59 // reference is correct (that the class name corresponds to a real
60 // class and that the property names are really keys and that all keys
61 // of the class or used. Also be sure that there is a valid conversion
62 // between the string value and the value of that property).
63 //
64 // ATTN: also check to see that the reference refers to a class that is the
65 // same or derived from the _className member.
66
67 ////////////////////////////////////////////////////////////////////////////////
68 //
69 // Local routines:
70 //
71 kumpf 1.2 ////////////////////////////////////////////////////////////////////////////////
72
73 static String _escapeSpecialCharacters(const String& str)
74 {
75 String result;
76
77 for (Uint32 i = 0, n = str.size(); i < n; i++)
78 {
79 switch (str[i])
80 {
|
81 kumpf 1.28 case '\\':
82 result.append("\\\\");
|
83 kumpf 1.2 break;
84
85 case '"':
|
86 kumpf 1.13 result.append("\\\"");
|
87 kumpf 1.2 break;
88
89 default:
|
90 kumpf 1.13 result.append(str[i]);
|
91 kumpf 1.2 }
92 }
93
94 return result;
95 }
96
|
97 kumpf 1.16 static void _BubbleSort(Array<CIMKeyBinding>& x)
|
98 kumpf 1.2 {
99 Uint32 n = x.size();
100
|
101 kumpf 1.24 //
102 // If the key is a reference, the keys in the reference must also be
103 // sorted
104 //
105 for (Uint32 k = 0; k < n ; k++)
106 if (x[k].getType () == CIMKeyBinding::REFERENCE)
107 {
108 CIMObjectPath tmp (x[k].getValue ());
109 Array <CIMKeyBinding> keyBindings = tmp.getKeyBindings ();
110 _BubbleSort (keyBindings);
111 tmp.setKeyBindings (keyBindings);
112 x[k].setValue (tmp.toString ());
113 }
114
|
115 kumpf 1.2 if (n < 2)
116 return;
117
118 for (Uint32 i = 0; i < n - 1; i++)
119 {
120 for (Uint32 j = 0; j < n - 1; j++)
121 {
|
122 kumpf 1.17 if (String::compareNoCase(x[j].getName().getString(),
123 x[j+1].getName().getString()) > 0)
|
124 kumpf 1.2 {
|
125 kumpf 1.16 CIMKeyBinding t = x[j];
|
126 kumpf 1.2 x[j] = x[j+1];
127 x[j+1] = t;
128 }
129 }
130 }
131 }
132
133 ////////////////////////////////////////////////////////////////////////////////
134 //
|
135 kumpf 1.16 // CIMKeyBinding
|
136 kumpf 1.2 //
137 ////////////////////////////////////////////////////////////////////////////////
138
|
139 kumpf 1.16 class CIMKeyBindingRep
|
140 kumpf 1.2 {
141 public:
|
142 kumpf 1.16 CIMKeyBindingRep()
|
143 kumpf 1.2 {
144 }
145
|
146 kumpf 1.16 CIMKeyBindingRep(const CIMKeyBindingRep& x)
|
147 kumpf 1.2 : _name(x._name), _value(x._value), _type(x._type)
148 {
149 }
150
|
151 kumpf 1.16 CIMKeyBindingRep(
|
152 kumpf 1.7 const CIMName& name,
|
153 kumpf 1.2 const String& value,
|
154 kumpf 1.16 CIMKeyBinding::Type type)
|
155 kumpf 1.2 : _name(name), _value(value), _type(type)
156 {
157 }
158
|
159 kumpf 1.16 ~CIMKeyBindingRep()
|
160 kumpf 1.2 {
161 }
162
|
163 kumpf 1.16 CIMKeyBindingRep& operator=(const CIMKeyBindingRep& x)
|
164 kumpf 1.2 {
165 if (&x != this)
166 {
167 _name = x._name;
168 _value = x._value;
169 _type = x._type;
170 }
171 return *this;
172 }
173
|
174 kumpf 1.7 CIMName _name;
|
175 kumpf 1.2 String _value;
|
176 kumpf 1.16 CIMKeyBinding::Type _type;
|
177 kumpf 1.2 };
178
179
|
180 kumpf 1.16 CIMKeyBinding::CIMKeyBinding()
|
181 kumpf 1.2 {
|
182 kumpf 1.16 _rep = new CIMKeyBindingRep();
|
183 kumpf 1.2 }
184
|
185 kumpf 1.16 CIMKeyBinding::CIMKeyBinding(const CIMKeyBinding& x)
|
186 kumpf 1.2 {
|
187 kumpf 1.16 _rep = new CIMKeyBindingRep(*x._rep);
|
188 kumpf 1.2 }
189
|
190 kumpf 1.16 CIMKeyBinding::CIMKeyBinding(const CIMName& name, const String& value, Type type)
|
191 kumpf 1.2 {
|
192 kumpf 1.16 _rep = new CIMKeyBindingRep(name, value, type);
|
193 kumpf 1.2 }
194
|
195 kumpf 1.18 CIMKeyBinding::CIMKeyBinding(const CIMName& name, const CIMValue& value)
196 {
|
197 kumpf 1.21 if (value.isArray())
|
198 kumpf 1.20 {
199 throw TypeMismatchException();
200 }
201
|
202 kumpf 1.18 String kbValue = value.toString();
203 Type kbType;
204
205 switch (value.getType())
206 {
207 case CIMTYPE_BOOLEAN:
208 kbType = BOOLEAN;
209 break;
210 case CIMTYPE_CHAR16:
211 case CIMTYPE_STRING:
212 case CIMTYPE_DATETIME:
213 kbType = STRING;
214 break;
215 case CIMTYPE_REFERENCE:
216 kbType = REFERENCE;
217 break;
218 default:
219 kbType = NUMERIC;
220 break;
221 }
222
223 kumpf 1.18 _rep = new CIMKeyBindingRep(name, kbValue, kbType);
224 }
225
|
226 kumpf 1.16 CIMKeyBinding::~CIMKeyBinding()
|
227 kumpf 1.2 {
228 delete _rep;
229 }
230
|
231 kumpf 1.16 CIMKeyBinding& CIMKeyBinding::operator=(const CIMKeyBinding& x)
|
232 kumpf 1.2 {
233 *_rep = *x._rep;
234 return *this;
235 }
236
|
237 kumpf 1.16 const CIMName& CIMKeyBinding::getName() const
|
238 kumpf 1.2 {
239 return _rep->_name;
240 }
241
|
242 kumpf 1.16 void CIMKeyBinding::setName(const CIMName& name)
|
243 kumpf 1.2 {
244 _rep->_name = name;
245 }
246
|
247 kumpf 1.16 const String& CIMKeyBinding::getValue() const
|
248 kumpf 1.2 {
249 return _rep->_value;
250 }
251
|
252 kumpf 1.16 void CIMKeyBinding::setValue(const String& value)
|
253 kumpf 1.2 {
254 _rep->_value = value;
255 }
256
|
257 kumpf 1.16 CIMKeyBinding::Type CIMKeyBinding::getType() const
|
258 kumpf 1.2 {
259 return _rep->_type;
260 }
261
|
262 kumpf 1.16 void CIMKeyBinding::setType(CIMKeyBinding::Type type)
|
263 kumpf 1.2 {
264 _rep->_type = type;
265 }
|
266 kumpf 1.18
267 Boolean CIMKeyBinding::equal(CIMValue value)
268 {
|
269 kumpf 1.21 if (value.isArray())
|
270 kumpf 1.20 {
271 return false;
272 }
273
|
274 kumpf 1.18 CIMValue kbValue;
275
276 try
277 {
278 switch (value.getType())
279 {
280 case CIMTYPE_CHAR16:
|
281 kumpf 1.20 if (getType() != STRING) return false;
|
282 kumpf 1.18 kbValue.set(getValue()[0]);
283 break;
284 case CIMTYPE_DATETIME:
|
285 kumpf 1.20 if (getType() != STRING) return false;
|
286 kumpf 1.18 kbValue.set(CIMDateTime(getValue()));
287 break;
288 case CIMTYPE_STRING:
|
289 kumpf 1.20 if (getType() != STRING) return false;
|
290 kumpf 1.18 kbValue.set(getValue());
291 break;
292 case CIMTYPE_REFERENCE:
|
293 kumpf 1.20 if (getType() != REFERENCE) return false;
|
294 kumpf 1.18 kbValue.set(CIMObjectPath(getValue()));
295 break;
|
296 kumpf 1.20 case CIMTYPE_BOOLEAN:
297 if (getType() != BOOLEAN) return false;
298 kbValue = XmlReader::stringToValue(0, getValue().getCString(),
299 value.getType());
300 break;
301 default: // Numerics
302 if (getType() != NUMERIC) return false;
|
303 kumpf 1.18 kbValue = XmlReader::stringToValue(0, getValue().getCString(),
304 value.getType());
305 break;
306 }
307 }
|
308 kumpf 1.19 catch (Exception&)
|
309 kumpf 1.18 {
310 return false;
311 }
312
313 return value.equal(kbValue);
314 }
|
315 kumpf 1.2
|
316 kumpf 1.16 Boolean operator==(const CIMKeyBinding& x, const CIMKeyBinding& y)
|
317 kumpf 1.2 {
|
318 kumpf 1.33 // Check that the names and types match
319 if (!(x.getName().equal(y.getName())) ||
320 !(x.getType() == y.getType()))
321 {
322 return false;
323 }
324
325 switch (x.getType())
326 {
327 case CIMKeyBinding::REFERENCE:
328 try
329 {
330 // References should be compared as CIMObjectPaths
331 return (CIMObjectPath(x.getValue()) == CIMObjectPath(y.getValue()));
332 }
333 catch (Exception&)
334 {
335 // If CIMObjectPath parsing fails, just compare strings
336 return (String::equal(x.getValue(), y.getValue()));
337 }
338 break;
339 kumpf 1.33 case CIMKeyBinding::BOOLEAN:
340 // Case-insensitive comparison is sufficient for booleans
341 return (String::equalNoCase(x.getValue(), y.getValue()));
342 break;
343 case CIMKeyBinding::NUMERIC:
344 // Note: This comparison assumes XML syntax for integers
345 // First try comparing as unsigned integers
346 {
347 Uint64 xValue;
348 Uint64 yValue;
349 if (XmlReader::stringToUnsignedInteger(
350 x.getValue().getCString(), xValue) &&
351 XmlReader::stringToUnsignedInteger(
352 y.getValue().getCString(), yValue))
353 {
354 return (xValue == yValue);
355 }
356 }
357 // Next try comparing as signed integers
358 {
359 Sint64 xValue;
360 kumpf 1.33 Sint64 yValue;
361 if (XmlReader::stringToSignedInteger(
362 x.getValue().getCString(), xValue) &&
363 XmlReader::stringToSignedInteger(
364 y.getValue().getCString(), yValue))
365 {
366 return (xValue == yValue);
367 }
368 }
369 // Note: Keys may not be real values, so don't try comparing as reals
370 // We couldn't parse the numbers, so just compare the strings
371 return (String::equal(x.getValue(), y.getValue()));
372 break;
373 default: // CIMKeyBinding::STRING
374 return (String::equal(x.getValue(), y.getValue()));
375 break;
376 }
377
378 PEGASUS_UNREACHABLE(return false;)
|
379 kumpf 1.2 }
380
381
382 ////////////////////////////////////////////////////////////////////////////////
383 //
384 // CIMObjectPath
385 //
386 ////////////////////////////////////////////////////////////////////////////////
387
388 class CIMObjectPathRep
389 {
390 public:
391 CIMObjectPathRep()
392 {
393 }
394
395 CIMObjectPathRep(const CIMObjectPathRep& x)
396 : _host(x._host), _nameSpace(x._nameSpace),
397 _className(x._className), _keyBindings(x._keyBindings)
398 {
399 }
400 kumpf 1.2
401 CIMObjectPathRep(
402 const String& host,
|
403 kumpf 1.7 const CIMNamespaceName& nameSpace,
404 const CIMName& className,
|
405 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
406 kumpf 1.2 : _host(host), _nameSpace(nameSpace),
407 _className(className), _keyBindings(keyBindings)
408 {
409 }
410
411 ~CIMObjectPathRep()
412 {
413 }
414
415 CIMObjectPathRep& operator=(const CIMObjectPathRep& x)
416 {
417 if (&x != this)
418 {
419 _host = x._host;
420 _nameSpace = x._nameSpace;
421 _className = x._className;
422 _keyBindings = x._keyBindings;
423 }
424 return *this;
425 }
426
427 kumpf 1.2 //
428 // Contains port as well (e.g., myhost:1234).
429 //
430 String _host;
431
|
432 kumpf 1.7 CIMNamespaceName _nameSpace;
433 CIMName _className;
|
434 kumpf 1.16 Array<CIMKeyBinding> _keyBindings;
|
435 kumpf 1.2 };
436
437
438 CIMObjectPath::CIMObjectPath()
439 {
440 _rep = new CIMObjectPathRep();
441 }
442
443 CIMObjectPath::CIMObjectPath(const CIMObjectPath& x)
444 {
445 _rep = new CIMObjectPathRep(*x._rep);
446 }
447
448 CIMObjectPath::CIMObjectPath(const String& objectName)
449 {
450 // Test the objectName out to see if we get an exception
451 CIMObjectPath tmpRef;
452 tmpRef.set(objectName);
453
454 _rep = new CIMObjectPathRep(*tmpRef._rep);
455 }
456 kumpf 1.2
457 CIMObjectPath::CIMObjectPath(
458 const String& host,
|
459 kumpf 1.7 const CIMNamespaceName& nameSpace,
460 const CIMName& className,
|
461 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
462 kumpf 1.2 {
463 // Test the objectName out to see if we get an exception
464 CIMObjectPath tmpRef;
465 tmpRef.set(host, nameSpace, className, keyBindings);
466
467 _rep = new CIMObjectPathRep(*tmpRef._rep);
468 }
469
470 CIMObjectPath::~CIMObjectPath()
471 {
472 delete _rep;
473 }
474
475 CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x)
476 {
477 *_rep = *x._rep;
478 return *this;
479 }
480
481 void CIMObjectPath::clear()
482 {
483 kumpf 1.2 _rep->_host.clear();
484 _rep->_nameSpace.clear();
485 _rep->_className.clear();
486 _rep->_keyBindings.clear();
487 }
488
489 void CIMObjectPath::set(
490 const String& host,
|
491 kumpf 1.7 const CIMNamespaceName& nameSpace,
492 const CIMName& className,
|
493 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
494 kumpf 1.2 {
495 setHost(host);
496 setNameSpace(nameSpace);
497 setClassName(className);
498 setKeyBindings(keyBindings);
499 }
500
|
501 kumpf 1.22 Boolean _parseHostElement(
|
502 kumpf 1.2 const String& objectName,
503 char*& p,
|
504 kumpf 1.9 String& host)
|
505 kumpf 1.2 {
506 // See if there is a host name (true if it begins with "//"):
|
507 kumpf 1.32 // Host is of the form <hostname>:<port> and begins with "//"
|
508 kumpf 1.2 // and ends with "/":
509
510 if (p[0] != '/' || p[1] != '/')
511 {
512 return false;
513 }
514
515 p += 2;
516
517 //----------------------------------------------------------------------
|
518 chuck 1.23 // Validate the hostname. A domain is allowed after the hostname.
519 // Eg. xyz.company.com
520 // Hostnames must match the following regular expression:
521 // ^([A-Za-z][A-Za-z0-9-]*)(\.[A-Za-z][A-Za-z0-9-]*)*$
|
522 kumpf 1.2 //----------------------------------------------------------------------
523
524 char* q = p;
525
|
526 chuck 1.23 Boolean foundDot = true;
527 while (foundDot == true)
528 {
529 foundDot = false;
|
530 kumpf 1.2
|
531 chuck 1.23 if (!isalpha(*q))
532 throw MalformedObjectNameException(objectName);
|
533 kumpf 1.2
534 q++;
|
535 chuck 1.23
536 while (isalnum(*q) || *q == '-')
537 {
538 q++;
539 }
540
541 if (*q == '.')
542 {
543 q++;
544 foundDot = true;
545 }
546 }
|
547 kumpf 1.2
|
548 kumpf 1.32 // Check for a port:
|
549 kumpf 1.2
550 if (*q == ':')
551 {
552 q++;
553 // Check for a port number:
554
555 if (!isdigit(*q))
|
556 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
557 kumpf 1.2
558 while (isdigit(*q))
559 q++;
560 }
561
|
562 kumpf 1.32 // Finally, assign the host name:
|
563 kumpf 1.2
|
564 kumpf 1.32 host.assign(p, q - p);
|
565 kumpf 1.2
566 // Check for slash terminating the entire sequence:
567
568 if (*q != '/')
569 {
570 host.clear();
|
571 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
572 kumpf 1.2 }
573
|
574 kumpf 1.31 // Do not step past the '/'; it will be consumed by the namespace parser
575 p = q;
|
576 kumpf 1.2
577 return true;
578 }
579
|
580 kumpf 1.22 Boolean _parseNamespaceElement(
|
581 kumpf 1.2 const String& objectName,
582 char*& p,
|
583 kumpf 1.7 CIMNamespaceName& nameSpace)
|
584 kumpf 1.2 {
585 // If we don't find a valid namespace name followed by a ':', we
586 // assume we're not looking at a namespace name.
587
|
588 kumpf 1.7 char* colon = strchr(p, ':');
589 if (!colon)
590 {
591 return false;
592 }
593
|
594 kumpf 1.25 // A ':' as part of a keybinding value should not be interpreted as
595 // a namespace delimiter. Since keybinding pairs follow the first '.'
596 // in the object path string, the ':' delimiter only counts if it
597 // appears before the '.'.
598
599 char* dot = strchr(p, '.');
600 if (dot && (dot < colon))
601 {
602 return false;
603 }
604
|
605 kumpf 1.2 //----------------------------------------------------------------------
606 // Validate the namespace path. Namespaces must match the following
607 // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*"
608 //----------------------------------------------------------------------
609
|
610 david 1.27 String namespaceName = String(p, (Uint32)(colon - p));
|
611 kumpf 1.7 if (!CIMNamespaceName::legal(namespaceName))
|
612 kumpf 1.2 {
|
613 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
614 kumpf 1.2 }
|
615 kumpf 1.7 nameSpace = namespaceName;
|
616 kumpf 1.2
|
617 kumpf 1.7 p = colon+1;
|
618 kumpf 1.2 return true;
619 }
620
621 /**
|
622 kumpf 1.29 ATTN-RK: The DMTF specification for the string form of an
623 object path makes it impossible for a parser to distinguish
624 between a key values of String type and Reference type.
625
626 Given the ambiguity, this implementation takes a guess at the
627 type of a quoted key value. If the value can be parsed into
628 a CIMObjectPath with at least one key binding, the type is
629 set to REFERENCE. Otherwise, the type is set to STRING.
630 Note: This algorithm appears to be in line with what the Sun
631 WBEM Services implementation does.
632
633 To be totally correct, it would be necessary to retrieve the
634 class definition and look up the types of the key properties
635 to determine how to interpret the key values. This is clearly
636 too inefficient for internal transformations between
637 CIMObjectPaths and String values.
|
638 kumpf 1.2 */
|
639 kumpf 1.22 void _parseKeyBindingPairs(
|
640 kumpf 1.2 const String& objectName,
641 char*& p,
|
642 kumpf 1.16 Array<CIMKeyBinding>& keyBindings)
|
643 kumpf 1.2 {
644 // Get the key-value pairs:
645
646 while (*p)
647 {
648 // Get key part:
649
|
650 kumpf 1.5 char* equalsign = strchr(p, '=');
651 if (!equalsign)
|
652 kumpf 1.2 {
|
653 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
654 kumpf 1.2 }
655
|
656 kumpf 1.5 *equalsign = 0;
|
657 kumpf 1.2
|
658 kumpf 1.17 if (!CIMName::legal(p))
|
659 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
660 kumpf 1.2
|
661 kumpf 1.17 CIMName keyName (p);
662
|
663 kumpf 1.2 // Get the value part:
664
665 String valueString;
|
666 kumpf 1.5 p = equalsign + 1;
|
667 kumpf 1.16 CIMKeyBinding::Type type;
|
668 kumpf 1.2
|
669 kumpf 1.29 if (*p == '"')
|
670 kumpf 1.2 {
|
671 kumpf 1.29 // Could be CIMKeyBinding::STRING or CIMKeyBinding::REFERENCE
672
|
673 kumpf 1.2 p++;
674
675 while (*p && *p != '"')
676 {
677 if (*p == '\\')
|
678 kumpf 1.28 {
|
679 kumpf 1.2 *p++;
680
|
681 kumpf 1.28 if ((*p != '\\') && (*p != '"'))
682 {
683 throw MalformedObjectNameException(objectName);
684 }
685 }
686
|
687 kumpf 1.2 valueString.append(*p++);
688 }
689
690 if (*p++ != '"')
|
691 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
692 kumpf 1.2
|
693 kumpf 1.29 /*
694 Guess at the type of this quoted key value. If the value
695 can be parsed into a CIMObjectPath with at least one key
696 binding, the type is assumed to be a REFERENCE. Otherwise,
697 the type is set to STRING. (See method header for details.)
698 */
|
699 kumpf 1.16 type = CIMKeyBinding::STRING;
|
700 kumpf 1.2
|
701 kumpf 1.29 try
|
702 kumpf 1.2 {
|
703 kumpf 1.29 CIMObjectPath testForPath(valueString);
704 if (testForPath.getKeyBindings().size() > 0)
|
705 kumpf 1.28 {
|
706 kumpf 1.29 // We've found a reference value!
707 type = CIMKeyBinding::REFERENCE;
|
708 kumpf 1.28 }
|
709 kumpf 1.2 }
|
710 kumpf 1.29 catch (Exception & e)
711 {
712 // Not a reference value; leave type as STRING
713 }
|
714 kumpf 1.2 }
715 else if (toupper(*p) == 'T' || toupper(*p) == 'F')
716 {
|
717 kumpf 1.16 type = CIMKeyBinding::BOOLEAN;
|
718 kumpf 1.2
719 char* r = p;
720 Uint32 n = 0;
721
722 while (*r && *r != ',')
723 {
724 *r = toupper(*r);
725 r++;
726 n++;
727 }
728
729 if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) ||
730 ((strncmp(p, "FALSE", n) == 0) && n == 5)))
|
731 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
732 kumpf 1.2
733 valueString.assign(p, n);
734
735 p = p + n;
736 }
737 else
738 {
|
739 kumpf 1.16 type = CIMKeyBinding::NUMERIC;
|
740 kumpf 1.2
741 char* r = p;
742 Uint32 n = 0;
743
744 while (*r && *r != ',')
745 {
746 r++;
747 n++;
748 }
749
750 Boolean isComma = false;
751 if (*r)
752 {
753 *r = '\0';
754 isComma = true;
755 }
756
757 Sint64 x;
758
759 if (!XmlReader::stringToSignedInteger(p, x))
|
760 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
761 kumpf 1.2
762 valueString.assign(p, n);
763
764 if (isComma)
765 {
766 *r = ',';
767 }
768
769 p = p + n;
770 }
771
|
772 kumpf 1.17 keyBindings.append(CIMKeyBinding(keyName.getString (), valueString,
773 type));
|
774 kumpf 1.2
775 if (*p)
776 {
777 if (*p++ != ',')
778 {
|
779 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
780 kumpf 1.2 }
781 }
782 }
783
784 _BubbleSort(keyBindings);
785 }
786
|
787 kumpf 1.9 void CIMObjectPath::set(const String& objectName)
|
788 kumpf 1.2 {
789 clear();
790
791 //--------------------------------------------------------------------------
792 // We will extract components from an object name. Here is an sample
793 // object name:
794 //
795 // //atp:9999/root/cimv25:TennisPlayer.first="Patrick",last="Rafter"
796 //--------------------------------------------------------------------------
797
798 // Convert to a C String first:
799
|
800 david 1.27 CString pCString = objectName.getCStringUTF8();
|
801 kumpf 1.26 char* p = const_cast<char*>((const char*) pCString);
|
802 kumpf 1.2 Boolean gotHost;
803 Boolean gotNamespace;
804
805 gotHost = _parseHostElement(objectName, p, _rep->_host);
806 gotNamespace = _parseNamespaceElement(objectName, p, _rep->_nameSpace);
807
808 if (gotHost && !gotNamespace)
809 {
|
810 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
811 kumpf 1.2 }
812
813 // Extract the class name:
814
815 char* dot = strchr(p, '.');
816
817 if (!dot)
818 {
819 if (!CIMName::legal(p))
820 {
|
821 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
822 kumpf 1.2 }
823
824 // ATTN: remove this later: a reference should only be able to hold
825 // an instance name.
826
|
827 kumpf 1.17 _rep->_className = CIMName (p);
|
828 kumpf 1.2 return;
829 }
830
|
831 david 1.27 String className = String(p, (Uint32)(dot - p));
|
832 kumpf 1.7 if (!CIMName::legal(className))
833 {
|
834 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
835 kumpf 1.7 }
836 _rep->_className = className;
|
837 kumpf 1.2
838 // Advance past dot:
839
840 p = dot + 1;
841
842 _parseKeyBindingPairs(objectName, p, _rep->_keyBindings);
843 }
844
845 CIMObjectPath& CIMObjectPath::operator=(const String& objectName)
846 {
847 set(objectName);
848 return *this;
849 }
850
851 const String& CIMObjectPath::getHost() const
852 {
853 return _rep->_host;
854 }
855
856 void CIMObjectPath::setHost(const String& host)
857 {
858 kumpf 1.2 _rep->_host = host;
859 }
860
|
861 kumpf 1.7 const CIMNamespaceName& CIMObjectPath::getNameSpace() const
|
862 kumpf 1.2 {
863 return _rep->_nameSpace;
864 }
865
|
866 kumpf 1.7 void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace)
|
867 kumpf 1.2 {
868 _rep->_nameSpace = nameSpace;
869 }
870
|
871 kumpf 1.7 const CIMName& CIMObjectPath::getClassName() const
|
872 kumpf 1.2 {
873 return _rep->_className;
874 }
875
|
876 kumpf 1.7 void CIMObjectPath::setClassName(const CIMName& className)
|
877 kumpf 1.2 {
878 _rep->_className = className;
879 }
880
|
881 kumpf 1.16 const Array<CIMKeyBinding>& CIMObjectPath::getKeyBindings() const
|
882 kumpf 1.2 {
883 return _rep->_keyBindings;
884 }
885
|
886 kumpf 1.16 void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings)
|
887 kumpf 1.2 {
888 _rep->_keyBindings = keyBindings;
889 _BubbleSort(_rep->_keyBindings);
890 }
891
|
892 kumpf 1.15 String CIMObjectPath::toString() const
|
893 kumpf 1.2 {
894 String objectName;
895
896 // Get the host:
897
|
898 kumpf 1.15 if (_rep->_host.size())
|
899 kumpf 1.2 {
900 objectName = "//";
|
901 kumpf 1.13 objectName.append(_rep->_host);
902 objectName.append("/");
|
903 kumpf 1.2 }
904
905 // Get the namespace (if we have a host name, we must write namespace):
906
|
907 kumpf 1.7 if (!_rep->_nameSpace.isNull() || _rep->_host.size())
|
908 kumpf 1.2 {
|
909 kumpf 1.17 objectName.append(_rep->_nameSpace.getString ());
|
910 kumpf 1.13 objectName.append(":");
|
911 kumpf 1.2 }
912
913 // Get the class name:
914
|
915 kumpf 1.17 objectName.append(getClassName().getString ());
|
916 kumpf 1.2
|
917 kumpf 1.9 //
918 // ATTN-CAKG-P2-20020726: The following condition does not correctly
919 // distinguish instanceNames from classNames in every case
920 // The instanceName of a singleton instance of a keyless class has no
921 // key bindings
922 //
923 if (_rep->_keyBindings.size () != 0)
|
924 kumpf 1.2 {
925 objectName.append('.');
926
927 // Append each key-value pair:
928
|
929 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings = getKeyBindings();
|
930 kumpf 1.2
931 for (Uint32 i = 0, n = keyBindings.size(); i < n; i++)
932 {
|
933 kumpf 1.17 objectName.append(keyBindings[i].getName().getString ());
|
934 kumpf 1.2 objectName.append('=');
935
936 const String& value = _escapeSpecialCharacters(
937 keyBindings[i].getValue());
938
|
939 kumpf 1.16 CIMKeyBinding::Type type = keyBindings[i].getType();
|
940 kumpf 1.2
|
941 kumpf 1.16 if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
|
942 kumpf 1.2 objectName.append('"');
943
944 objectName.append(value);
945
|
946 kumpf 1.16 if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
|
947 kumpf 1.2 objectName.append('"');
948
949 if (i + 1 != n)
950 objectName.append(',');
951 }
952 }
953
954 return objectName;
955 }
956
|
957 kumpf 1.15 String CIMObjectPath::_toStringCanonical() const
|
958 kumpf 1.2 {
959 CIMObjectPath ref = *this;
960
|
961 kumpf 1.33 // Normalize hostname by changing to lower case
962 ref._rep->_host.toLower(); // ICU_TODO:
|
963 kumpf 1.2
|
964 kumpf 1.33 // Normalize namespace by changing to lower case
965 if (!ref._rep->_nameSpace.isNull())
966 {
967 String nameSpaceLower = ref._rep->_nameSpace.getString();
968 nameSpaceLower.toLower(); // ICU_TODO:
969 ref._rep->_nameSpace = nameSpaceLower;
970 }
971
972 // Normalize class name by changing to lower case
973 if (!ref._rep->_className.isNull())
974 {
975 String classNameLower = ref._rep->_className.getString();
976 classNameLower.toLower(); // ICU_TODO:
977 ref._rep->_className = classNameLower;
978 }
|
979 kumpf 1.2
980 for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
981 {
|
982 kumpf 1.33 // Normalize key binding name by changing to lower case
983 if (!ref._rep->_keyBindings[i]._rep->_name.isNull())
984 {
985 String keyBindingNameLower =
986 ref._rep->_keyBindings[i]._rep->_name.getString();
987 keyBindingNameLower.toLower(); // ICU_TODO:
988 ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
989 }
990
991 // Normalize the key value
992 switch (ref._rep->_keyBindings[i]._rep->_type)
993 {
994 case CIMKeyBinding::REFERENCE:
995 try
996 {
997 // Convert reference to CIMObjectPath and recurse
998 ref._rep->_keyBindings[i]._rep->_value =
999 CIMObjectPath(ref._rep->_keyBindings[i]._rep->_value).
1000 _toStringCanonical();
1001 }
1002 catch (Exception&)
1003 kumpf 1.33 {
1004 // Leave value unchanged if the CIMObjectPath parsing fails
1005 }
1006 break;
1007 case CIMKeyBinding::BOOLEAN:
1008 // Normalize the boolean string by changing to lower case
1009 ref._rep->_keyBindings[i]._rep->_value.toLower(); // ICU_TODO:
1010 break;
1011 case CIMKeyBinding::NUMERIC:
1012 // Normalize the numeric string by converting to integer and back
1013 Uint64 uValue;
1014 Sint64 sValue;
1015 // First try converting to unsigned integer
1016 if (XmlReader::stringToUnsignedInteger(
1017 ref._rep->_keyBindings[i]._rep->_value.getCString(),
1018 uValue))
1019 {
1020 char buffer[32]; // Should need 21 chars max
1021 sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", uValue);
1022 ref._rep->_keyBindings[i]._rep->_value = String(buffer);
1023 }
1024 kumpf 1.33 // Next try converting to signed integer
1025 else if (XmlReader::stringToSignedInteger(
1026 ref._rep->_keyBindings[i]._rep->_value.getCString(),
1027 sValue))
1028 {
1029 char buffer[32]; // Should need 21 chars max
1030 sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "d", sValue);
1031 ref._rep->_keyBindings[i]._rep->_value = String(buffer);
1032 }
1033 // Leave value unchanged if it cannot be converted to an integer
1034 break;
1035 default: // CIMKeyBinding::STRING
1036 // No normalization required for STRING
1037 break;
1038 }
|
1039 kumpf 1.2 }
1040
|
1041 kumpf 1.33 // Note: key bindings are sorted when set in the CIMObjectPath
|
1042 kumpf 1.12
|
1043 kumpf 1.15 return ref.toString();
|
1044 kumpf 1.2 }
1045
1046 Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
1047 {
1048 return
|
1049 kumpf 1.33 String::equalNoCase(_rep->_host, x._rep->_host) &&
|
1050 kumpf 1.7 _rep->_nameSpace.equal(x._rep->_nameSpace) &&
1051 _rep->_className.equal(x._rep->_className) &&
|
1052 kumpf 1.2 _rep->_keyBindings == x._rep->_keyBindings;
1053 }
1054
1055 Uint32 CIMObjectPath::makeHashCode() const
1056 {
|
1057 kumpf 1.12 return HashFunc<String>::hash(_toStringCanonical());
|
1058 kumpf 1.2 }
1059
1060 Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y)
1061 {
1062 return x.identical(y);
1063 }
1064
1065 Boolean operator!=(const CIMObjectPath& x, const CIMObjectPath& y)
1066 {
1067 return !operator==(x, y);
1068 }
1069
|
1070 kumpf 1.22 #ifndef PEGASUS_REMOVE_DEPRECATED
|
1071 kumpf 1.2 PEGASUS_STD(ostream)& operator<<(
1072 PEGASUS_STD(ostream)& os,
1073 const CIMObjectPath& x)
1074 {
1075 return os << x.toString();
1076 }
|
1077 kumpf 1.22 #endif
|
1078 chip 1.1
1079 PEGASUS_NAMESPACE_END
|