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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2