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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2