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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2