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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2