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