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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2