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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2