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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2