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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2