(file) Return to CIMObjectPath.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2