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