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 dave.sudlik 1.58.4.1 #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 dave.sudlik 1.58.4.1 HostLocator addr(hostname);
|
450 kumpf 1.34
|
451 dave.sudlik 1.58.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 kumpf 1.58.4.2 Array<Uint8> keyValueUTF8;
659 keyValueUTF8.reserveCapacity(128);
660
|
661 kumpf 1.2 while (*p && *p != '"')
662 {
663 if (*p == '\\')
|
664 kumpf 1.28 {
|
665 kumpf 1.58.4.2 p++;
|
666 kumpf 1.2
|
667 kumpf 1.28 if ((*p != '\\') && (*p != '"'))
668 {
669 throw MalformedObjectNameException(objectName);
670 }
671 }
672
|
673 kumpf 1.58.4.2 keyValueUTF8.append(*p++);
|
674 kumpf 1.2 }
675
676 if (*p++ != '"')
|
677 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
678 kumpf 1.2
|
679 kumpf 1.58.4.2 // Convert the UTF-8 value to a UTF-16 String
680
681 valueString.assign(
682 (const char*)keyValueUTF8.getData(),
683 keyValueUTF8.size());
684
|
685 kumpf 1.29 /*
686 Guess at the type of this quoted key value. If the value
687 can be parsed into a CIMObjectPath with at least one key
688 binding, the type is assumed to be a REFERENCE. Otherwise,
689 the type is set to STRING. (See method header for details.)
690 */
|
691 kumpf 1.16 type = CIMKeyBinding::STRING;
|
692 kumpf 1.2
|
693 kumpf 1.29 try
|
694 kumpf 1.2 {
|
695 kumpf 1.29 CIMObjectPath testForPath(valueString);
696 if (testForPath.getKeyBindings().size() > 0)
|
697 kumpf 1.28 {
|
698 kumpf 1.29 // We've found a reference value!
699 type = CIMKeyBinding::REFERENCE;
|
700 kumpf 1.28 }
|
701 kumpf 1.2 }
|
702 david.dillard 1.41 catch (const Exception &)
|
703 kumpf 1.29 {
704 // Not a reference value; leave type as STRING
705 }
|
706 kumpf 1.2 }
707 else if (toupper(*p) == 'T' || toupper(*p) == 'F')
708 {
|
709 kumpf 1.16 type = CIMKeyBinding::BOOLEAN;
|
710 kumpf 1.2
711 char* r = p;
712 Uint32 n = 0;
713
714 while (*r && *r != ',')
715 {
716 *r = toupper(*r);
717 r++;
718 n++;
719 }
720
721 if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) ||
722 ((strncmp(p, "FALSE", n) == 0) && n == 5)))
|
723 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
724 kumpf 1.2
725 valueString.assign(p, n);
726
727 p = p + n;
728 }
729 else
730 {
|
731 kumpf 1.16 type = CIMKeyBinding::NUMERIC;
|
732 kumpf 1.2
733 char* r = p;
734 Uint32 n = 0;
735
736 while (*r && *r != ',')
737 {
738 r++;
739 n++;
740 }
741
742 Boolean isComma = false;
743 if (*r)
744 {
745 *r = '\0';
746 isComma = true;
747 }
748
|
749 r.kieninger 1.56 if (*p == '-')
750 {
751 Sint64 x;
752 if (!XmlReader::stringToSignedInteger(p, x))
753 throw MalformedObjectNameException(objectName);
754 }
755 else
756 {
757 Uint64 x;
758 if (!XmlReader::stringToUnsignedInteger(p, x))
759 throw MalformedObjectNameException(objectName);
760 }
|
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 chip 1.47 keyBindings.append(CIMKeyBinding(keyName.getString (), valueString,
|
773 kumpf 1.17 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 chip 1.47 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.37 CString pCString = objectName.getCString();
|
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.35 if ((host != String::EMPTY) && !CIMObjectPathRep::isValidHostname(host))
859 {
860 throw MalformedObjectNameException(host);
861 }
862
|
863 kumpf 1.2 _rep->_host = host;
864 }
865
|
866 kumpf 1.7 const CIMNamespaceName& CIMObjectPath::getNameSpace() const
|
867 kumpf 1.2 {
868 return _rep->_nameSpace;
869 }
870
|
871 kumpf 1.7 void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace)
|
872 kumpf 1.2 {
873 _rep->_nameSpace = nameSpace;
874 }
875
|
876 kumpf 1.7 const CIMName& CIMObjectPath::getClassName() const
|
877 kumpf 1.2 {
878 return _rep->_className;
879 }
880
|
881 kumpf 1.7 void CIMObjectPath::setClassName(const CIMName& className)
|
882 kumpf 1.2 {
883 _rep->_className = className;
884 }
885
|
886 kumpf 1.16 const Array<CIMKeyBinding>& CIMObjectPath::getKeyBindings() const
|
887 kumpf 1.2 {
888 return _rep->_keyBindings;
889 }
890
|
891 kumpf 1.16 void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings)
|
892 kumpf 1.2 {
893 _rep->_keyBindings = keyBindings;
894 _BubbleSort(_rep->_keyBindings);
895 }
896
|
897 kumpf 1.15 String CIMObjectPath::toString() const
|
898 kumpf 1.2 {
899 String objectName;
900
901 // Get the host:
902
|
903 kumpf 1.15 if (_rep->_host.size())
|
904 kumpf 1.2 {
905 objectName = "//";
|
906 kumpf 1.13 objectName.append(_rep->_host);
907 objectName.append("/");
|
908 kumpf 1.2 }
909
910 // Get the namespace (if we have a host name, we must write namespace):
911
|
912 kumpf 1.7 if (!_rep->_nameSpace.isNull() || _rep->_host.size())
|
913 kumpf 1.2 {
|
914 kumpf 1.17 objectName.append(_rep->_nameSpace.getString ());
|
915 kumpf 1.13 objectName.append(":");
|
916 kumpf 1.2 }
917
918 // Get the class name:
919
|
920 kumpf 1.17 objectName.append(getClassName().getString ());
|
921 kumpf 1.2
|
922 kumpf 1.9 //
923 // ATTN-CAKG-P2-20020726: The following condition does not correctly
924 // distinguish instanceNames from classNames in every case
925 // The instanceName of a singleton instance of a keyless class has no
926 // key bindings
927 //
928 if (_rep->_keyBindings.size () != 0)
|
929 kumpf 1.2 {
930 objectName.append('.');
931
932 // Append each key-value pair:
933
|
934 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings = getKeyBindings();
|
935 kumpf 1.2
936 for (Uint32 i = 0, n = keyBindings.size(); i < n; i++)
937 {
|
938 kumpf 1.17 objectName.append(keyBindings[i].getName().getString ());
|
939 kumpf 1.2 objectName.append('=');
940
941 const String& value = _escapeSpecialCharacters(
942 keyBindings[i].getValue());
943
|
944 kumpf 1.16 CIMKeyBinding::Type type = keyBindings[i].getType();
|
945 chip 1.47
|
946 kumpf 1.57 if (type == CIMKeyBinding::STRING ||
947 type == CIMKeyBinding::REFERENCE)
|
948 kumpf 1.2 objectName.append('"');
949
950 objectName.append(value);
951
|
952 kumpf 1.57 if (type == CIMKeyBinding::STRING ||
953 type == CIMKeyBinding::REFERENCE)
|
954 kumpf 1.2 objectName.append('"');
955
956 if (i + 1 != n)
957 objectName.append(',');
958 }
959 }
960
961 return objectName;
962 }
963
|
964 kumpf 1.15 String CIMObjectPath::_toStringCanonical() const
|
965 kumpf 1.2 {
966 CIMObjectPath ref = *this;
967
|
968 kumpf 1.33 // Normalize hostname by changing to lower case
|
969 chip 1.47 ref._rep->_host.toLower(); // ICU_TODO:
|
970 kumpf 1.2
|
971 kumpf 1.33 // Normalize namespace by changing to lower case
972 if (!ref._rep->_nameSpace.isNull())
973 {
974 String nameSpaceLower = ref._rep->_nameSpace.getString();
|
975 chip 1.47 nameSpaceLower.toLower(); // ICU_TODO:
|
976 kumpf 1.33 ref._rep->_nameSpace = nameSpaceLower;
977 }
978
979 // Normalize class name by changing to lower case
980 if (!ref._rep->_className.isNull())
981 {
982 String classNameLower = ref._rep->_className.getString();
|
983 chip 1.47 classNameLower.toLower(); // ICU_TODO:
|
984 kumpf 1.33 ref._rep->_className = classNameLower;
985 }
|
986 kumpf 1.2
987 for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
988 {
|
989 kumpf 1.33 // Normalize key binding name by changing to lower case
990 if (!ref._rep->_keyBindings[i]._rep->_name.isNull())
991 {
|
992 chip 1.47 String keyBindingNameLower =
|
993 kumpf 1.33 ref._rep->_keyBindings[i]._rep->_name.getString();
994 keyBindingNameLower.toLower(); // ICU_TODO:
995 ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
996 }
997
998 // Normalize the key value
999 switch (ref._rep->_keyBindings[i]._rep->_type)
1000 {
1001 case CIMKeyBinding::REFERENCE:
1002 try
1003 {
1004 // Convert reference to CIMObjectPath and recurse
1005 ref._rep->_keyBindings[i]._rep->_value =
1006 CIMObjectPath(ref._rep->_keyBindings[i]._rep->_value).
1007 _toStringCanonical();
1008 }
1009 catch (Exception&)
1010 {
1011 // Leave value unchanged if the CIMObjectPath parsing fails
1012 }
1013 break;
1014 kumpf 1.33 case CIMKeyBinding::BOOLEAN:
1015 // Normalize the boolean string by changing to lower case
1016 ref._rep->_keyBindings[i]._rep->_value.toLower(); // ICU_TODO:
1017 break;
1018 case CIMKeyBinding::NUMERIC:
1019 // Normalize the numeric string by converting to integer and back
1020 Uint64 uValue;
1021 Sint64 sValue;
1022 // First try converting to unsigned integer
1023 if (XmlReader::stringToUnsignedInteger(
1024 ref._rep->_keyBindings[i]._rep->_value.getCString(),
1025 uValue))
1026 {
1027 char buffer[32]; // Should need 21 chars max
1028 sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", uValue);
1029 ref._rep->_keyBindings[i]._rep->_value = String(buffer);
1030 }
1031 // Next try converting to signed integer
1032 else if (XmlReader::stringToSignedInteger(
1033 ref._rep->_keyBindings[i]._rep->_value.getCString(),
1034 sValue))
1035 kumpf 1.33 {
1036 char buffer[32]; // Should need 21 chars max
1037 sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "d", sValue);
1038 ref._rep->_keyBindings[i]._rep->_value = String(buffer);
1039 }
1040 // Leave value unchanged if it cannot be converted to an integer
1041 break;
1042 default: // CIMKeyBinding::STRING
1043 // No normalization required for STRING
1044 break;
1045 }
|
1046 kumpf 1.2 }
1047
|
1048 kumpf 1.33 // Note: key bindings are sorted when set in the CIMObjectPath
|
1049 kumpf 1.12
|
1050 kumpf 1.15 return ref.toString();
|
1051 kumpf 1.2 }
1052
1053 Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
1054 {
1055 return
|
1056 kumpf 1.33 String::equalNoCase(_rep->_host, x._rep->_host) &&
|
1057 kumpf 1.7 _rep->_nameSpace.equal(x._rep->_nameSpace) &&
1058 _rep->_className.equal(x._rep->_className) &&
|
1059 kumpf 1.2 _rep->_keyBindings == x._rep->_keyBindings;
1060 }
1061
1062 Uint32 CIMObjectPath::makeHashCode() const
1063 {
|
1064 kumpf 1.12 return HashFunc<String>::hash(_toStringCanonical());
|
1065 kumpf 1.2 }
1066
1067 Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y)
1068 {
1069 return x.identical(y);
1070 }
1071
1072 Boolean operator!=(const CIMObjectPath& x, const CIMObjectPath& y)
1073 {
1074 return !operator==(x, y);
1075 }
1076
|
1077 chip 1.1 PEGASUS_NAMESPACE_END
|