(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.58.4.1 #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.58.4.1         HostLocator addr(hostname);
 450 kumpf       1.34     
 451 dave.sudlik 1.58.4.1         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.58.4.2             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.58.4.2                     p++;
 666 kumpf       1.2      
 667 kumpf       1.28                         if ((*p != '\\') && (*p != '"'))
 668                                          {
 669                                              throw MalformedObjectNameException(objectName);
 670                                          }
 671                                      }
 672                      
 673 kumpf       1.58.4.2                 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.58.4.2             // 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