1 kumpf 1.2 //%/////////////////////////////////////////////////////////////////////////////
|
2 chip 1.1 //
|
3 kumpf 1.6 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
|
5 chip 1.1 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
|
12 kumpf 1.6 //
|
13 chip 1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
14 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 //==============================================================================
23 //
|
24 kumpf 1.2 // Author: Mike Brasher (mbrasher@bmc.com)
|
25 chip 1.1 //
|
26 kumpf 1.2 // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
27 kumpf 1.9 // Carol Ann Krug Graves, Hewlett-Packard Company
28 // (carolann_graves@hp.com)
|
29 chip 1.1 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
|
32 kumpf 1.2 #include <Pegasus/Common/Config.h>
33 #include <cctype>
34 #include <cstring>
|
35 kumpf 1.22 #include <iostream>
|
36 kumpf 1.2 #include "HashTable.h"
37 #include "CIMObjectPath.h"
38 #include "Indentor.h"
39 #include "CIMName.h"
40 #include "Destroyer.h"
41 #include "XmlWriter.h"
42 #include "XmlReader.h"
|
43 kumpf 1.11 #include "ArrayInternal.h"
|
44 kumpf 1.2 #include "CIMOMPort.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 case '\n':
|
81 kumpf 1.13 result.append("\\n");
|
82 kumpf 1.2 break;
83
84 case '\r':
|
85 kumpf 1.13 result.append("\\r");
|
86 kumpf 1.2 break;
87
88 case '\t':
|
89 kumpf 1.13 result.append("\\t");
|
90 kumpf 1.2 break;
91
92 case '"':
|
93 kumpf 1.13 result.append("\\\"");
|
94 kumpf 1.2 break;
95
96 default:
|
97 kumpf 1.13 result.append(str[i]);
|
98 kumpf 1.2 }
99 }
100
101 return result;
102 }
103
|
104 kumpf 1.16 static void _BubbleSort(Array<CIMKeyBinding>& x)
|
105 kumpf 1.2 {
106 Uint32 n = x.size();
107
|
108 kumpf 1.24 //
109 // If the key is a reference, the keys in the reference must also be
110 // sorted
111 //
112 for (Uint32 k = 0; k < n ; k++)
113 if (x[k].getType () == CIMKeyBinding::REFERENCE)
114 {
115 CIMObjectPath tmp (x[k].getValue ());
116 Array <CIMKeyBinding> keyBindings = tmp.getKeyBindings ();
117 _BubbleSort (keyBindings);
118 tmp.setKeyBindings (keyBindings);
119 x[k].setValue (tmp.toString ());
120 }
121
|
122 kumpf 1.2 if (n < 2)
123 return;
124
125 for (Uint32 i = 0; i < n - 1; i++)
126 {
127 for (Uint32 j = 0; j < n - 1; j++)
128 {
|
129 kumpf 1.17 if (String::compareNoCase(x[j].getName().getString(),
130 x[j+1].getName().getString()) > 0)
|
131 kumpf 1.2 {
|
132 kumpf 1.16 CIMKeyBinding t = x[j];
|
133 kumpf 1.2 x[j] = x[j+1];
134 x[j+1] = t;
135 }
136 }
137 }
138 }
139
140 ////////////////////////////////////////////////////////////////////////////////
141 //
|
142 kumpf 1.16 // CIMKeyBinding
|
143 kumpf 1.2 //
144 ////////////////////////////////////////////////////////////////////////////////
145
|
146 kumpf 1.16 class CIMKeyBindingRep
|
147 kumpf 1.2 {
148 public:
|
149 kumpf 1.16 CIMKeyBindingRep()
|
150 kumpf 1.2 {
151 }
152
|
153 kumpf 1.16 CIMKeyBindingRep(const CIMKeyBindingRep& x)
|
154 kumpf 1.2 : _name(x._name), _value(x._value), _type(x._type)
155 {
156 }
157
|
158 kumpf 1.16 CIMKeyBindingRep(
|
159 kumpf 1.7 const CIMName& name,
|
160 kumpf 1.2 const String& value,
|
161 kumpf 1.16 CIMKeyBinding::Type type)
|
162 kumpf 1.2 : _name(name), _value(value), _type(type)
163 {
164 }
165
|
166 kumpf 1.16 ~CIMKeyBindingRep()
|
167 kumpf 1.2 {
168 }
169
|
170 kumpf 1.16 CIMKeyBindingRep& operator=(const CIMKeyBindingRep& x)
|
171 kumpf 1.2 {
172 if (&x != this)
173 {
174 _name = x._name;
175 _value = x._value;
176 _type = x._type;
177 }
178 return *this;
179 }
180
|
181 kumpf 1.7 CIMName _name;
|
182 kumpf 1.2 String _value;
|
183 kumpf 1.16 CIMKeyBinding::Type _type;
|
184 kumpf 1.2 };
185
186
|
187 kumpf 1.16 CIMKeyBinding::CIMKeyBinding()
|
188 kumpf 1.2 {
|
189 kumpf 1.16 _rep = new CIMKeyBindingRep();
|
190 kumpf 1.2 }
191
|
192 kumpf 1.16 CIMKeyBinding::CIMKeyBinding(const CIMKeyBinding& x)
|
193 kumpf 1.2 {
|
194 kumpf 1.16 _rep = new CIMKeyBindingRep(*x._rep);
|
195 kumpf 1.2 }
196
|
197 kumpf 1.16 CIMKeyBinding::CIMKeyBinding(const CIMName& name, const String& value, Type type)
|
198 kumpf 1.2 {
|
199 kumpf 1.16 _rep = new CIMKeyBindingRep(name, value, type);
|
200 kumpf 1.2 }
201
|
202 kumpf 1.18 CIMKeyBinding::CIMKeyBinding(const CIMName& name, const CIMValue& value)
203 {
|
204 kumpf 1.21 if (value.isArray())
|
205 kumpf 1.20 {
206 throw TypeMismatchException();
207 }
208
|
209 kumpf 1.18 String kbValue = value.toString();
210 Type kbType;
211
212 switch (value.getType())
213 {
214 case CIMTYPE_BOOLEAN:
215 kbType = BOOLEAN;
216 break;
217 case CIMTYPE_CHAR16:
218 case CIMTYPE_STRING:
219 case CIMTYPE_DATETIME:
220 kbType = STRING;
221 break;
222 case CIMTYPE_REFERENCE:
223 kbType = REFERENCE;
224 break;
225 default:
226 kbType = NUMERIC;
227 break;
228 }
229
230 kumpf 1.18 _rep = new CIMKeyBindingRep(name, kbValue, kbType);
231 }
232
|
233 kumpf 1.16 CIMKeyBinding::~CIMKeyBinding()
|
234 kumpf 1.2 {
235 delete _rep;
236 }
237
|
238 kumpf 1.16 CIMKeyBinding& CIMKeyBinding::operator=(const CIMKeyBinding& x)
|
239 kumpf 1.2 {
240 *_rep = *x._rep;
241 return *this;
242 }
243
|
244 kumpf 1.16 const CIMName& CIMKeyBinding::getName() const
|
245 kumpf 1.2 {
246 return _rep->_name;
247 }
248
|
249 kumpf 1.16 void CIMKeyBinding::setName(const CIMName& name)
|
250 kumpf 1.2 {
251 _rep->_name = name;
252 }
253
|
254 kumpf 1.16 const String& CIMKeyBinding::getValue() const
|
255 kumpf 1.2 {
256 return _rep->_value;
257 }
258
|
259 kumpf 1.16 void CIMKeyBinding::setValue(const String& value)
|
260 kumpf 1.2 {
261 _rep->_value = value;
262 }
263
|
264 kumpf 1.16 CIMKeyBinding::Type CIMKeyBinding::getType() const
|
265 kumpf 1.2 {
266 return _rep->_type;
267 }
268
|
269 kumpf 1.16 void CIMKeyBinding::setType(CIMKeyBinding::Type type)
|
270 kumpf 1.2 {
271 _rep->_type = type;
272 }
|
273 kumpf 1.18
274 Boolean CIMKeyBinding::equal(CIMValue value)
275 {
|
276 kumpf 1.21 if (value.isArray())
|
277 kumpf 1.20 {
278 return false;
279 }
280
|
281 kumpf 1.18 CIMValue kbValue;
282
283 try
284 {
285 switch (value.getType())
286 {
287 case CIMTYPE_CHAR16:
|
288 kumpf 1.20 if (getType() != STRING) return false;
|
289 kumpf 1.18 kbValue.set(getValue()[0]);
290 break;
291 case CIMTYPE_DATETIME:
|
292 kumpf 1.20 if (getType() != STRING) return false;
|
293 kumpf 1.18 kbValue.set(CIMDateTime(getValue()));
294 break;
295 case CIMTYPE_STRING:
|
296 kumpf 1.20 if (getType() != STRING) return false;
|
297 kumpf 1.18 kbValue.set(getValue());
298 break;
299 case CIMTYPE_REFERENCE:
|
300 kumpf 1.20 if (getType() != REFERENCE) return false;
|
301 kumpf 1.18 kbValue.set(CIMObjectPath(getValue()));
302 break;
|
303 kumpf 1.20 case CIMTYPE_BOOLEAN:
304 if (getType() != BOOLEAN) return false;
305 kbValue = XmlReader::stringToValue(0, getValue().getCString(),
306 value.getType());
307 break;
308 default: // Numerics
309 if (getType() != NUMERIC) return false;
|
310 kumpf 1.18 kbValue = XmlReader::stringToValue(0, getValue().getCString(),
311 value.getType());
312 break;
313 }
314 }
|
315 kumpf 1.19 catch (Exception&)
|
316 kumpf 1.18 {
317 return false;
318 }
319
320 return value.equal(kbValue);
321 }
|
322 kumpf 1.2
|
323 kumpf 1.16 Boolean operator==(const CIMKeyBinding& x, const CIMKeyBinding& y)
|
324 kumpf 1.2 {
325 return
|
326 kumpf 1.7 x.getName().equal(y.getName()) &&
|
327 kumpf 1.2 String::equal(x.getValue(), y.getValue()) &&
328 x.getType() == y.getType();
329 }
330
331
332 ////////////////////////////////////////////////////////////////////////////////
333 //
334 // CIMObjectPath
335 //
336 ////////////////////////////////////////////////////////////////////////////////
337
338 class CIMObjectPathRep
339 {
340 public:
341 CIMObjectPathRep()
342 {
343 }
344
345 CIMObjectPathRep(const CIMObjectPathRep& x)
346 : _host(x._host), _nameSpace(x._nameSpace),
347 _className(x._className), _keyBindings(x._keyBindings)
348 kumpf 1.2 {
349 }
350
351 CIMObjectPathRep(
352 const String& host,
|
353 kumpf 1.7 const CIMNamespaceName& nameSpace,
354 const CIMName& className,
|
355 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
356 kumpf 1.2 : _host(host), _nameSpace(nameSpace),
357 _className(className), _keyBindings(keyBindings)
358 {
359 }
360
361 ~CIMObjectPathRep()
362 {
363 }
364
365 CIMObjectPathRep& operator=(const CIMObjectPathRep& x)
366 {
367 if (&x != this)
368 {
369 _host = x._host;
370 _nameSpace = x._nameSpace;
371 _className = x._className;
372 _keyBindings = x._keyBindings;
373 }
374 return *this;
375 }
376
377 kumpf 1.2 //
378 // Contains port as well (e.g., myhost:1234).
379 //
380 String _host;
381
|
382 kumpf 1.7 CIMNamespaceName _nameSpace;
383 CIMName _className;
|
384 kumpf 1.16 Array<CIMKeyBinding> _keyBindings;
|
385 kumpf 1.2 };
386
387
388 CIMObjectPath::CIMObjectPath()
389 {
390 _rep = new CIMObjectPathRep();
391 }
392
393 CIMObjectPath::CIMObjectPath(const CIMObjectPath& x)
394 {
395 _rep = new CIMObjectPathRep(*x._rep);
396 }
397
398 CIMObjectPath::CIMObjectPath(const String& objectName)
399 {
400 // Test the objectName out to see if we get an exception
401 CIMObjectPath tmpRef;
402 tmpRef.set(objectName);
403
404 _rep = new CIMObjectPathRep(*tmpRef._rep);
405 }
406 kumpf 1.2
407 CIMObjectPath::CIMObjectPath(
408 const String& host,
|
409 kumpf 1.7 const CIMNamespaceName& nameSpace,
410 const CIMName& className,
|
411 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
412 kumpf 1.2 {
413 // Test the objectName out to see if we get an exception
414 CIMObjectPath tmpRef;
415 tmpRef.set(host, nameSpace, className, keyBindings);
416
417 _rep = new CIMObjectPathRep(*tmpRef._rep);
418 }
419
420 CIMObjectPath::~CIMObjectPath()
421 {
422 delete _rep;
423 }
424
425 CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x)
426 {
427 *_rep = *x._rep;
428 return *this;
429 }
430
431 void CIMObjectPath::clear()
432 {
433 kumpf 1.2 _rep->_host.clear();
434 _rep->_nameSpace.clear();
435 _rep->_className.clear();
436 _rep->_keyBindings.clear();
437 }
438
439 void CIMObjectPath::set(
440 const String& host,
|
441 kumpf 1.7 const CIMNamespaceName& nameSpace,
442 const CIMName& className,
|
443 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings)
|
444 kumpf 1.2 {
445 setHost(host);
446 setNameSpace(nameSpace);
447 setClassName(className);
448 setKeyBindings(keyBindings);
449 }
450
|
451 kumpf 1.22 Boolean _parseHostElement(
|
452 kumpf 1.2 const String& objectName,
453 char*& p,
|
454 kumpf 1.9 String& host)
|
455 kumpf 1.2 {
456 // See if there is a host name (true if it begins with "//"):
457 // Host is of the from <hostname>-<port> and begins with "//"
458 // and ends with "/":
459
460 if (p[0] != '/' || p[1] != '/')
461 {
462 return false;
463 }
464
465 p += 2;
466
467 //----------------------------------------------------------------------
|
468 chuck 1.23 // Validate the hostname. A domain is allowed after the hostname.
469 // Eg. xyz.company.com
470 // Hostnames must match the following regular expression:
471 // ^([A-Za-z][A-Za-z0-9-]*)(\.[A-Za-z][A-Za-z0-9-]*)*$
|
472 kumpf 1.2 //----------------------------------------------------------------------
473
474 char* q = p;
475
|
476 chuck 1.23 Boolean foundDot = true;
477 while (foundDot == true)
478 {
479 foundDot = false;
|
480 kumpf 1.2
|
481 chuck 1.23 if (!isalpha(*q))
482 throw MalformedObjectNameException(objectName);
|
483 kumpf 1.2
484 q++;
|
485 chuck 1.23
486 while (isalnum(*q) || *q == '-')
487 {
488 q++;
489 }
490
491 if (*q == '.')
492 {
493 q++;
494 foundDot = true;
495 }
496 }
|
497 kumpf 1.2
498 // We now expect a port (or default the port).
499
500 if (*q == ':')
501 {
502 q++;
503 // Check for a port number:
504
505 if (!isdigit(*q))
|
506 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
507 kumpf 1.2
508 while (isdigit(*q))
509 q++;
510
511 // Finally, assign the host name:
512
513 host.assign(p, q - p);
514 }
515 else
516 {
517 host.assign(p, q - p);
518
519 // Assign the default port number:
520
521 host.append(":");
522 host.append(PEGASUS_CIMOM_DEFAULT_PORT_STRING);
523 }
524
525 // Check for slash terminating the entire sequence:
526
527 if (*q != '/')
528 kumpf 1.2 {
529 host.clear();
|
530 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
531 kumpf 1.2 }
532
533 p = ++q;
534
535 return true;
536 }
537
|
538 kumpf 1.22 Boolean _parseNamespaceElement(
|
539 kumpf 1.2 const String& objectName,
540 char*& p,
|
541 kumpf 1.7 CIMNamespaceName& nameSpace)
|
542 kumpf 1.2 {
543 // If we don't find a valid namespace name followed by a ':', we
544 // assume we're not looking at a namespace name.
545
|
546 kumpf 1.7 char* colon = strchr(p, ':');
547 if (!colon)
548 {
549 return false;
550 }
551
|
552 kumpf 1.25 // A ':' as part of a keybinding value should not be interpreted as
553 // a namespace delimiter. Since keybinding pairs follow the first '.'
554 // in the object path string, the ':' delimiter only counts if it
555 // appears before the '.'.
556
557 char* dot = strchr(p, '.');
558 if (dot && (dot < colon))
559 {
560 return false;
561 }
562
|
563 kumpf 1.2 //----------------------------------------------------------------------
564 // Validate the namespace path. Namespaces must match the following
565 // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*"
566 //----------------------------------------------------------------------
567
|
568 kumpf 1.7 String namespaceName = String(p, colon - p);
569 if (!CIMNamespaceName::legal(namespaceName))
|
570 kumpf 1.2 {
|
571 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
572 kumpf 1.2 }
|
573 kumpf 1.7 nameSpace = namespaceName;
|
574 kumpf 1.2
|
575 kumpf 1.7 p = colon+1;
|
576 kumpf 1.2 return true;
577 }
578
579 /**
580 ATTN: RK - Association classes have keys whose types are
581 references. These reference values must be treated specially
582 in the XML encoding, using the VALUE.REFERENCE tag structure.
583
584 Pegasus had been passing reference values simply as String
585 values. For example, EnumerateInstanceNames returned
586 KEYVALUEs of string type rather than VALUE.REFERENCEs.
587
588 I've modified the XmlReader::getKeyBindingElement() and
589 XmlWriter::appendInstanceNameElement() methods to read and write
590 the XML in the proper format. However, making that change
591 required that a CIMObjectPath object be able to distinguish
592 between a key of String type and a key of reference type.
593
594 I've modified the String format of CIMObjectPaths slightly to
595 allow efficient processing of references whose keys are also
596 of reference type. The "official" form uses the same
597 kumpf 1.2 encoding for key values of String type and of reference type,
598 and so it would be necessary to retrieve the class definition
599 and look up the types of the key properties to determine how
600 to treat the key values. This is clearly too inefficient for
601 internal transformations between CIMObjectPaths and String
602 values.
603
604 The workaround is to encode a 'R' at the beginning of the
605 value for a key of reference type (before the opening '"').
606 This allows the parser to know a priori whether the key is of
607 String or reference type.
608
609 In this example:
610
611 MyClass.Key1="StringValue",Key2=R"RefClass.KeyA="StringA",KeyB=10"
612
613 Property Key1 of class MyClass is of String type, and so it
614 gets the usual encoding. Key2 is a reference property, so
615 the extra 'R' is inserted before its encoded value. Note
616 that this algorithm is recursive, such that RefClass could
617 include KeyC of reference type, which would also get encoded
618 kumpf 1.2 with the 'R' notation.
619
620 The toString() method inserts the 'R' to provide symmetry. A
|
621 kumpf 1.16 new CIMKeyBinding type (REFERENCE) has been defined to denote
|
622 kumpf 1.2 keys in a CIMObjectPath that are of reference type. This
|
623 kumpf 1.16 CIMKeyBinding type must be used appropriately for
|
624 kumpf 1.2 CIMObjectPath::toString() to behave correctly.
625
626 A result of this change is that instances names in the
627 instance repository will include this extra 'R' character.
628 Note that for user-facing uses of the String encoding of
629 instance names (such as might appear in MOF for static
630 association instances or in the CGI client), this solution
631 is non-standard and therefore unacceptable. It is likely
632 that these points will need to process the more expensive
633 operation of retrieving the class definition to determine
634 the key property types.
635 */
|
636 kumpf 1.22 void _parseKeyBindingPairs(
|
637 kumpf 1.2 const String& objectName,
638 char*& p,
|
639 kumpf 1.16 Array<CIMKeyBinding>& keyBindings)
|
640 kumpf 1.2 {
641 // Get the key-value pairs:
642
643 while (*p)
644 {
645 // Get key part:
646
|
647 kumpf 1.5 char* equalsign = strchr(p, '=');
648 if (!equalsign)
|
649 kumpf 1.2 {
|
650 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
651 kumpf 1.2 }
652
|
653 kumpf 1.5 *equalsign = 0;
|
654 kumpf 1.2
|
655 kumpf 1.17 if (!CIMName::legal(p))
|
656 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
657 kumpf 1.2
|
658 kumpf 1.17 CIMName keyName (p);
659
|
660 kumpf 1.2 // Get the value part:
661
662 String valueString;
|
663 kumpf 1.5 p = equalsign + 1;
|
664 kumpf 1.16 CIMKeyBinding::Type type;
|
665 kumpf 1.2
666 if (*p == 'R')
667 {
668 p++;
669
|
670 kumpf 1.16 type = CIMKeyBinding::REFERENCE;
|
671 kumpf 1.2
672 if (*p++ != '"')
|
673 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
674 kumpf 1.2
675 while (*p && *p != '"')
676 {
677 // ATTN: need to handle special characters here:
678
679 if (*p == '\\')
680 *p++;
681
682 valueString.append(*p++);
683 }
684
685 if (*p++ != '"')
|
686 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
687 kumpf 1.2 }
688 else if (*p == '"')
689 {
690 p++;
691
|
692 kumpf 1.16 type = CIMKeyBinding::STRING;
|
693 kumpf 1.2
694 while (*p && *p != '"')
695 {
696 // ATTN: need to handle special characters here:
697
698 if (*p == '\\')
699 *p++;
700
701 valueString.append(*p++);
702 }
703
704 if (*p++ != '"')
|
705 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
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 Sint64 x;
750
751 if (!XmlReader::stringToSignedInteger(p, x))
|
752 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
753 kumpf 1.2
754 valueString.assign(p, n);
755
756 if (isComma)
757 {
758 *r = ',';
759 }
760
761 p = p + n;
762 }
763
|
764 kumpf 1.17 keyBindings.append(CIMKeyBinding(keyName.getString (), valueString,
765 type));
|
766 kumpf 1.2
767 if (*p)
768 {
769 if (*p++ != ',')
770 {
|
771 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
772 kumpf 1.2 }
773 }
774 }
775
776 _BubbleSort(keyBindings);
777 }
778
|
779 kumpf 1.9 void CIMObjectPath::set(const String& objectName)
|
780 kumpf 1.2 {
781 clear();
782
783 //--------------------------------------------------------------------------
784 // We will extract components from an object name. Here is an sample
785 // object name:
786 //
787 // //atp:9999/root/cimv25:TennisPlayer.first="Patrick",last="Rafter"
788 //--------------------------------------------------------------------------
789
790 // Convert to a C String first:
791
|
792 kumpf 1.26 CString pCString = objectName.getCString();
793 char* p = const_cast<char*>((const char*) pCString);
|
794 kumpf 1.2 Boolean gotHost;
795 Boolean gotNamespace;
796
797 gotHost = _parseHostElement(objectName, p, _rep->_host);
798 gotNamespace = _parseNamespaceElement(objectName, p, _rep->_nameSpace);
799
800 if (gotHost && !gotNamespace)
801 {
|
802 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
803 kumpf 1.2 }
804
805 // Extract the class name:
806
807 char* dot = strchr(p, '.');
808
809 if (!dot)
810 {
811 if (!CIMName::legal(p))
812 {
|
813 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
814 kumpf 1.2 }
815
816 // ATTN: remove this later: a reference should only be able to hold
817 // an instance name.
818
|
819 kumpf 1.17 _rep->_className = CIMName (p);
|
820 kumpf 1.2 return;
821 }
822
|
823 kumpf 1.7 String className = String(p, dot - p);
824 if (!CIMName::legal(className))
825 {
|
826 kumpf 1.10 throw MalformedObjectNameException(objectName);
|
827 kumpf 1.7 }
828 _rep->_className = className;
|
829 kumpf 1.2
830 // Advance past dot:
831
832 p = dot + 1;
833
834 _parseKeyBindingPairs(objectName, p, _rep->_keyBindings);
835 }
836
837 CIMObjectPath& CIMObjectPath::operator=(const String& objectName)
838 {
839 set(objectName);
840 return *this;
841 }
842
843 const String& CIMObjectPath::getHost() const
844 {
845 return _rep->_host;
846 }
847
848 void CIMObjectPath::setHost(const String& host)
849 {
850 kumpf 1.2 _rep->_host = host;
851 }
852
|
853 kumpf 1.7 const CIMNamespaceName& CIMObjectPath::getNameSpace() const
|
854 kumpf 1.2 {
855 return _rep->_nameSpace;
856 }
857
|
858 kumpf 1.7 void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace)
|
859 kumpf 1.2 {
860 _rep->_nameSpace = nameSpace;
861 }
862
|
863 kumpf 1.7 const CIMName& CIMObjectPath::getClassName() const
|
864 kumpf 1.2 {
865 return _rep->_className;
866 }
867
|
868 kumpf 1.7 void CIMObjectPath::setClassName(const CIMName& className)
|
869 kumpf 1.2 {
870 _rep->_className = className;
871 }
872
|
873 kumpf 1.16 const Array<CIMKeyBinding>& CIMObjectPath::getKeyBindings() const
|
874 kumpf 1.2 {
875 return _rep->_keyBindings;
876 }
877
|
878 kumpf 1.16 void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings)
|
879 kumpf 1.2 {
880 _rep->_keyBindings = keyBindings;
881 _BubbleSort(_rep->_keyBindings);
882 }
883
|
884 kumpf 1.15 String CIMObjectPath::toString() const
|
885 kumpf 1.2 {
886 String objectName;
887
888 // Get the host:
889
|
890 kumpf 1.15 if (_rep->_host.size())
|
891 kumpf 1.2 {
892 objectName = "//";
|
893 kumpf 1.13 objectName.append(_rep->_host);
894 objectName.append("/");
|
895 kumpf 1.2 }
896
897 // Get the namespace (if we have a host name, we must write namespace):
898
|
899 kumpf 1.7 if (!_rep->_nameSpace.isNull() || _rep->_host.size())
|
900 kumpf 1.2 {
|
901 kumpf 1.17 objectName.append(_rep->_nameSpace.getString ());
|
902 kumpf 1.13 objectName.append(":");
|
903 kumpf 1.2 }
904
905 // Get the class name:
906
|
907 kumpf 1.17 objectName.append(getClassName().getString ());
|
908 kumpf 1.2
|
909 kumpf 1.9 //
910 // ATTN-CAKG-P2-20020726: The following condition does not correctly
911 // distinguish instanceNames from classNames in every case
912 // The instanceName of a singleton instance of a keyless class has no
913 // key bindings
914 //
915 if (_rep->_keyBindings.size () != 0)
|
916 kumpf 1.2 {
917 objectName.append('.');
918
919 // Append each key-value pair:
920
|
921 kumpf 1.16 const Array<CIMKeyBinding>& keyBindings = getKeyBindings();
|
922 kumpf 1.2
923 for (Uint32 i = 0, n = keyBindings.size(); i < n; i++)
924 {
|
925 kumpf 1.17 objectName.append(keyBindings[i].getName().getString ());
|
926 kumpf 1.2 objectName.append('=');
927
928 const String& value = _escapeSpecialCharacters(
929 keyBindings[i].getValue());
930
|
931 kumpf 1.16 CIMKeyBinding::Type type = keyBindings[i].getType();
|
932 kumpf 1.2
|
933 kumpf 1.16 if (type == CIMKeyBinding::REFERENCE)
|
934 kumpf 1.2 objectName.append('R');
935
|
936 kumpf 1.16 if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
|
937 kumpf 1.2 objectName.append('"');
938
939 objectName.append(value);
940
|
941 kumpf 1.16 if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
|
942 kumpf 1.2 objectName.append('"');
943
944 if (i + 1 != n)
945 objectName.append(',');
946 }
947 }
948
949 return objectName;
950 }
951
|
952 kumpf 1.15 String CIMObjectPath::_toStringCanonical() const
|
953 kumpf 1.2 {
954 CIMObjectPath ref = *this;
955
956 // ATTN-RK-P2-20020510: Need to make hostname and namespace lower case?
957
|
958 kumpf 1.17 String classNameLower = ref._rep->_className.getString ();
|
959 kumpf 1.7 classNameLower.toLower();
960 ref._rep->_className = classNameLower;
|
961 kumpf 1.2
962 for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
963 {
|
964 kumpf 1.17 String keyBindingNameLower =
965 ref._rep->_keyBindings[i]._rep->_name.getString ();
|
966 kumpf 1.7 keyBindingNameLower.toLower();
967 ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
|
968 kumpf 1.2 }
969
|
970 kumpf 1.12 // ATTN-RK-20020826: Need to sort keys?
971
|
972 kumpf 1.15 return ref.toString();
|
973 kumpf 1.2 }
974
975 Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
976 {
977 return
978 String::equal(_rep->_host, x._rep->_host) &&
|
979 kumpf 1.7 _rep->_nameSpace.equal(x._rep->_nameSpace) &&
980 _rep->_className.equal(x._rep->_className) &&
|
981 kumpf 1.2 _rep->_keyBindings == x._rep->_keyBindings;
982 }
983
984 Uint32 CIMObjectPath::makeHashCode() const
985 {
|
986 kumpf 1.12 return HashFunc<String>::hash(_toStringCanonical());
|
987 kumpf 1.2 }
988
989 Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y)
990 {
991 return x.identical(y);
992 }
993
994 Boolean operator!=(const CIMObjectPath& x, const CIMObjectPath& y)
995 {
996 return !operator==(x, y);
997 }
998
|
999 kumpf 1.22 #ifndef PEGASUS_REMOVE_DEPRECATED
|
1000 kumpf 1.2 PEGASUS_STD(ostream)& operator<<(
1001 PEGASUS_STD(ostream)& os,
1002 const CIMObjectPath& x)
1003 {
1004 return os << x.toString();
1005 }
|
1006 kumpf 1.22 #endif
|
1007 chip 1.1
1008 PEGASUS_NAMESPACE_END
|