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