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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2