(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.62.4.1     CIMObjectPathRep(): _refCounter(1)
 412 kumpf       1.2          {
 413                          }
 414                      
 415                          CIMObjectPathRep(const CIMObjectPathRep& x)
 416 marek       1.62.4.1         : _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.62.4.1         : _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.62.4.1     // 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.62.4.1 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.62.4.1     _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.62.4.1     
 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.62.4.1     _rep = tmpRef._rep;
 511                          Ref(_rep);
 512 kumpf       1.2      }
 513                      
 514                      CIMObjectPath::~CIMObjectPath()
 515                      {
 516 marek       1.62.4.1     Unref(_rep);
 517 kumpf       1.2      }
 518                      
 519                      CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x)
 520                      {
 521 marek       1.62.4.1     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.62.4.1 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.62.4.1     // 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.62.4.1     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.62.4.1     // 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.62.4.1     // 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 marek         1.62.4.2     if ((host != String::EMPTY) &&
 920                                (host != System::getHostName()) &&
 921                                !CIMObjectPathRep::isValidHostname(host))
 922 kumpf         1.35         {
 923                                throw MalformedObjectNameException(host);
 924                            }
 925 marek         1.62.4.1     _rep = _copyOnWriteCIMObjectPathRep(_rep);
 926 kumpf         1.35     
 927 kumpf         1.2          _rep->_host = host;
 928                        }
 929                        
 930 kumpf         1.7      const CIMNamespaceName& CIMObjectPath::getNameSpace() const
 931 kumpf         1.2      {
 932                            return _rep->_nameSpace;
 933                        }
 934                        
 935 kumpf         1.7      void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace)
 936 kumpf         1.2      {
 937 marek         1.62.4.1     _rep = _copyOnWriteCIMObjectPathRep(_rep);
 938 kumpf         1.2         _rep->_nameSpace = nameSpace;
 939                        }
 940                        
 941 kumpf         1.7      const CIMName& CIMObjectPath::getClassName() const
 942 kumpf         1.2      {
 943                            return _rep->_className;
 944                        }
 945                        
 946 kumpf         1.7      void CIMObjectPath::setClassName(const CIMName& className)
 947 kumpf         1.2      {
 948 marek         1.62.4.1     _rep = _copyOnWriteCIMObjectPathRep(_rep);
 949 kumpf         1.2          _rep->_className = className;
 950                        }
 951                        
 952 kumpf         1.16     const Array<CIMKeyBinding>& CIMObjectPath::getKeyBindings() const
 953 kumpf         1.2      {
 954                            return _rep->_keyBindings;
 955                        }
 956                        
 957 kumpf         1.16     void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings)
 958 kumpf         1.2      {
 959 marek         1.62.4.1     _rep = _copyOnWriteCIMObjectPathRep(_rep);
 960 kumpf         1.2          _rep->_keyBindings = keyBindings;
 961                            _BubbleSort(_rep->_keyBindings);
 962                        }
 963                        
 964 kumpf         1.15     String CIMObjectPath::toString() const
 965 kumpf         1.2      {
 966                            String objectName;
 967                        
 968                            // Get the host:
 969                        
 970 kumpf         1.15         if (_rep->_host.size())
 971 kumpf         1.2          {
 972                                objectName = "//";
 973 kumpf         1.13             objectName.append(_rep->_host);
 974                                objectName.append("/");
 975 kumpf         1.2          }
 976                        
 977                            // Get the namespace (if we have a host name, we must write namespace):
 978                        
 979 kumpf         1.7          if (!_rep->_nameSpace.isNull() || _rep->_host.size())
 980 kumpf         1.2          {
 981 kumpf         1.17             objectName.append(_rep->_nameSpace.getString ());
 982 kumpf         1.13             objectName.append(":");
 983 kumpf         1.2          }
 984                        
 985                            // Get the class name:
 986                        
 987 kumpf         1.17         objectName.append(getClassName().getString ());
 988 kumpf         1.2      
 989 kumpf         1.9          //
 990                            //  ATTN-CAKG-P2-20020726:  The following condition does not correctly
 991                            //  distinguish instanceNames from classNames in every case
 992                            //  The instanceName of a singleton instance of a keyless class has no
 993                            //  key bindings
 994                            //
 995                            if (_rep->_keyBindings.size () != 0)
 996 kumpf         1.2          {
 997                                objectName.append('.');
 998                        
 999                                // Append each key-value pair:
1000                        
1001 kumpf         1.16             const Array<CIMKeyBinding>& keyBindings = getKeyBindings();
1002 kumpf         1.2      
1003                                for (Uint32 i = 0, n = keyBindings.size(); i < n; i++)
1004                                {
1005 kumpf         1.17                 objectName.append(keyBindings[i].getName().getString ());
1006 kumpf         1.2                  objectName.append('=');
1007                        
1008                                    const String& value = _escapeSpecialCharacters(
1009                                        keyBindings[i].getValue());
1010                        
1011 kumpf         1.16                 CIMKeyBinding::Type type = keyBindings[i].getType();
1012 chip          1.47     
1013 kumpf         1.57                 if (type == CIMKeyBinding::STRING ||
1014                                        type == CIMKeyBinding::REFERENCE)
1015 kumpf         1.2                      objectName.append('"');
1016                        
1017                                    objectName.append(value);
1018                        
1019 kumpf         1.57                 if (type == CIMKeyBinding::STRING ||
1020                                        type == CIMKeyBinding::REFERENCE)
1021 kumpf         1.2                      objectName.append('"');
1022                        
1023                                    if (i + 1 != n)
1024                                        objectName.append(',');
1025                                }
1026                            }
1027                        
1028                            return objectName;
1029                        }
1030                        
1031 kumpf         1.15     String CIMObjectPath::_toStringCanonical() const
1032 kumpf         1.2      {
1033 marek         1.62.4.1     CIMObjectPath ref;
1034                            *ref._rep = *this->_rep;
1035 kumpf         1.2      
1036 kumpf         1.33         // Normalize hostname by changing to lower case
1037 chip          1.47         ref._rep->_host.toLower(); // ICU_TODO:
1038 kumpf         1.2      
1039 kumpf         1.33         // Normalize namespace by changing to lower case
1040                            if (!ref._rep->_nameSpace.isNull())
1041                            {
1042                                String nameSpaceLower = ref._rep->_nameSpace.getString();
1043 chip          1.47             nameSpaceLower.toLower(); // ICU_TODO:
1044 kumpf         1.33             ref._rep->_nameSpace = nameSpaceLower;
1045                            }
1046                        
1047                            // Normalize class name by changing to lower case
1048                            if (!ref._rep->_className.isNull())
1049                            {
1050                                String classNameLower = ref._rep->_className.getString();
1051 chip          1.47             classNameLower.toLower(); // ICU_TODO:
1052 kumpf         1.33             ref._rep->_className = classNameLower;
1053                            }
1054 kumpf         1.2      
1055                            for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
1056                            {
1057 kumpf         1.33             // Normalize key binding name by changing to lower case
1058                                if (!ref._rep->_keyBindings[i]._rep->_name.isNull())
1059                                {
1060 chip          1.47                 String keyBindingNameLower =
1061 kumpf         1.33                     ref._rep->_keyBindings[i]._rep->_name.getString();
1062                                    keyBindingNameLower.toLower(); // ICU_TODO:
1063                                    ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
1064                                }
1065                        
1066                                // Normalize the key value
1067                                switch (ref._rep->_keyBindings[i]._rep->_type)
1068                                {
1069                                case CIMKeyBinding::REFERENCE:
1070                                    try
1071                                    {
1072                                        // Convert reference to CIMObjectPath and recurse
1073                                        ref._rep->_keyBindings[i]._rep->_value =
1074                                            CIMObjectPath(ref._rep->_keyBindings[i]._rep->_value).
1075                                                _toStringCanonical();
1076                                    }
1077                                    catch (Exception&)
1078                                    {
1079                                        // Leave value unchanged if the CIMObjectPath parsing fails
1080                                    }
1081                                    break;
1082 kumpf         1.33             case CIMKeyBinding::BOOLEAN:
1083                                    // Normalize the boolean string by changing to lower case
1084                                    ref._rep->_keyBindings[i]._rep->_value.toLower(); // ICU_TODO:
1085                                    break;
1086                                case CIMKeyBinding::NUMERIC:
1087                                    // Normalize the numeric string by converting to integer and back
1088                                    Uint64 uValue;
1089                                    Sint64 sValue;
1090                                    // First try converting to unsigned integer
1091                                    if (XmlReader::stringToUnsignedInteger(
1092                                            ref._rep->_keyBindings[i]._rep->_value.getCString(),
1093                                                uValue))
1094                                    {
1095                                        char buffer[32];  // Should need 21 chars max
1096                                        sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", uValue);
1097                                        ref._rep->_keyBindings[i]._rep->_value = String(buffer);
1098                                    }
1099                                    // Next try converting to signed integer
1100                                    else if (XmlReader::stringToSignedInteger(
1101                                                 ref._rep->_keyBindings[i]._rep->_value.getCString(),
1102                                                     sValue))
1103 kumpf         1.33                 {
1104                                        char buffer[32];  // Should need 21 chars max
1105                                        sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "d", sValue);
1106                                        ref._rep->_keyBindings[i]._rep->_value = String(buffer);
1107                                    }
1108                                    // Leave value unchanged if it cannot be converted to an integer
1109                                    break;
1110                                default:  // CIMKeyBinding::STRING
1111                                    // No normalization required for STRING
1112                                    break;
1113                                }
1114 kumpf         1.2          }
1115                        
1116 kumpf         1.33         // Note: key bindings are sorted when set in the CIMObjectPath
1117 kumpf         1.12     
1118 kumpf         1.15         return ref.toString();
1119 kumpf         1.2      }
1120                        
1121                        Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
1122                        {
1123                            return
1124 kumpf         1.33             String::equalNoCase(_rep->_host, x._rep->_host) &&
1125 kumpf         1.7              _rep->_nameSpace.equal(x._rep->_nameSpace) &&
1126                                _rep->_className.equal(x._rep->_className) &&
1127 kumpf         1.2              _rep->_keyBindings == x._rep->_keyBindings;
1128                        }
1129                        
1130                        Uint32 CIMObjectPath::makeHashCode() const
1131                        {
1132 kumpf         1.12         return HashFunc<String>::hash(_toStringCanonical());
1133 kumpf         1.2      }
1134                        
1135                        Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y)
1136                        {
1137                            return x.identical(y);
1138                        }
1139                        
1140                        Boolean operator!=(const CIMObjectPath& x, const CIMObjectPath& y)
1141                        {
1142                            return !operator==(x, y);
1143                        }
1144                        
1145 chip          1.1      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2