(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 venkat.puvvada 1.60.4.2 #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 venkat.puvvada 1.60.4.2         HostLocator addr(hostname);
 450 kumpf          1.34     
 451 venkat.puvvada 1.60.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                                     while (*p && *p != '"')
 659                                     {
 660                                         if (*p == '\\')
 661 kumpf          1.28                     {
 662 kumpf          1.2                          *p++;
 663                         
 664 kumpf          1.28                         if ((*p != '\\') && (*p != '"'))
 665                                             {
 666                                                 throw MalformedObjectNameException(objectName);
 667                                             }
 668                                         }
 669                         
 670 kumpf          1.2                      valueString.append(*p++);
 671                                     }
 672                         
 673                                     if (*p++ != '"')
 674 kumpf          1.10                     throw MalformedObjectNameException(objectName);
 675 kumpf          1.2      
 676 kumpf          1.29                 /*
 677                                         Guess at the type of this quoted key value.  If the value
 678                                         can be parsed into a CIMObjectPath with at least one key
 679                                         binding, the type is assumed to be a REFERENCE.  Otherwise,
 680                                         the type is set to STRING.  (See method header for details.)
 681                                      */
 682 kumpf          1.16                 type = CIMKeyBinding::STRING;
 683 kumpf          1.2      
 684 kumpf          1.29                 try
 685 kumpf          1.2                  {
 686 kumpf          1.29                     CIMObjectPath testForPath(valueString);
 687                                         if (testForPath.getKeyBindings().size() > 0)
 688 kumpf          1.28                     {
 689 kumpf          1.29                         // We've found a reference value!
 690                                             type = CIMKeyBinding::REFERENCE;
 691 kumpf          1.28                     }
 692 kumpf          1.2                  }
 693 david.dillard  1.41                 catch (const Exception &)
 694 kumpf          1.29                 {
 695                                         // Not a reference value; leave type as STRING
 696                                     }
 697 kumpf          1.2              }
 698                                 else if (toupper(*p) == 'T' || toupper(*p) == 'F')
 699                                 {
 700 kumpf          1.16                 type = CIMKeyBinding::BOOLEAN;
 701 kumpf          1.2      
 702                                     char* r = p;
 703                                     Uint32 n = 0;
 704                         
 705                                     while (*r && *r != ',')
 706                                     {
 707                                         *r = toupper(*r);
 708                                         r++;
 709                                         n++;
 710                                     }
 711                         
 712                                     if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) ||
 713                                           ((strncmp(p, "FALSE", n) == 0) && n == 5)))
 714 kumpf          1.10                     throw MalformedObjectNameException(objectName);
 715 kumpf          1.2      
 716                                     valueString.assign(p, n);
 717                         
 718                                     p = p + n;
 719                                 }
 720                                 else
 721                                 {
 722 kumpf          1.16                 type = CIMKeyBinding::NUMERIC;
 723 kumpf          1.2      
 724                                     char* r = p;
 725                                     Uint32 n = 0;
 726                         
 727                                     while (*r && *r != ',')
 728                                     {
 729                                         r++;
 730                                         n++;
 731                                     }
 732                         
 733                                     Boolean isComma = false;
 734                                     if (*r)
 735                                     {
 736                                         *r = '\0';
 737                                         isComma = true;
 738                                     }
 739                         
 740 r.kieninger    1.56                 if (*p == '-')
 741                                     {
 742                                         Sint64 x;
 743                                         if (!XmlReader::stringToSignedInteger(p, x))
 744                                             throw MalformedObjectNameException(objectName);
 745                                     }
 746                                     else
 747                                     {
 748                                         Uint64 x;
 749                                         if (!XmlReader::stringToUnsignedInteger(p, x))
 750                                             throw MalformedObjectNameException(objectName);
 751                                     }
 752 kumpf          1.2      
 753                                     valueString.assign(p, n);
 754                         
 755                                     if (isComma)
 756                                     {
 757                                         *r = ',';
 758                                     }
 759                         
 760                                     p = p + n;
 761                                 }
 762                         
 763 chip           1.47             keyBindings.append(CIMKeyBinding(keyName.getString (), valueString,
 764 kumpf          1.17                 type));
 765 kumpf          1.2      
 766                                 if (*p)
 767                                 {
 768                                     if (*p++ != ',')
 769                                     {
 770 kumpf          1.10                     throw MalformedObjectNameException(objectName);
 771 kumpf          1.2                  }
 772                                 }
 773                             }
 774                         
 775                             _BubbleSort(keyBindings);
 776                         }
 777                         
 778 chip           1.47     void CIMObjectPath::set(const String& objectName)
 779 kumpf          1.2      {
 780                             clear();
 781                         
 782                             //--------------------------------------------------------------------------
 783                             // We will extract components from an object name. Here is an sample
 784                             // object name:
 785                             //
 786                             //     //atp:9999/root/cimv25:TennisPlayer.first="Patrick",last="Rafter"
 787                             //--------------------------------------------------------------------------
 788                         
 789                             // Convert to a C String first:
 790                         
 791 david          1.37         CString pCString = objectName.getCString();
 792 kumpf          1.26         char* p = const_cast<char*>((const char*) pCString);
 793 kumpf          1.2          Boolean gotHost;
 794                             Boolean gotNamespace;
 795                         
 796                             gotHost = _parseHostElement(objectName, p, _rep->_host);
 797                             gotNamespace = _parseNamespaceElement(objectName, p, _rep->_nameSpace);
 798                         
 799                             if (gotHost && !gotNamespace)
 800                             {
 801 kumpf          1.10             throw MalformedObjectNameException(objectName);
 802 kumpf          1.2          }
 803                         
 804                             // Extract the class name:
 805                         
 806                             char* dot = strchr(p, '.');
 807                         
 808                             if (!dot)
 809                             {
 810                                 if (!CIMName::legal(p))
 811                                 {
 812 kumpf          1.10                 throw MalformedObjectNameException(objectName);
 813 kumpf          1.2              }
 814                         
 815                                 // ATTN: remove this later: a reference should only be able to hold
 816                                 // an instance name.
 817                         
 818 kumpf          1.17             _rep->_className = CIMName (p);
 819 kumpf          1.2              return;
 820                             }
 821                         
 822 david          1.27         String className = String(p, (Uint32)(dot - p));
 823 kumpf          1.7          if (!CIMName::legal(className))
 824                             {
 825 kumpf          1.10             throw MalformedObjectNameException(objectName);
 826 kumpf          1.7          }
 827                             _rep->_className = className;
 828 kumpf          1.2      
 829                             // Advance past dot:
 830                         
 831                             p = dot + 1;
 832                         
 833                             _parseKeyBindingPairs(objectName, p, _rep->_keyBindings);
 834                         }
 835                         
 836                         CIMObjectPath& CIMObjectPath::operator=(const String& objectName)
 837                         {
 838                             set(objectName);
 839                             return *this;
 840                         }
 841                         
 842                         const String& CIMObjectPath::getHost() const
 843                         {
 844                             return _rep->_host;
 845                         }
 846                         
 847                         void CIMObjectPath::setHost(const String& host)
 848                         {
 849 kumpf          1.35         if ((host != String::EMPTY) && !CIMObjectPathRep::isValidHostname(host))
 850                             {
 851                                 throw MalformedObjectNameException(host);
 852                             }
 853                         
 854 kumpf          1.2          _rep->_host = host;
 855                         }
 856                         
 857 kumpf          1.7      const CIMNamespaceName& CIMObjectPath::getNameSpace() const
 858 kumpf          1.2      {
 859                             return _rep->_nameSpace;
 860                         }
 861                         
 862 kumpf          1.7      void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace)
 863 kumpf          1.2      {
 864                            _rep->_nameSpace = nameSpace;
 865                         }
 866                         
 867 kumpf          1.7      const CIMName& CIMObjectPath::getClassName() const
 868 kumpf          1.2      {
 869                             return _rep->_className;
 870                         }
 871                         
 872 kumpf          1.7      void CIMObjectPath::setClassName(const CIMName& className)
 873 kumpf          1.2      {
 874                             _rep->_className = className;
 875                         }
 876                         
 877 kumpf          1.16     const Array<CIMKeyBinding>& CIMObjectPath::getKeyBindings() const
 878 kumpf          1.2      {
 879                             return _rep->_keyBindings;
 880                         }
 881                         
 882 kumpf          1.16     void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings)
 883 kumpf          1.2      {
 884                             _rep->_keyBindings = keyBindings;
 885                             _BubbleSort(_rep->_keyBindings);
 886                         }
 887                         
 888 kumpf          1.15     String CIMObjectPath::toString() const
 889 kumpf          1.2      {
 890                             String objectName;
 891                         
 892                             // Get the host:
 893                         
 894 kumpf          1.15         if (_rep->_host.size())
 895 kumpf          1.2          {
 896                                 objectName = "//";
 897 kumpf          1.13             objectName.append(_rep->_host);
 898                                 objectName.append("/");
 899 kumpf          1.2          }
 900                         
 901                             // Get the namespace (if we have a host name, we must write namespace):
 902                         
 903 kumpf          1.7          if (!_rep->_nameSpace.isNull() || _rep->_host.size())
 904 kumpf          1.2          {
 905 kumpf          1.17             objectName.append(_rep->_nameSpace.getString ());
 906 kumpf          1.13             objectName.append(":");
 907 kumpf          1.2          }
 908                         
 909                             // Get the class name:
 910                         
 911 kumpf          1.17         objectName.append(getClassName().getString ());
 912 kumpf          1.2      
 913 kumpf          1.9          //
 914                             //  ATTN-CAKG-P2-20020726:  The following condition does not correctly
 915                             //  distinguish instanceNames from classNames in every case
 916                             //  The instanceName of a singleton instance of a keyless class has no
 917                             //  key bindings
 918                             //
 919                             if (_rep->_keyBindings.size () != 0)
 920 kumpf          1.2          {
 921                                 objectName.append('.');
 922                         
 923                                 // Append each key-value pair:
 924                         
 925 kumpf          1.16             const Array<CIMKeyBinding>& keyBindings = getKeyBindings();
 926 kumpf          1.2      
 927                                 for (Uint32 i = 0, n = keyBindings.size(); i < n; i++)
 928                                 {
 929 kumpf          1.17                 objectName.append(keyBindings[i].getName().getString ());
 930 kumpf          1.2                  objectName.append('=');
 931                         
 932                                     const String& value = _escapeSpecialCharacters(
 933                                         keyBindings[i].getValue());
 934                         
 935 kumpf          1.16                 CIMKeyBinding::Type type = keyBindings[i].getType();
 936 chip           1.47     
 937 kumpf          1.57                 if (type == CIMKeyBinding::STRING ||
 938                                         type == CIMKeyBinding::REFERENCE)
 939 kumpf          1.2                      objectName.append('"');
 940                         
 941                                     objectName.append(value);
 942                         
 943 kumpf          1.57                 if (type == CIMKeyBinding::STRING ||
 944                                         type == CIMKeyBinding::REFERENCE)
 945 kumpf          1.2                      objectName.append('"');
 946                         
 947                                     if (i + 1 != n)
 948                                         objectName.append(',');
 949                                 }
 950                             }
 951                         
 952                             return objectName;
 953                         }
 954                         
 955 kumpf          1.15     String CIMObjectPath::_toStringCanonical() const
 956 kumpf          1.2      {
 957                             CIMObjectPath ref = *this;
 958                         
 959 kumpf          1.33         // Normalize hostname by changing to lower case
 960 chip           1.47         ref._rep->_host.toLower(); // ICU_TODO:
 961 kumpf          1.2      
 962 kumpf          1.33         // Normalize namespace by changing to lower case
 963                             if (!ref._rep->_nameSpace.isNull())
 964                             {
 965                                 String nameSpaceLower = ref._rep->_nameSpace.getString();
 966 chip           1.47             nameSpaceLower.toLower(); // ICU_TODO:
 967 kumpf          1.33             ref._rep->_nameSpace = nameSpaceLower;
 968                             }
 969                         
 970                             // Normalize class name by changing to lower case
 971                             if (!ref._rep->_className.isNull())
 972                             {
 973                                 String classNameLower = ref._rep->_className.getString();
 974 chip           1.47             classNameLower.toLower(); // ICU_TODO:
 975 kumpf          1.33             ref._rep->_className = classNameLower;
 976                             }
 977 kumpf          1.2      
 978                             for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
 979                             {
 980 kumpf          1.33             // Normalize key binding name by changing to lower case
 981                                 if (!ref._rep->_keyBindings[i]._rep->_name.isNull())
 982                                 {
 983 chip           1.47                 String keyBindingNameLower =
 984 kumpf          1.33                     ref._rep->_keyBindings[i]._rep->_name.getString();
 985                                     keyBindingNameLower.toLower(); // ICU_TODO:
 986                                     ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
 987                                 }
 988                         
 989                                 // Normalize the key value
 990                                 switch (ref._rep->_keyBindings[i]._rep->_type)
 991                                 {
 992                                 case CIMKeyBinding::REFERENCE:
 993                                     try
 994                                     {
 995                                         // Convert reference to CIMObjectPath and recurse
 996                                         ref._rep->_keyBindings[i]._rep->_value =
 997                                             CIMObjectPath(ref._rep->_keyBindings[i]._rep->_value).
 998                                                 _toStringCanonical();
 999                                     }
1000                                     catch (Exception&)
1001                                     {
1002                                         // Leave value unchanged if the CIMObjectPath parsing fails
1003                                     }
1004                                     break;
1005 kumpf          1.33             case CIMKeyBinding::BOOLEAN:
1006                                     // Normalize the boolean string by changing to lower case
1007                                     ref._rep->_keyBindings[i]._rep->_value.toLower(); // ICU_TODO:
1008                                     break;
1009                                 case CIMKeyBinding::NUMERIC:
1010                                     // Normalize the numeric string by converting to integer and back
1011                                     Uint64 uValue;
1012                                     Sint64 sValue;
1013                                     // First try converting to unsigned integer
1014                                     if (XmlReader::stringToUnsignedInteger(
1015                                             ref._rep->_keyBindings[i]._rep->_value.getCString(),
1016                                                 uValue))
1017                                     {
1018                                         char buffer[32];  // Should need 21 chars max
1019                                         sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", uValue);
1020                                         ref._rep->_keyBindings[i]._rep->_value = String(buffer);
1021                                     }
1022                                     // Next try converting to signed integer
1023                                     else if (XmlReader::stringToSignedInteger(
1024                                                  ref._rep->_keyBindings[i]._rep->_value.getCString(),
1025                                                      sValue))
1026 kumpf          1.33                 {
1027                                         char buffer[32];  // Should need 21 chars max
1028                                         sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "d", sValue);
1029                                         ref._rep->_keyBindings[i]._rep->_value = String(buffer);
1030                                     }
1031                                     // Leave value unchanged if it cannot be converted to an integer
1032                                     break;
1033                                 default:  // CIMKeyBinding::STRING
1034                                     // No normalization required for STRING
1035                                     break;
1036                                 }
1037 kumpf          1.2          }
1038                         
1039 kumpf          1.33         // Note: key bindings are sorted when set in the CIMObjectPath
1040 kumpf          1.12     
1041 kumpf          1.15         return ref.toString();
1042 kumpf          1.2      }
1043                         
1044                         Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
1045                         {
1046                             return
1047 kumpf          1.33             String::equalNoCase(_rep->_host, x._rep->_host) &&
1048 kumpf          1.7              _rep->_nameSpace.equal(x._rep->_nameSpace) &&
1049                                 _rep->_className.equal(x._rep->_className) &&
1050 kumpf          1.2              _rep->_keyBindings == x._rep->_keyBindings;
1051                         }
1052                         
1053                         Uint32 CIMObjectPath::makeHashCode() const
1054                         {
1055 kumpf          1.12         return HashFunc<String>::hash(_toStringCanonical());
1056 kumpf          1.2      }
1057                         
1058                         Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y)
1059                         {
1060                             return x.identical(y);
1061                         }
1062                         
1063                         Boolean operator!=(const CIMObjectPath& x, const CIMObjectPath& y)
1064                         {
1065                             return !operator==(x, y);
1066                         }
1067                         
1068 chip           1.1      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2