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

   1 karl  1.54 //%2006////////////////////////////////////////////////////////////////////////
   2 chip  1.1  //
   3 karl  1.43 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
   4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   6 karl  1.30 // IBM Corp.; EMC Corporation, The Open Group.
   7 karl  1.43 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   9 karl  1.45 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
  11 karl  1.54 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
  12            // EMC Corporation; Symantec Corporation; The Open Group.
  13 chip  1.1  //
  14            // Permission is hereby granted, free of charge, to any person obtaining a copy
  15            // of this software and associated documentation files (the "Software"), to
  16            // deal in the Software without restriction, including without limitation the
  17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  18            // sell copies of the Software, and to permit persons to whom the Software is
  19            // furnished to do so, subject to the following conditions:
  20 r.kieninger 1.56 //
  21 chip        1.1  // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
  22                  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
  23                  // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  24                  // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  25                  // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  26                  // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  27                  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28                  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29                  //
  30                  //==============================================================================
  31                  //
  32                  //%/////////////////////////////////////////////////////////////////////////////
  33                  
  34 kumpf       1.2  #include <Pegasus/Common/Config.h>
  35                  #include <cstring>
  36 kumpf       1.22 #include <iostream>
  37 kumpf       1.2  #include "HashTable.h"
  38                  #include "CIMObjectPath.h"
  39                  #include "Indentor.h"
  40                  #include "CIMName.h"
  41                  #include "XmlWriter.h"
  42                  #include "XmlReader.h"
  43 kumpf       1.11 #include "ArrayInternal.h"
  44 chip        1.1  
  45                  PEGASUS_NAMESPACE_BEGIN
  46 kumpf       1.2  
  47 kumpf       1.16 #define PEGASUS_ARRAY_T CIMKeyBinding
  48 kumpf       1.2  # include "ArrayImpl.h"
  49                  #undef PEGASUS_ARRAY_T
  50                  
  51                  #define PEGASUS_ARRAY_T CIMObjectPath
  52                  # include "ArrayImpl.h"
  53                  #undef PEGASUS_ARRAY_T
  54                  
  55                  // ATTN: KS May 2002 P0 Add resolve method to CIMObjectPath.
  56                  // Add a resolve method to this class to verify that the
  57                  // reference is correct (that the class name corresponds to a real
  58                  // class and that the property names are really keys and that all keys
  59                  // of the class or used. Also be sure that there is a valid conversion
  60                  // between the string value and the value of that property).
  61                  //
  62                  // ATTN: also check to see that the reference refers to a class that is the
  63                  // same or derived from the _className member.
  64                  
  65                  ////////////////////////////////////////////////////////////////////////////////
  66                  //
  67                  // Local routines:
  68                  //
  69 kumpf       1.2  ////////////////////////////////////////////////////////////////////////////////
  70                  
  71                  static String _escapeSpecialCharacters(const String& str)
  72                  {
  73                      String result;
  74                  
  75                      for (Uint32 i = 0, n = str.size(); i < n; i++)
  76                      {
  77                          switch (str[i])
  78                          {
  79 kumpf       1.28             case '\\':
  80                                  result.append("\\\\");
  81 kumpf       1.2                  break;
  82                  
  83                              case '"':
  84 kumpf       1.13                 result.append("\\\"");
  85 kumpf       1.2                  break;
  86                  
  87                              default:
  88 kumpf       1.13                 result.append(str[i]);
  89 kumpf       1.2          }
  90                      }
  91                  
  92                      return result;
  93                  }
  94                  
  95 kumpf       1.16 static void _BubbleSort(Array<CIMKeyBinding>& x)
  96 kumpf       1.2  {
  97                      Uint32 n = x.size();
  98                  
  99 kumpf       1.24     //
 100 chip        1.47     //  If the key is a reference, the keys in the reference must also be
 101 kumpf       1.24     //  sorted
 102                      //
 103                      for (Uint32 k = 0; k < n ; k++)
 104                          if (x[k].getType () == CIMKeyBinding::REFERENCE)
 105                          {
 106                              CIMObjectPath tmp (x[k].getValue ());
 107                              Array <CIMKeyBinding> keyBindings = tmp.getKeyBindings ();
 108                              _BubbleSort (keyBindings);
 109                              tmp.setKeyBindings (keyBindings);
 110                              x[k].setValue (tmp.toString ());
 111                          }
 112                  
 113 kumpf       1.2      if (n < 2)
 114                          return;
 115                  
 116                      for (Uint32 i = 0; i < n - 1; i++)
 117                      {
 118                          for (Uint32 j = 0; j < n - 1; j++)
 119                          {
 120 chip        1.47             if (String::compareNoCase(x[j].getName().getString(),
 121 kumpf       1.17                                       x[j+1].getName().getString()) > 0)
 122 kumpf       1.2              {
 123 kumpf       1.16                 CIMKeyBinding t = x[j];
 124 kumpf       1.2                  x[j] = x[j+1];
 125                                  x[j+1] = t;
 126                              }
 127                          }
 128                      }
 129                  }
 130                  
 131                  ////////////////////////////////////////////////////////////////////////////////
 132                  //
 133 kumpf       1.16 // CIMKeyBinding
 134 kumpf       1.2  //
 135                  ////////////////////////////////////////////////////////////////////////////////
 136                  
 137 kumpf       1.16 class CIMKeyBindingRep
 138 kumpf       1.2  {
 139                  public:
 140 kumpf       1.16     CIMKeyBindingRep()
 141 kumpf       1.2      {
 142                      }
 143                  
 144 kumpf       1.16     CIMKeyBindingRep(const CIMKeyBindingRep& x)
 145 kumpf       1.2          : _name(x._name), _value(x._value), _type(x._type)
 146                      {
 147                      }
 148                  
 149 kumpf       1.16     CIMKeyBindingRep(
 150 kumpf       1.7          const CIMName& name,
 151 kumpf       1.2          const String& value,
 152 kumpf       1.16         CIMKeyBinding::Type type)
 153 kumpf       1.2          : _name(name), _value(value), _type(type)
 154                      {
 155                      }
 156                  
 157 kumpf       1.16     ~CIMKeyBindingRep()
 158 kumpf       1.2      {
 159                      }
 160                  
 161 kumpf       1.16     CIMKeyBindingRep& operator=(const CIMKeyBindingRep& x)
 162 kumpf       1.2      {
 163                          if (&x != this)
 164                          {
 165                              _name = x._name;
 166                              _value = x._value;
 167                              _type = x._type;
 168                          }
 169                          return *this;
 170                      }
 171                  
 172 kumpf       1.7      CIMName _name;
 173 kumpf       1.2      String _value;
 174 kumpf       1.16     CIMKeyBinding::Type _type;
 175 kumpf       1.2  };
 176                  
 177                  
 178 a.arora     1.39 CIMKeyBinding::CIMKeyBinding()
 179 kumpf       1.2  {
 180 a.arora     1.39     _rep = new CIMKeyBindingRep();
 181 kumpf       1.2  }
 182                  
 183 a.arora     1.39 CIMKeyBinding::CIMKeyBinding(const CIMKeyBinding& x)
 184 kumpf       1.2  {
 185 a.arora     1.39     _rep = new CIMKeyBindingRep(*x._rep);
 186 kumpf       1.2  }
 187                  
 188 kumpf       1.57 CIMKeyBinding::CIMKeyBinding(
 189                      const CIMName& name,
 190                      const String& value,
 191                      Type type)
 192 kumpf       1.2  {
 193 a.arora     1.39     _rep = new CIMKeyBindingRep(name, value, type);
 194 kumpf       1.2  }
 195                  
 196 kumpf       1.18 CIMKeyBinding::CIMKeyBinding(const CIMName& name, const CIMValue& value)
 197                  {
 198 kumpf       1.21     if (value.isArray())
 199 kumpf       1.20     {
 200                          throw TypeMismatchException();
 201                      }
 202                  
 203 kumpf       1.18     String kbValue = value.toString();
 204                      Type kbType;
 205                  
 206                      switch (value.getType())
 207                      {
 208                      case CIMTYPE_BOOLEAN:
 209                          kbType = BOOLEAN;
 210                          break;
 211                      case CIMTYPE_CHAR16:
 212                      case CIMTYPE_STRING:
 213                      case CIMTYPE_DATETIME:
 214                          kbType = STRING;
 215                          break;
 216                      case CIMTYPE_REFERENCE:
 217                          kbType = REFERENCE;
 218                          break;
 219 dave.sudlik 1.46 //  case CIMTYPE_REAL32:
 220                  //  case CIMTYPE_REAL64:
 221 dave.sudlik 1.44     case CIMTYPE_OBJECT:
 222 a.dunfey    1.55 #ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
 223                      case CIMTYPE_INSTANCE:
 224                  #endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT
 225 dave.sudlik 1.46         // From PEP 194: EmbeddedObjects cannot be keys.
 226 dave.sudlik 1.44         throw TypeMismatchException();
 227                          break;
 228 kumpf       1.18     default:
 229                          kbType = NUMERIC;
 230                          break;
 231                      }
 232                  
 233 a.arora     1.39     _rep = new CIMKeyBindingRep(name, kbValue, kbType);
 234 kumpf       1.18 }
 235                  
 236 kumpf       1.16 CIMKeyBinding::~CIMKeyBinding()
 237 kumpf       1.2  {
 238 a.arora     1.39     delete _rep;
 239 kumpf       1.2  }
 240                  
 241 kumpf       1.16 CIMKeyBinding& CIMKeyBinding::operator=(const CIMKeyBinding& x)
 242 kumpf       1.2  {
 243 a.arora     1.39     *_rep = *x._rep;
 244 kumpf       1.2      return *this;
 245                  }
 246                  
 247 kumpf       1.16 const CIMName& CIMKeyBinding::getName() const
 248 kumpf       1.2  {
 249                      return _rep->_name;
 250                  }
 251                  
 252 kumpf       1.16 void CIMKeyBinding::setName(const CIMName& name)
 253 kumpf       1.2  {
 254                      _rep->_name = name;
 255                  }
 256                  
 257 kumpf       1.16 const String& CIMKeyBinding::getValue() const
 258 kumpf       1.2  {
 259                      return _rep->_value;
 260                  }
 261                  
 262 kumpf       1.16 void CIMKeyBinding::setValue(const String& value)
 263 kumpf       1.2  {
 264                      _rep->_value = value;
 265                  }
 266                  
 267 kumpf       1.16 CIMKeyBinding::Type CIMKeyBinding::getType() const
 268 kumpf       1.2  {
 269                      return _rep->_type;
 270                  }
 271                  
 272 kumpf       1.16 void CIMKeyBinding::setType(CIMKeyBinding::Type type)
 273 kumpf       1.2  {
 274                      _rep->_type = type;
 275                  }
 276 kumpf       1.18 
 277                  Boolean CIMKeyBinding::equal(CIMValue value)
 278                  {
 279 kumpf       1.21     if (value.isArray())
 280 kumpf       1.20     {
 281                          return false;
 282                      }
 283                  
 284 kumpf       1.18     CIMValue kbValue;
 285                  
 286                      try
 287                      {
 288                          switch (value.getType())
 289                          {
 290                          case CIMTYPE_CHAR16:
 291 kumpf       1.20             if (getType() != STRING) return false;
 292 kumpf       1.18             kbValue.set(getValue()[0]);
 293                              break;
 294                          case CIMTYPE_DATETIME:
 295 kumpf       1.20             if (getType() != STRING) return false;
 296 kumpf       1.18             kbValue.set(CIMDateTime(getValue()));
 297                              break;
 298                          case CIMTYPE_STRING:
 299 kumpf       1.20             if (getType() != STRING) return false;
 300 kumpf       1.18             kbValue.set(getValue());
 301                              break;
 302                          case CIMTYPE_REFERENCE:
 303 kumpf       1.20             if (getType() != REFERENCE) return false;
 304 kumpf       1.18             kbValue.set(CIMObjectPath(getValue()));
 305                              break;
 306 kumpf       1.20         case CIMTYPE_BOOLEAN:
 307                              if (getType() != BOOLEAN) return false;
 308                              kbValue = XmlReader::stringToValue(0, getValue().getCString(),
 309                                                                 value.getType());
 310                              break;
 311 dave.sudlik 1.46 //      case CIMTYPE_REAL32:
 312                  //      case CIMTYPE_REAL64:
 313 dave.sudlik 1.44         case CIMTYPE_OBJECT:
 314 a.dunfey    1.55 #ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT
 315                          case CIMTYPE_INSTANCE:
 316                  #endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT
 317 dave.sudlik 1.46             // From PEP 194: EmbeddedObjects cannot be keys.
 318 dave.sudlik 1.44             return false;
 319                              break;
 320 kumpf       1.20         default:  // Numerics
 321                              if (getType() != NUMERIC) return false;
 322 kumpf       1.18             kbValue = XmlReader::stringToValue(0, getValue().getCString(),
 323                                                                 value.getType());
 324                              break;
 325                          }
 326                      }
 327 kumpf       1.19     catch (Exception&)
 328 kumpf       1.18     {
 329                          return false;
 330                      }
 331                  
 332                      return value.equal(kbValue);
 333                  }
 334 kumpf       1.2  
 335 kumpf       1.16 Boolean operator==(const CIMKeyBinding& x, const CIMKeyBinding& y)
 336 kumpf       1.2  {
 337 kumpf       1.33     // Check that the names and types match
 338                      if (!(x.getName().equal(y.getName())) ||
 339                          !(x.getType() == y.getType()))
 340                      {
 341                          return false;
 342                      }
 343                  
 344                      switch (x.getType())
 345                      {
 346                      case CIMKeyBinding::REFERENCE:
 347                          try
 348                          {
 349                              // References should be compared as CIMObjectPaths
 350                              return (CIMObjectPath(x.getValue()) == CIMObjectPath(y.getValue()));
 351                          }
 352                          catch (Exception&)
 353                          {
 354                              // If CIMObjectPath parsing fails, just compare strings
 355 kumpf       1.58             return String::equal(x.getValue(), y.getValue());
 356 kumpf       1.33         }
 357                          break;
 358                      case CIMKeyBinding::BOOLEAN:
 359                          // Case-insensitive comparison is sufficient for booleans
 360 kumpf       1.58         return String::equalNoCase(x.getValue(), y.getValue());
 361 kumpf       1.33         break;
 362                      case CIMKeyBinding::NUMERIC:
 363                          // Note: This comparison assumes XML syntax for integers
 364                          // First try comparing as unsigned integers
 365                          {
 366                              Uint64 xValue;
 367                              Uint64 yValue;
 368                              if (XmlReader::stringToUnsignedInteger(
 369                                      x.getValue().getCString(), xValue) &&
 370                                  XmlReader::stringToUnsignedInteger(
 371                                      y.getValue().getCString(), yValue))
 372                              {
 373                                  return (xValue == yValue);
 374                              }
 375                          }
 376                          // Next try comparing as signed integers
 377                          {
 378                              Sint64 xValue;
 379                              Sint64 yValue;
 380                              if (XmlReader::stringToSignedInteger(
 381                                      x.getValue().getCString(), xValue) &&
 382 kumpf       1.33                 XmlReader::stringToSignedInteger(
 383                                      y.getValue().getCString(), yValue))
 384                              {
 385                                  return (xValue == yValue);
 386                              }
 387                          }
 388                          // Note: Keys may not be real values, so don't try comparing as reals
 389                          // We couldn't parse the numbers, so just compare the strings
 390 kumpf       1.58         return String::equal(x.getValue(), y.getValue());
 391 kumpf       1.33         break;
 392                      default:  // CIMKeyBinding::STRING
 393 kumpf       1.58         return String::equal(x.getValue(), y.getValue());
 394 kumpf       1.33         break;
 395                      }
 396                  
 397                      PEGASUS_UNREACHABLE(return false;)
 398 kumpf       1.2  }
 399                  
 400                  
 401                  ////////////////////////////////////////////////////////////////////////////////
 402                  //
 403                  // CIMObjectPath
 404                  //
 405                  ////////////////////////////////////////////////////////////////////////////////
 406                  
 407                  class CIMObjectPathRep
 408                  {
 409                  public:
 410                      CIMObjectPathRep()
 411                      {
 412                      }
 413                  
 414                      CIMObjectPathRep(const CIMObjectPathRep& x)
 415                          : _host(x._host), _nameSpace(x._nameSpace),
 416                          _className(x._className), _keyBindings(x._keyBindings)
 417                      {
 418                      }
 419 kumpf       1.2  
 420                      CIMObjectPathRep(
 421                          const String& host,
 422 kumpf       1.7          const CIMNamespaceName& nameSpace,
 423                          const CIMName& className,
 424 kumpf       1.16         const Array<CIMKeyBinding>& keyBindings)
 425 kumpf       1.2          : _host(host), _nameSpace(nameSpace),
 426                          _className(className), _keyBindings(keyBindings)
 427                      {
 428                      }
 429                  
 430                      ~CIMObjectPathRep()
 431                      {
 432                      }
 433                  
 434                      CIMObjectPathRep& operator=(const CIMObjectPathRep& x)
 435                      {
 436                          if (&x != this)
 437                          {
 438                              _host = x._host;
 439                              _nameSpace = x._nameSpace;
 440                              _className = x._className;
 441                              _keyBindings = x._keyBindings;
 442                          }
 443                          return *this;
 444                      }
 445                  
 446 kumpf       1.34     static Boolean isValidHostname(const String& hostname)
 447                      {
 448                          //------------------------------------------------------------------
 449                          // Validate the hostname.  The hostname value may or may not be a
 450                          // fully-qualified domain name (e.g., xyz.company.com) or may be an
 451                          // IP address.  A port number may follow the hostname.
 452                          // Hostnames must match one of the following regular expressions:
 453 dave.sudlik 1.42         // ^([A-Za-z0-9][A-Za-z0-9-]*)(\.[A-Za-z][A-Za-z0-9-]*)*(:[0-9]*)?$
 454 kumpf       1.34         // ^([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)(:[0-9]*)?$
 455 dave.sudlik 1.42         // Note for Bug#1462. Be careful here, from RFC 1123:
 456 chip        1.47         // - The syntax of a legal Internet host name was specified in
 457                          //   RFC-952 [DNS:4]. One aspect of host name syntax is hereby
 458                          //   changed: the restriction on the first character is relaxed to
 459                          //   allow either a letter or a digit.
 460 dave.sudlik 1.42         // - If a dotted-decimal number can be entered without identifying
 461                          //   delimiters, then a full syntactic check must be made, because
 462                          //   a segment of a host domain name is now allowed to begin with a
 463                          //   digit and could legally be entirely numeric (see Section 6.1.2.4).
 464                          //   However, a valid host name can never have the dotted-decimal form
 465                          //   #.#.#.#, since at least the highest-level component label will be
 466 chip        1.47         //   alphabetic.
 467 dave.sudlik 1.42         // The algorithm below has been updated accordingly.
 468 kumpf       1.34         //------------------------------------------------------------------
 469                  
 470                          Uint32 i = 0;
 471                  
 472 dave.sudlik 1.42         Boolean isValid = false;
 473                  
 474 kumpf       1.52         if (isascii(hostname[0]) && isdigit(hostname[0]))
 475 kumpf       1.34         {
 476 dave.sudlik 1.42             //--------------------------------------------------------------
 477 chip        1.47             // Attempt to validate an IP address, but keep in mind that it
 478 dave.sudlik 1.42             // might be a host name, since the leading character can now be
 479                              // a digit.
 480                              //--------------------------------------------------------------
 481                              isValid = true;
 482 kumpf       1.34 
 483                              for (Uint32 octet=1; octet<=4; octet++)
 484                              {
 485                                  Uint32 octetValue = 0;
 486                  
 487 dave.sudlik 1.42                 //----------------------------------------------------------
 488                                  // If a non-digit is encountered in the input parameter,
 489                                  // then break from here and attempt to validate as host name.
 490                                  //----------------------------------------------------------
 491 kumpf       1.52                 if (!(isascii(hostname[i]) && isdigit(hostname[i])))
 492 kumpf       1.34                 {
 493 dave.sudlik 1.42                     isValid = false;
 494                                      break;
 495 kumpf       1.34                 }
 496                  
 497 kumpf       1.52                 // skip over digits
 498                                  while (isascii(hostname[i]) && isdigit(hostname[i]))
 499 kumpf       1.34                 {
 500                                      octetValue = octetValue*10 + (hostname[i] - '0');
 501                                      i++;
 502                                  }
 503                  
 504                                  if (octetValue > 255)
 505                                  {
 506 dave.sudlik 1.42                     isValid = false;
 507                                      break;
 508 kumpf       1.34                 }
 509                  
 510 dave.sudlik 1.42                 // Check for invalid character in IP address
 511 kumpf       1.34                 if ((octet != 4) && (hostname[i++] != '.'))
 512                                  {
 513 dave.sudlik 1.42                     isValid = false;
 514                                      break;
 515                                  }
 516                  
 517                                  // Check for the case where it's a valid host name that happens
 518                                  // to have 4 (or more) leading all-numeric host segments.
 519 kumpf       1.57                 if ((octet == 4) && (hostname[i] != ':') &&
 520                                      hostname[i] != char(0))
 521 dave.sudlik 1.42                 {
 522                                      isValid = false;
 523                                      break;
 524 kumpf       1.34                 }
 525                              }
 526                          }
 527 dave.sudlik 1.42         if (!isValid)   // if it is not a valid IP address
 528 kumpf       1.34         {
 529 dave.sudlik 1.42             i = 0;  // reset index for host name check
 530                  
 531                              // Validate a host name
 532                              isValid = true;
 533 kumpf       1.34 
 534                              Boolean expectHostSegment = true;
 535 dave.sudlik 1.42             Boolean hostSegmentIsNumeric;
 536 kumpf       1.34 
 537                              while (expectHostSegment == true)
 538                              {
 539                                  expectHostSegment = false;
 540 dave.sudlik 1.42                 hostSegmentIsNumeric = true; // assume all-numeric host segment
 541 kumpf       1.34 
 542 kumpf       1.53                 if (!(isascii(hostname[i]) &&
 543                                        (isalnum(hostname[i]) || (hostname[i] == '_'))))
 544 kumpf       1.34                 {
 545                                      return false;
 546                                  }
 547                  
 548 kumpf       1.52                 while (isascii(hostname[i]) &&
 549                                         (isalnum(hostname[i]) || (hostname[i] == '-') ||
 550                                          (hostname[i] == '_')))
 551 kumpf       1.34                 {
 552 dave.sudlik 1.42                     // If a non-digit is encountered, set "all-numeric"
 553                                      // flag to false
 554 vijay.eli   1.51                     if (isalpha(hostname[i]) || (hostname[i] == '-') ||
 555 kumpf       1.58                                                 (hostname[i] == '_'))
 556                                      {
 557 dave.sudlik 1.42                         hostSegmentIsNumeric = false;
 558                                      }
 559 kumpf       1.34                     i++;
 560                                  }
 561                  
 562                                  if (hostname[i] == '.')
 563                                  {
 564                                      i++;
 565                                      expectHostSegment = true;
 566                                  }
 567                              }
 568 dave.sudlik 1.42             // If the last Host Segment is all numeric, then return false.
 569                              // RFC 1123 says "highest-level component label will be alphabetic".
 570 kumpf       1.58             if (hostSegmentIsNumeric)
 571                              {
 572 dave.sudlik 1.42                 return false;
 573                              }
 574                          }
 575                  
 576                          if (!isValid) // if not a valid IP address or host name
 577                          {
 578                              return false;
 579 kumpf       1.34         }
 580                  
 581                          // Check for a port number:
 582                  
 583                          if (hostname[i] == ':')
 584                          {
 585 kumpf       1.52             i++;
 586                              if (!(isascii(hostname[i]) && isdigit(hostname[i])))
 587 kumpf       1.34             {
 588                                  return false;
 589                              }
 590 kumpf       1.52             i++;
 591 chip        1.47 
 592 kumpf       1.52             while (isascii(hostname[i]) && isdigit(hostname[i]))
 593                              {
 594                                  i++;
 595                              }
 596 kumpf       1.34         }
 597                  
 598                          return (hostname[i] == char(0));
 599                      }
 600                  
 601 kumpf       1.2      //
 602                      // Contains port as well (e.g., myhost:1234).
 603                      //
 604                      String _host;
 605                  
 606 kumpf       1.7      CIMNamespaceName _nameSpace;
 607                      CIMName _className;
 608 kumpf       1.16     Array<CIMKeyBinding> _keyBindings;
 609 kumpf       1.2  };
 610                  
 611                  
 612 a.arora     1.39 CIMObjectPath::CIMObjectPath()
 613 kumpf       1.2  {
 614 a.arora     1.39     _rep = new CIMObjectPathRep();
 615 kumpf       1.2  }
 616                  
 617 a.arora     1.39 CIMObjectPath::CIMObjectPath(const CIMObjectPath& x)
 618 kumpf       1.2  {
 619 a.arora     1.39     _rep = new CIMObjectPathRep(*x._rep);
 620 kumpf       1.2  }
 621                  
 622                  CIMObjectPath::CIMObjectPath(const String& objectName)
 623                  {
 624                      // Test the objectName out to see if we get an exception
 625                      CIMObjectPath tmpRef;
 626                      tmpRef.set(objectName);
 627                  
 628 a.arora     1.39     _rep = new CIMObjectPathRep(*tmpRef._rep);
 629 kumpf       1.2  }
 630                  
 631                  CIMObjectPath::CIMObjectPath(
 632                      const String& host,
 633 kumpf       1.7      const CIMNamespaceName& nameSpace,
 634                      const CIMName& className,
 635 kumpf       1.16     const Array<CIMKeyBinding>& keyBindings)
 636 kumpf       1.2  {
 637                      // Test the objectName out to see if we get an exception
 638                      CIMObjectPath tmpRef;
 639                      tmpRef.set(host, nameSpace, className, keyBindings);
 640                  
 641 a.arora     1.39     _rep = new CIMObjectPathRep(*tmpRef._rep);
 642 kumpf       1.2  }
 643                  
 644                  CIMObjectPath::~CIMObjectPath()
 645                  {
 646 a.arora     1.39     delete _rep;
 647 kumpf       1.2  }
 648                  
 649                  CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x)
 650                  {
 651 a.arora     1.39     *_rep = *x._rep;
 652 kumpf       1.2      return *this;
 653                  }
 654                  
 655                  void CIMObjectPath::clear()
 656                  {
 657                      _rep->_host.clear();
 658                      _rep->_nameSpace.clear();
 659                      _rep->_className.clear();
 660                      _rep->_keyBindings.clear();
 661                  }
 662                  
 663                  void CIMObjectPath::set(
 664                      const String& host,
 665 kumpf       1.7      const CIMNamespaceName& nameSpace,
 666                      const CIMName& className,
 667 kumpf       1.16     const Array<CIMKeyBinding>& keyBindings)
 668 kumpf       1.2  {
 669                     setHost(host);
 670                     setNameSpace(nameSpace);
 671                     setClassName(className);
 672                     setKeyBindings(keyBindings);
 673                  }
 674                  
 675 kumpf       1.22 Boolean _parseHostElement(
 676 kumpf       1.2      const String& objectName,
 677                      char*& p,
 678 kumpf       1.9      String& host)
 679 kumpf       1.2  {
 680                      // See if there is a host name (true if it begins with "//"):
 681 kumpf       1.32     // Host is of the form <hostname>:<port> and begins with "//"
 682 kumpf       1.2      // and ends with "/":
 683                  
 684                      if (p[0] != '/' || p[1] != '/')
 685                      {
 686                          return false;
 687                      }
 688                  
 689                      p += 2;
 690                  
 691 kumpf       1.34     char* slash = strchr(p, '/');
 692                      if (!slash)
 693 chuck       1.23     {
 694 kumpf       1.34         throw MalformedObjectNameException(objectName);
 695 kumpf       1.2      }
 696                  
 697 kumpf       1.34     String hostname = String(p, (Uint32)(slash - p));
 698                      if (!CIMObjectPathRep::isValidHostname(hostname))
 699 kumpf       1.2      {
 700 kumpf       1.10         throw MalformedObjectNameException(objectName);
 701 kumpf       1.2      }
 702 kumpf       1.34     host = hostname;
 703 kumpf       1.2  
 704 kumpf       1.31     // Do not step past the '/'; it will be consumed by the namespace parser
 705 kumpf       1.34     p = slash;
 706 kumpf       1.2  
 707                      return true;
 708                  }
 709                  
 710 kumpf       1.22 Boolean _parseNamespaceElement(
 711 kumpf       1.2      const String& objectName,
 712                      char*& p,
 713 kumpf       1.7      CIMNamespaceName& nameSpace)
 714 kumpf       1.2  {
 715                      // If we don't find a valid namespace name followed by a ':', we
 716                      // assume we're not looking at a namespace name.
 717                  
 718 kumpf       1.7      char* colon = strchr(p, ':');
 719                      if (!colon)
 720                      {
 721                          return false;
 722                      }
 723                  
 724 chip        1.47     // A ':' as part of a keybinding value should not be interpreted as
 725 kumpf       1.25     // a namespace delimiter.  Since keybinding pairs follow the first '.'
 726                      // in the object path string, the ':' delimiter only counts if it
 727                      // appears before the '.'.
 728                  
 729                      char* dot = strchr(p, '.');
 730                      if (dot && (dot < colon))
 731                      {
 732                          return false;
 733                      }
 734                  
 735 kumpf       1.2      //----------------------------------------------------------------------
 736                      // Validate the namespace path.  Namespaces must match the following
 737                      // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*"
 738                      //----------------------------------------------------------------------
 739                  
 740 david       1.27     String namespaceName = String(p, (Uint32)(colon - p));
 741 kumpf       1.7      if (!CIMNamespaceName::legal(namespaceName))
 742 kumpf       1.2      {
 743 kumpf       1.10         throw MalformedObjectNameException(objectName);
 744 kumpf       1.2      }
 745 kumpf       1.7      nameSpace = namespaceName;
 746 kumpf       1.2  
 747 kumpf       1.7      p = colon+1;
 748 kumpf       1.2      return true;
 749                  }
 750                  
 751                  /**
 752 kumpf       1.29     ATTN-RK: The DMTF specification for the string form of an
 753                      object path makes it impossible for a parser to distinguish
 754                      between a key values of String type and Reference type.
 755                  
 756                      Given the ambiguity, this implementation takes a guess at the
 757                      type of a quoted key value.  If the value can be parsed into
 758                      a CIMObjectPath with at least one key binding, the type is
 759                      set to REFERENCE.  Otherwise, the type is set to STRING.
 760                      Note: This algorithm appears to be in line with what the Sun
 761                      WBEM Services implementation does.
 762                  
 763                      To be totally correct, it would be necessary to retrieve the
 764                      class definition and look up the types of the key properties
 765                      to determine how to interpret the key values.  This is clearly
 766                      too inefficient for internal transformations between
 767                      CIMObjectPaths and String values.
 768 kumpf       1.2  */
 769 kumpf       1.22 void _parseKeyBindingPairs(
 770 kumpf       1.2      const String& objectName,
 771                      char*& p,
 772 chip        1.47     Array<CIMKeyBinding>& keyBindings)
 773 kumpf       1.2  {
 774                      // Get the key-value pairs:
 775                  
 776                      while (*p)
 777                      {
 778                          // Get key part:
 779                  
 780 kumpf       1.5          char* equalsign = strchr(p, '=');
 781                          if (!equalsign)
 782 kumpf       1.2          {
 783 kumpf       1.10             throw MalformedObjectNameException(objectName);
 784 kumpf       1.2          }
 785                  
 786 kumpf       1.5          *equalsign = 0;
 787 kumpf       1.2  
 788 kumpf       1.17         if (!CIMName::legal(p))
 789 kumpf       1.10             throw MalformedObjectNameException(objectName);
 790 kumpf       1.2  
 791 kumpf       1.17         CIMName keyName (p);
 792                  
 793 kumpf       1.2          // Get the value part:
 794                  
 795                          String valueString;
 796 kumpf       1.5          p = equalsign + 1;
 797 kumpf       1.16         CIMKeyBinding::Type type;
 798 kumpf       1.2  
 799 kumpf       1.29         if (*p == '"')
 800 kumpf       1.2          {
 801 kumpf       1.29             // Could be CIMKeyBinding::STRING or CIMKeyBinding::REFERENCE
 802                  
 803 kumpf       1.2              p++;
 804                  
 805                              while (*p && *p != '"')
 806                              {
 807                                  if (*p == '\\')
 808 kumpf       1.28                 {
 809 kumpf       1.2                      *p++;
 810                  
 811 kumpf       1.28                     if ((*p != '\\') && (*p != '"'))
 812                                      {
 813                                          throw MalformedObjectNameException(objectName);
 814                                      }
 815                                  }
 816                  
 817 kumpf       1.2                  valueString.append(*p++);
 818                              }
 819                  
 820                              if (*p++ != '"')
 821 kumpf       1.10                 throw MalformedObjectNameException(objectName);
 822 kumpf       1.2  
 823 kumpf       1.29             /*
 824                                  Guess at the type of this quoted key value.  If the value
 825                                  can be parsed into a CIMObjectPath with at least one key
 826                                  binding, the type is assumed to be a REFERENCE.  Otherwise,
 827                                  the type is set to STRING.  (See method header for details.)
 828                               */
 829 kumpf       1.16             type = CIMKeyBinding::STRING;
 830 kumpf       1.2  
 831 kumpf       1.29             try
 832 kumpf       1.2              {
 833 kumpf       1.29                 CIMObjectPath testForPath(valueString);
 834                                  if (testForPath.getKeyBindings().size() > 0)
 835 kumpf       1.28                 {
 836 kumpf       1.29                     // We've found a reference value!
 837                                      type = CIMKeyBinding::REFERENCE;
 838 kumpf       1.28                 }
 839 kumpf       1.2              }
 840 david.dillard 1.41             catch (const Exception &)
 841 kumpf         1.29             {
 842                                    // Not a reference value; leave type as STRING
 843                                }
 844 kumpf         1.2          }
 845                            else if (toupper(*p) == 'T' || toupper(*p) == 'F')
 846                            {
 847 kumpf         1.16             type = CIMKeyBinding::BOOLEAN;
 848 kumpf         1.2  
 849                                char* r = p;
 850                                Uint32 n = 0;
 851                    
 852                                while (*r && *r != ',')
 853                                {
 854                                    *r = toupper(*r);
 855                                    r++;
 856                                    n++;
 857                                }
 858                    
 859                                if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) ||
 860                                      ((strncmp(p, "FALSE", n) == 0) && n == 5)))
 861 kumpf         1.10                 throw MalformedObjectNameException(objectName);
 862 kumpf         1.2  
 863                                valueString.assign(p, n);
 864                    
 865                                p = p + n;
 866                            }
 867                            else
 868                            {
 869 kumpf         1.16             type = CIMKeyBinding::NUMERIC;
 870 kumpf         1.2  
 871                                char* r = p;
 872                                Uint32 n = 0;
 873                    
 874                                while (*r && *r != ',')
 875                                {
 876                                    r++;
 877                                    n++;
 878                                }
 879                    
 880                                Boolean isComma = false;
 881                                if (*r)
 882                                {
 883                                    *r = '\0';
 884                                    isComma = true;
 885                                }
 886                    
 887 r.kieninger   1.56             if (*p == '-')
 888                                {
 889                                    Sint64 x;
 890                                    if (!XmlReader::stringToSignedInteger(p, x))
 891                                        throw MalformedObjectNameException(objectName);
 892                                }
 893                                else
 894                                {
 895                                    Uint64 x;
 896                                    if (!XmlReader::stringToUnsignedInteger(p, x))
 897                                        throw MalformedObjectNameException(objectName);
 898                                }
 899 kumpf         1.2  
 900                                valueString.assign(p, n);
 901                    
 902                                if (isComma)
 903                                {
 904                                    *r = ',';
 905                                }
 906                    
 907                                p = p + n;
 908                            }
 909                    
 910 chip          1.47         keyBindings.append(CIMKeyBinding(keyName.getString (), valueString,
 911 kumpf         1.17             type));
 912 kumpf         1.2  
 913                            if (*p)
 914                            {
 915                                if (*p++ != ',')
 916                                {
 917 kumpf         1.10                 throw MalformedObjectNameException(objectName);
 918 kumpf         1.2              }
 919                            }
 920                        }
 921                    
 922                        _BubbleSort(keyBindings);
 923                    }
 924                    
 925 chip          1.47 void CIMObjectPath::set(const String& objectName)
 926 kumpf         1.2  {
 927                        clear();
 928                    
 929                        //--------------------------------------------------------------------------
 930                        // We will extract components from an object name. Here is an sample
 931                        // object name:
 932                        //
 933                        //     //atp:9999/root/cimv25:TennisPlayer.first="Patrick",last="Rafter"
 934                        //--------------------------------------------------------------------------
 935                    
 936                        // Convert to a C String first:
 937                    
 938 david         1.37     CString pCString = objectName.getCString();
 939 kumpf         1.26     char* p = const_cast<char*>((const char*) pCString);
 940 kumpf         1.2      Boolean gotHost;
 941                        Boolean gotNamespace;
 942                    
 943                        gotHost = _parseHostElement(objectName, p, _rep->_host);
 944                        gotNamespace = _parseNamespaceElement(objectName, p, _rep->_nameSpace);
 945                    
 946                        if (gotHost && !gotNamespace)
 947                        {
 948 kumpf         1.10         throw MalformedObjectNameException(objectName);
 949 kumpf         1.2      }
 950                    
 951                        // Extract the class name:
 952                    
 953                        char* dot = strchr(p, '.');
 954                    
 955                        if (!dot)
 956                        {
 957                            if (!CIMName::legal(p))
 958                            {
 959 kumpf         1.10             throw MalformedObjectNameException(objectName);
 960 kumpf         1.2          }
 961                    
 962                            // ATTN: remove this later: a reference should only be able to hold
 963                            // an instance name.
 964                    
 965 kumpf         1.17         _rep->_className = CIMName (p);
 966 kumpf         1.2          return;
 967                        }
 968                    
 969 david         1.27     String className = String(p, (Uint32)(dot - p));
 970 kumpf         1.7      if (!CIMName::legal(className))
 971                        {
 972 kumpf         1.10         throw MalformedObjectNameException(objectName);
 973 kumpf         1.7      }
 974                        _rep->_className = className;
 975 kumpf         1.2  
 976                        // Advance past dot:
 977                    
 978                        p = dot + 1;
 979                    
 980                        _parseKeyBindingPairs(objectName, p, _rep->_keyBindings);
 981                    }
 982                    
 983                    CIMObjectPath& CIMObjectPath::operator=(const String& objectName)
 984                    {
 985                        set(objectName);
 986                        return *this;
 987                    }
 988                    
 989                    const String& CIMObjectPath::getHost() const
 990                    {
 991                        return _rep->_host;
 992                    }
 993                    
 994                    void CIMObjectPath::setHost(const String& host)
 995                    {
 996 kumpf         1.35     if ((host != String::EMPTY) && !CIMObjectPathRep::isValidHostname(host))
 997                        {
 998                            throw MalformedObjectNameException(host);
 999                        }
1000                    
1001 kumpf         1.2      _rep->_host = host;
1002                    }
1003                    
1004 kumpf         1.7  const CIMNamespaceName& CIMObjectPath::getNameSpace() const
1005 kumpf         1.2  {
1006                        return _rep->_nameSpace;
1007                    }
1008                    
1009 kumpf         1.7  void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace)
1010 kumpf         1.2  {
1011                       _rep->_nameSpace = nameSpace;
1012                    }
1013                    
1014 kumpf         1.7  const CIMName& CIMObjectPath::getClassName() const
1015 kumpf         1.2  {
1016                        return _rep->_className;
1017                    }
1018                    
1019 kumpf         1.7  void CIMObjectPath::setClassName(const CIMName& className)
1020 kumpf         1.2  {
1021                        _rep->_className = className;
1022                    }
1023                    
1024 kumpf         1.16 const Array<CIMKeyBinding>& CIMObjectPath::getKeyBindings() const
1025 kumpf         1.2  {
1026                        return _rep->_keyBindings;
1027                    }
1028                    
1029 kumpf         1.16 void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings)
1030 kumpf         1.2  {
1031                        _rep->_keyBindings = keyBindings;
1032                        _BubbleSort(_rep->_keyBindings);
1033                    }
1034                    
1035 kumpf         1.15 String CIMObjectPath::toString() const
1036 kumpf         1.2  {
1037                        String objectName;
1038                    
1039                        // Get the host:
1040                    
1041 kumpf         1.15     if (_rep->_host.size())
1042 kumpf         1.2      {
1043                            objectName = "//";
1044 kumpf         1.13         objectName.append(_rep->_host);
1045                            objectName.append("/");
1046 kumpf         1.2      }
1047                    
1048                        // Get the namespace (if we have a host name, we must write namespace):
1049                    
1050 kumpf         1.7      if (!_rep->_nameSpace.isNull() || _rep->_host.size())
1051 kumpf         1.2      {
1052 kumpf         1.17         objectName.append(_rep->_nameSpace.getString ());
1053 kumpf         1.13         objectName.append(":");
1054 kumpf         1.2      }
1055                    
1056                        // Get the class name:
1057                    
1058 kumpf         1.17     objectName.append(getClassName().getString ());
1059 kumpf         1.2  
1060 kumpf         1.9      //
1061                        //  ATTN-CAKG-P2-20020726:  The following condition does not correctly
1062                        //  distinguish instanceNames from classNames in every case
1063                        //  The instanceName of a singleton instance of a keyless class has no
1064                        //  key bindings
1065                        //
1066                        if (_rep->_keyBindings.size () != 0)
1067 kumpf         1.2      {
1068                            objectName.append('.');
1069                    
1070                            // Append each key-value pair:
1071                    
1072 kumpf         1.16         const Array<CIMKeyBinding>& keyBindings = getKeyBindings();
1073 kumpf         1.2  
1074                            for (Uint32 i = 0, n = keyBindings.size(); i < n; i++)
1075                            {
1076 kumpf         1.17             objectName.append(keyBindings[i].getName().getString ());
1077 kumpf         1.2              objectName.append('=');
1078                    
1079                                const String& value = _escapeSpecialCharacters(
1080                                    keyBindings[i].getValue());
1081                    
1082 kumpf         1.16             CIMKeyBinding::Type type = keyBindings[i].getType();
1083 chip          1.47 
1084 kumpf         1.57             if (type == CIMKeyBinding::STRING ||
1085                                    type == CIMKeyBinding::REFERENCE)
1086 kumpf         1.2                  objectName.append('"');
1087                    
1088                                objectName.append(value);
1089                    
1090 kumpf         1.57             if (type == CIMKeyBinding::STRING ||
1091                                    type == CIMKeyBinding::REFERENCE)
1092 kumpf         1.2                  objectName.append('"');
1093                    
1094                                if (i + 1 != n)
1095                                    objectName.append(',');
1096                            }
1097                        }
1098                    
1099                        return objectName;
1100                    }
1101                    
1102 kumpf         1.15 String CIMObjectPath::_toStringCanonical() const
1103 kumpf         1.2  {
1104                        CIMObjectPath ref = *this;
1105                    
1106 kumpf         1.33     // Normalize hostname by changing to lower case
1107 chip          1.47     ref._rep->_host.toLower(); // ICU_TODO:
1108 kumpf         1.2  
1109 kumpf         1.33     // Normalize namespace by changing to lower case
1110                        if (!ref._rep->_nameSpace.isNull())
1111                        {
1112                            String nameSpaceLower = ref._rep->_nameSpace.getString();
1113 chip          1.47         nameSpaceLower.toLower(); // ICU_TODO:
1114 kumpf         1.33         ref._rep->_nameSpace = nameSpaceLower;
1115                        }
1116                    
1117                        // Normalize class name by changing to lower case
1118                        if (!ref._rep->_className.isNull())
1119                        {
1120                            String classNameLower = ref._rep->_className.getString();
1121 chip          1.47         classNameLower.toLower(); // ICU_TODO:
1122 kumpf         1.33         ref._rep->_className = classNameLower;
1123                        }
1124 kumpf         1.2  
1125                        for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
1126                        {
1127 kumpf         1.33         // Normalize key binding name by changing to lower case
1128                            if (!ref._rep->_keyBindings[i]._rep->_name.isNull())
1129                            {
1130 chip          1.47             String keyBindingNameLower =
1131 kumpf         1.33                 ref._rep->_keyBindings[i]._rep->_name.getString();
1132                                keyBindingNameLower.toLower(); // ICU_TODO:
1133                                ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
1134                            }
1135                    
1136                            // Normalize the key value
1137                            switch (ref._rep->_keyBindings[i]._rep->_type)
1138                            {
1139                            case CIMKeyBinding::REFERENCE:
1140                                try
1141                                {
1142                                    // Convert reference to CIMObjectPath and recurse
1143                                    ref._rep->_keyBindings[i]._rep->_value =
1144                                        CIMObjectPath(ref._rep->_keyBindings[i]._rep->_value).
1145                                            _toStringCanonical();
1146                                }
1147                                catch (Exception&)
1148                                {
1149                                    // Leave value unchanged if the CIMObjectPath parsing fails
1150                                }
1151                                break;
1152 kumpf         1.33         case CIMKeyBinding::BOOLEAN:
1153                                // Normalize the boolean string by changing to lower case
1154                                ref._rep->_keyBindings[i]._rep->_value.toLower(); // ICU_TODO:
1155                                break;
1156                            case CIMKeyBinding::NUMERIC:
1157                                // Normalize the numeric string by converting to integer and back
1158                                Uint64 uValue;
1159                                Sint64 sValue;
1160                                // First try converting to unsigned integer
1161                                if (XmlReader::stringToUnsignedInteger(
1162                                        ref._rep->_keyBindings[i]._rep->_value.getCString(),
1163                                            uValue))
1164                                {
1165                                    char buffer[32];  // Should need 21 chars max
1166                                    sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", uValue);
1167                                    ref._rep->_keyBindings[i]._rep->_value = String(buffer);
1168                                }
1169                                // Next try converting to signed integer
1170                                else if (XmlReader::stringToSignedInteger(
1171                                             ref._rep->_keyBindings[i]._rep->_value.getCString(),
1172                                                 sValue))
1173 kumpf         1.33             {
1174                                    char buffer[32];  // Should need 21 chars max
1175                                    sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "d", sValue);
1176                                    ref._rep->_keyBindings[i]._rep->_value = String(buffer);
1177                                }
1178                                // Leave value unchanged if it cannot be converted to an integer
1179                                break;
1180                            default:  // CIMKeyBinding::STRING
1181                                // No normalization required for STRING
1182                                break;
1183                            }
1184 kumpf         1.2      }
1185                    
1186 kumpf         1.33     // Note: key bindings are sorted when set in the CIMObjectPath
1187 kumpf         1.12 
1188 kumpf         1.15     return ref.toString();
1189 kumpf         1.2  }
1190                    
1191                    Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
1192                    {
1193                        return
1194 kumpf         1.33         String::equalNoCase(_rep->_host, x._rep->_host) &&
1195 kumpf         1.7          _rep->_nameSpace.equal(x._rep->_nameSpace) &&
1196                            _rep->_className.equal(x._rep->_className) &&
1197 kumpf         1.2          _rep->_keyBindings == x._rep->_keyBindings;
1198                    }
1199                    
1200                    Uint32 CIMObjectPath::makeHashCode() const
1201                    {
1202 kumpf         1.12     return HashFunc<String>::hash(_toStringCanonical());
1203 kumpf         1.2  }
1204                    
1205                    Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y)
1206                    {
1207                        return x.identical(y);
1208                    }
1209                    
1210                    Boolean operator!=(const CIMObjectPath& x, const CIMObjectPath& y)
1211                    {
1212                        return !operator==(x, y);
1213                    }
1214                    
1215 chip          1.1  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2