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

   1 kumpf 1.2 //%/////////////////////////////////////////////////////////////////////////////
   2 chip  1.1 //
   3 kumpf 1.6 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
   4           // The Open Group, Tivoli Systems
   5 chip  1.1 //
   6           // Permission is hereby granted, free of charge, to any person obtaining a copy
   7           // of this software and associated documentation files (the "Software"), to
   8           // deal in the Software without restriction, including without limitation the
   9           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10           // sell copies of the Software, and to permit persons to whom the Software is
  11           // furnished to do so, subject to the following conditions:
  12 kumpf 1.6 // 
  13 chip  1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
  14           // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
  15           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
  16           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  17           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  19           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  20           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21           //
  22           //==============================================================================
  23           //
  24 kumpf 1.2 // Author: Mike Brasher (mbrasher@bmc.com)
  25 chip  1.1 //
  26 kumpf 1.2 // Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
  27 kumpf 1.9 //              Carol Ann Krug Graves, Hewlett-Packard Company
  28           //                (carolann_graves@hp.com)
  29 chip  1.1 //
  30           //%/////////////////////////////////////////////////////////////////////////////
  31           
  32 kumpf 1.2 #include <Pegasus/Common/Config.h>
  33           #include <cctype>
  34           #include <cstring>
  35 kumpf 1.22 #include <iostream>
  36 kumpf 1.2  #include "HashTable.h"
  37            #include "CIMObjectPath.h"
  38            #include "Indentor.h"
  39            #include "CIMName.h"
  40            #include "Destroyer.h"
  41            #include "XmlWriter.h"
  42            #include "XmlReader.h"
  43 kumpf 1.11 #include "ArrayInternal.h"
  44 kumpf 1.2  #include "CIMOMPort.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                        case '\n':
  81 kumpf 1.13                 result.append("\\n");
  82 kumpf 1.2                  break;
  83            
  84                        case '\r':
  85 kumpf 1.13                 result.append("\\r");
  86 kumpf 1.2                  break;
  87            
  88                        case '\t':
  89 kumpf 1.13                 result.append("\\t");
  90 kumpf 1.2                  break;
  91            
  92                        case '"':
  93 kumpf 1.13                 result.append("\\\"");
  94 kumpf 1.2                  break;
  95            
  96                        default:
  97 kumpf 1.13                 result.append(str[i]);
  98 kumpf 1.2          }
  99                }
 100            
 101                return result;
 102            }
 103            
 104 kumpf 1.16 static void _BubbleSort(Array<CIMKeyBinding>& x)
 105 kumpf 1.2  {
 106                Uint32 n = x.size();
 107            
 108 kumpf 1.24     //
 109                //  If the key is a reference, the keys in the reference must also be 
 110                //  sorted
 111                //
 112                for (Uint32 k = 0; k < n ; k++)
 113                    if (x[k].getType () == CIMKeyBinding::REFERENCE)
 114                    {
 115                        CIMObjectPath tmp (x[k].getValue ());
 116                        Array <CIMKeyBinding> keyBindings = tmp.getKeyBindings ();
 117                        _BubbleSort (keyBindings);
 118                        tmp.setKeyBindings (keyBindings);
 119                        x[k].setValue (tmp.toString ());
 120                    }
 121            
 122 kumpf 1.2      if (n < 2)
 123                    return;
 124            
 125                for (Uint32 i = 0; i < n - 1; i++)
 126                {
 127                    for (Uint32 j = 0; j < n - 1; j++)
 128                    {
 129 kumpf 1.17             if (String::compareNoCase(x[j].getName().getString(), 
 130                                                  x[j+1].getName().getString()) > 0)
 131 kumpf 1.2              {
 132 kumpf 1.16                 CIMKeyBinding t = x[j];
 133 kumpf 1.2                  x[j] = x[j+1];
 134                            x[j+1] = t;
 135                        }
 136                    }
 137                }
 138            }
 139            
 140            ////////////////////////////////////////////////////////////////////////////////
 141            //
 142 kumpf 1.16 // CIMKeyBinding
 143 kumpf 1.2  //
 144            ////////////////////////////////////////////////////////////////////////////////
 145            
 146 kumpf 1.16 class CIMKeyBindingRep
 147 kumpf 1.2  {
 148            public:
 149 kumpf 1.16     CIMKeyBindingRep()
 150 kumpf 1.2      {
 151                }
 152            
 153 kumpf 1.16     CIMKeyBindingRep(const CIMKeyBindingRep& x)
 154 kumpf 1.2          : _name(x._name), _value(x._value), _type(x._type)
 155                {
 156                }
 157            
 158 kumpf 1.16     CIMKeyBindingRep(
 159 kumpf 1.7          const CIMName& name,
 160 kumpf 1.2          const String& value,
 161 kumpf 1.16         CIMKeyBinding::Type type)
 162 kumpf 1.2          : _name(name), _value(value), _type(type)
 163                {
 164                }
 165            
 166 kumpf 1.16     ~CIMKeyBindingRep()
 167 kumpf 1.2      {
 168                }
 169            
 170 kumpf 1.16     CIMKeyBindingRep& operator=(const CIMKeyBindingRep& x)
 171 kumpf 1.2      {
 172                    if (&x != this)
 173                    {
 174                        _name = x._name;
 175                        _value = x._value;
 176                        _type = x._type;
 177                    }
 178                    return *this;
 179                }
 180            
 181 kumpf 1.7      CIMName _name;
 182 kumpf 1.2      String _value;
 183 kumpf 1.16     CIMKeyBinding::Type _type;
 184 kumpf 1.2  };
 185            
 186            
 187 kumpf 1.16 CIMKeyBinding::CIMKeyBinding()
 188 kumpf 1.2  {
 189 kumpf 1.16     _rep = new CIMKeyBindingRep();
 190 kumpf 1.2  }
 191            
 192 kumpf 1.16 CIMKeyBinding::CIMKeyBinding(const CIMKeyBinding& x)
 193 kumpf 1.2  {
 194 kumpf 1.16     _rep = new CIMKeyBindingRep(*x._rep);
 195 kumpf 1.2  }
 196            
 197 kumpf 1.16 CIMKeyBinding::CIMKeyBinding(const CIMName& name, const String& value, Type type)
 198 kumpf 1.2  {
 199 kumpf 1.16     _rep = new CIMKeyBindingRep(name, value, type);
 200 kumpf 1.2  }
 201            
 202 kumpf 1.18 CIMKeyBinding::CIMKeyBinding(const CIMName& name, const CIMValue& value)
 203            {
 204 kumpf 1.21     if (value.isArray())
 205 kumpf 1.20     {
 206                    throw TypeMismatchException();
 207                }
 208            
 209 kumpf 1.18     String kbValue = value.toString();
 210                Type kbType;
 211            
 212                switch (value.getType())
 213                {
 214                case CIMTYPE_BOOLEAN:
 215                    kbType = BOOLEAN;
 216                    break;
 217                case CIMTYPE_CHAR16:
 218                case CIMTYPE_STRING:
 219                case CIMTYPE_DATETIME:
 220                    kbType = STRING;
 221                    break;
 222                case CIMTYPE_REFERENCE:
 223                    kbType = REFERENCE;
 224                    break;
 225                default:
 226                    kbType = NUMERIC;
 227                    break;
 228                }
 229            
 230 kumpf 1.18     _rep = new CIMKeyBindingRep(name, kbValue, kbType);
 231            }
 232            
 233 kumpf 1.16 CIMKeyBinding::~CIMKeyBinding()
 234 kumpf 1.2  {
 235                delete _rep;
 236            }
 237            
 238 kumpf 1.16 CIMKeyBinding& CIMKeyBinding::operator=(const CIMKeyBinding& x)
 239 kumpf 1.2  {
 240                *_rep = *x._rep;
 241                return *this;
 242            }
 243            
 244 kumpf 1.16 const CIMName& CIMKeyBinding::getName() const
 245 kumpf 1.2  {
 246                return _rep->_name;
 247            }
 248            
 249 kumpf 1.16 void CIMKeyBinding::setName(const CIMName& name)
 250 kumpf 1.2  {
 251                _rep->_name = name;
 252            }
 253            
 254 kumpf 1.16 const String& CIMKeyBinding::getValue() const
 255 kumpf 1.2  {
 256                return _rep->_value;
 257            }
 258            
 259 kumpf 1.16 void CIMKeyBinding::setValue(const String& value)
 260 kumpf 1.2  {
 261                _rep->_value = value;
 262            }
 263            
 264 kumpf 1.16 CIMKeyBinding::Type CIMKeyBinding::getType() const
 265 kumpf 1.2  {
 266                return _rep->_type;
 267            }
 268            
 269 kumpf 1.16 void CIMKeyBinding::setType(CIMKeyBinding::Type type)
 270 kumpf 1.2  {
 271                _rep->_type = type;
 272            }
 273 kumpf 1.18 
 274            Boolean CIMKeyBinding::equal(CIMValue value)
 275            {
 276 kumpf 1.21     if (value.isArray())
 277 kumpf 1.20     {
 278                    return false;
 279                }
 280            
 281 kumpf 1.18     CIMValue kbValue;
 282            
 283                try
 284                {
 285                    switch (value.getType())
 286                    {
 287                    case CIMTYPE_CHAR16:
 288 kumpf 1.20             if (getType() != STRING) return false;
 289 kumpf 1.18             kbValue.set(getValue()[0]);
 290                        break;
 291                    case CIMTYPE_DATETIME:
 292 kumpf 1.20             if (getType() != STRING) return false;
 293 kumpf 1.18             kbValue.set(CIMDateTime(getValue()));
 294                        break;
 295                    case CIMTYPE_STRING:
 296 kumpf 1.20             if (getType() != STRING) return false;
 297 kumpf 1.18             kbValue.set(getValue());
 298                        break;
 299                    case CIMTYPE_REFERENCE:
 300 kumpf 1.20             if (getType() != REFERENCE) return false;
 301 kumpf 1.18             kbValue.set(CIMObjectPath(getValue()));
 302                        break;
 303 kumpf 1.20         case CIMTYPE_BOOLEAN:
 304                        if (getType() != BOOLEAN) return false;
 305                        kbValue = XmlReader::stringToValue(0, getValue().getCString(),
 306                                                           value.getType());
 307                        break;
 308                    default:  // Numerics
 309                        if (getType() != NUMERIC) return false;
 310 kumpf 1.18             kbValue = XmlReader::stringToValue(0, getValue().getCString(),
 311                                                           value.getType());
 312                        break;
 313                    }
 314                }
 315 kumpf 1.19     catch (Exception&)
 316 kumpf 1.18     {
 317                    return false;
 318                }
 319            
 320                return value.equal(kbValue);
 321            }
 322 kumpf 1.2  
 323 kumpf 1.16 Boolean operator==(const CIMKeyBinding& x, const CIMKeyBinding& y)
 324 kumpf 1.2  {
 325                return
 326 kumpf 1.7          x.getName().equal(y.getName()) &&
 327 kumpf 1.2          String::equal(x.getValue(), y.getValue()) &&
 328                    x.getType() == y.getType();
 329            }
 330            
 331            
 332            ////////////////////////////////////////////////////////////////////////////////
 333            //
 334            // CIMObjectPath
 335            //
 336            ////////////////////////////////////////////////////////////////////////////////
 337            
 338            class CIMObjectPathRep
 339            {
 340            public:
 341                CIMObjectPathRep()
 342                {
 343                }
 344            
 345                CIMObjectPathRep(const CIMObjectPathRep& x)
 346                    : _host(x._host), _nameSpace(x._nameSpace),
 347                    _className(x._className), _keyBindings(x._keyBindings)
 348 kumpf 1.2      {
 349                }
 350            
 351                CIMObjectPathRep(
 352                    const String& host,
 353 kumpf 1.7          const CIMNamespaceName& nameSpace,
 354                    const CIMName& className,
 355 kumpf 1.16         const Array<CIMKeyBinding>& keyBindings)
 356 kumpf 1.2          : _host(host), _nameSpace(nameSpace),
 357                    _className(className), _keyBindings(keyBindings)
 358                {
 359                }
 360            
 361                ~CIMObjectPathRep()
 362                {
 363                }
 364            
 365                CIMObjectPathRep& operator=(const CIMObjectPathRep& x)
 366                {
 367                    if (&x != this)
 368                    {
 369                        _host = x._host;
 370                        _nameSpace = x._nameSpace;
 371                        _className = x._className;
 372                        _keyBindings = x._keyBindings;
 373                    }
 374                    return *this;
 375                }
 376            
 377 kumpf 1.2      //
 378                // Contains port as well (e.g., myhost:1234).
 379                //
 380                String _host;
 381            
 382 kumpf 1.7      CIMNamespaceName _nameSpace;
 383                CIMName _className;
 384 kumpf 1.16     Array<CIMKeyBinding> _keyBindings;
 385 kumpf 1.2  };
 386            
 387            
 388            CIMObjectPath::CIMObjectPath()
 389            {
 390                _rep = new CIMObjectPathRep();
 391            }
 392            
 393            CIMObjectPath::CIMObjectPath(const CIMObjectPath& x)
 394            {
 395                _rep = new CIMObjectPathRep(*x._rep);
 396            }
 397            
 398            CIMObjectPath::CIMObjectPath(const String& objectName)
 399            {
 400                // Test the objectName out to see if we get an exception
 401                CIMObjectPath tmpRef;
 402                tmpRef.set(objectName);
 403            
 404                _rep = new CIMObjectPathRep(*tmpRef._rep);
 405            }
 406 kumpf 1.2  
 407            CIMObjectPath::CIMObjectPath(
 408                const String& host,
 409 kumpf 1.7      const CIMNamespaceName& nameSpace,
 410                const CIMName& className,
 411 kumpf 1.16     const Array<CIMKeyBinding>& keyBindings)
 412 kumpf 1.2  {
 413                // Test the objectName out to see if we get an exception
 414                CIMObjectPath tmpRef;
 415                tmpRef.set(host, nameSpace, className, keyBindings);
 416            
 417                _rep = new CIMObjectPathRep(*tmpRef._rep);
 418            }
 419            
 420            CIMObjectPath::~CIMObjectPath()
 421            {
 422                delete _rep;
 423            }
 424            
 425            CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x)
 426            {
 427                *_rep = *x._rep;
 428                return *this;
 429            }
 430            
 431            void CIMObjectPath::clear()
 432            {
 433 kumpf 1.2      _rep->_host.clear();
 434                _rep->_nameSpace.clear();
 435                _rep->_className.clear();
 436                _rep->_keyBindings.clear();
 437            }
 438            
 439            void CIMObjectPath::set(
 440                const String& host,
 441 kumpf 1.7      const CIMNamespaceName& nameSpace,
 442                const CIMName& className,
 443 kumpf 1.16     const Array<CIMKeyBinding>& keyBindings)
 444 kumpf 1.2  {
 445               setHost(host);
 446               setNameSpace(nameSpace);
 447               setClassName(className);
 448               setKeyBindings(keyBindings);
 449            }
 450            
 451 kumpf 1.22 Boolean _parseHostElement(
 452 kumpf 1.2      const String& objectName,
 453                char*& p,
 454 kumpf 1.9      String& host)
 455 kumpf 1.2  {
 456                // See if there is a host name (true if it begins with "//"):
 457                // Host is of the from <hostname>-<port> and begins with "//"
 458                // and ends with "/":
 459            
 460                if (p[0] != '/' || p[1] != '/')
 461                {
 462                    return false;
 463                }
 464            
 465                p += 2;
 466            
 467                //----------------------------------------------------------------------
 468 chuck 1.23     // Validate the hostname. A domain is allowed after the hostname.
 469                // Eg. xyz.company.com
 470                // Hostnames must match the following regular expression: 
 471                // ^([A-Za-z][A-Za-z0-9-]*)(\.[A-Za-z][A-Za-z0-9-]*)*$
 472 kumpf 1.2      //----------------------------------------------------------------------
 473            
 474                char* q = p;
 475            
 476 chuck 1.23     Boolean foundDot = true;
 477                while (foundDot == true)
 478                {
 479                    foundDot = false;
 480 kumpf 1.2  
 481 chuck 1.23         if (!isalpha(*q))
 482                        throw MalformedObjectNameException(objectName);
 483 kumpf 1.2  
 484                    q++;
 485 chuck 1.23 
 486                    while (isalnum(*q) || *q == '-')
 487                    {
 488                        q++;
 489                    }
 490            
 491                    if (*q == '.')
 492                    {
 493                        q++;
 494                        foundDot = true;
 495                    }
 496                 }
 497 kumpf 1.2  
 498                // We now expect a port (or default the port).
 499            
 500                if (*q == ':')
 501                {
 502                    q++;
 503                    // Check for a port number:
 504            
 505                    if (!isdigit(*q))
 506 kumpf 1.10             throw MalformedObjectNameException(objectName);
 507 kumpf 1.2          
 508                    while (isdigit(*q))
 509                        q++;
 510            
 511                    // Finally, assign the host name:
 512            
 513                    host.assign(p, q - p);
 514                }
 515                else
 516                {
 517                    host.assign(p, q - p);
 518            
 519                    // Assign the default port number:
 520            
 521                    host.append(":");
 522                    host.append(PEGASUS_CIMOM_DEFAULT_PORT_STRING);
 523                }
 524            
 525                // Check for slash terminating the entire sequence:
 526            
 527                if (*q != '/')
 528 kumpf 1.2      {
 529                    host.clear();
 530 kumpf 1.10         throw MalformedObjectNameException(objectName);
 531 kumpf 1.2      }
 532            
 533                p = ++q;
 534            
 535                return true;
 536            }
 537            
 538 kumpf 1.22 Boolean _parseNamespaceElement(
 539 kumpf 1.2      const String& objectName,
 540                char*& p,
 541 kumpf 1.7      CIMNamespaceName& nameSpace)
 542 kumpf 1.2  {
 543                // If we don't find a valid namespace name followed by a ':', we
 544                // assume we're not looking at a namespace name.
 545            
 546 kumpf 1.7      char* colon = strchr(p, ':');
 547                if (!colon)
 548                {
 549                    return false;
 550                }
 551            
 552 kumpf 1.25     // A ':' as part of a keybinding value should not be interpreted as 
 553                // a namespace delimiter.  Since keybinding pairs follow the first '.'
 554                // in the object path string, the ':' delimiter only counts if it
 555                // appears before the '.'.
 556            
 557                char* dot = strchr(p, '.');
 558                if (dot && (dot < colon))
 559                {
 560                    return false;
 561                }
 562            
 563 kumpf 1.2      //----------------------------------------------------------------------
 564                // Validate the namespace path.  Namespaces must match the following
 565                // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*"
 566                //----------------------------------------------------------------------
 567            
 568 kumpf 1.7      String namespaceName = String(p, colon - p);
 569                if (!CIMNamespaceName::legal(namespaceName))
 570 kumpf 1.2      {
 571 kumpf 1.10         throw MalformedObjectNameException(objectName);
 572 kumpf 1.2      }
 573 kumpf 1.7      nameSpace = namespaceName;
 574 kumpf 1.2  
 575 kumpf 1.7      p = colon+1;
 576 kumpf 1.2      return true;
 577            }
 578            
 579            /**
 580                ATTN: RK - Association classes have keys whose types are
 581                references.  These reference values must be treated specially
 582                in the XML encoding, using the VALUE.REFERENCE tag structure.
 583            
 584                Pegasus had been passing reference values simply as String
 585                values.  For example, EnumerateInstanceNames returned
 586                KEYVALUEs of string type rather than VALUE.REFERENCEs.
 587            
 588                I've modified the XmlReader::getKeyBindingElement() and
 589                XmlWriter::appendInstanceNameElement() methods to read and write
 590                the XML in the proper format.  However, making that change
 591                required that a CIMObjectPath object be able to distinguish
 592                between a key of String type and a key of reference type.
 593            
 594                I've modified the String format of CIMObjectPaths slightly to
 595                allow efficient processing of references whose keys are also
 596                of reference type.  The "official" form uses the same
 597 kumpf 1.2      encoding for key values of String type and of reference type,
 598                and so it would be necessary to retrieve the class definition
 599                and look up the types of the key properties to determine how
 600                to treat the key values.  This is clearly too inefficient for
 601                internal transformations between CIMObjectPaths and String
 602                values.
 603            
 604                The workaround is to encode a 'R' at the beginning of the
 605                value for a key of reference type (before the opening '"').
 606                This allows the parser to know a priori whether the key is of
 607                String or reference type.
 608            
 609                In this example:
 610            
 611                    MyClass.Key1="StringValue",Key2=R"RefClass.KeyA="StringA",KeyB=10"
 612            
 613                Property Key1 of class MyClass is of String type, and so it
 614                gets the usual encoding.  Key2 is a reference property, so
 615                the extra 'R' is inserted before its encoded value.  Note
 616                that this algorithm is recursive, such that RefClass could
 617                include KeyC of reference type, which would also get encoded
 618 kumpf 1.2      with the 'R' notation.
 619            
 620                The toString() method inserts the 'R' to provide symmetry.  A
 621 kumpf 1.16     new CIMKeyBinding type (REFERENCE) has been defined to denote
 622 kumpf 1.2      keys in a CIMObjectPath that are of reference type.  This
 623 kumpf 1.16     CIMKeyBinding type must be used appropriately for
 624 kumpf 1.2      CIMObjectPath::toString() to behave correctly.
 625            
 626                A result of this change is that instances names in the
 627                instance repository will include this extra 'R' character.
 628                Note that for user-facing uses of the String encoding of
 629                instance names (such as might appear in MOF for static
 630                association instances or in the CGI client), this solution
 631                is non-standard and therefore unacceptable.  It is likely
 632                that these points will need to process the more expensive
 633                operation of retrieving the class definition to determine
 634                the key property types.
 635            */
 636 kumpf 1.22 void _parseKeyBindingPairs(
 637 kumpf 1.2      const String& objectName,
 638                char*& p,
 639 kumpf 1.16     Array<CIMKeyBinding>& keyBindings)  
 640 kumpf 1.2  {
 641                // Get the key-value pairs:
 642            
 643                while (*p)
 644                {
 645                    // Get key part:
 646            
 647 kumpf 1.5          char* equalsign = strchr(p, '=');
 648                    if (!equalsign)
 649 kumpf 1.2          {
 650 kumpf 1.10             throw MalformedObjectNameException(objectName);
 651 kumpf 1.2          }
 652            
 653 kumpf 1.5          *equalsign = 0;
 654 kumpf 1.2  
 655 kumpf 1.17         if (!CIMName::legal(p))
 656 kumpf 1.10             throw MalformedObjectNameException(objectName);
 657 kumpf 1.2  
 658 kumpf 1.17         CIMName keyName (p);
 659            
 660 kumpf 1.2          // Get the value part:
 661            
 662                    String valueString;
 663 kumpf 1.5          p = equalsign + 1;
 664 kumpf 1.16         CIMKeyBinding::Type type;
 665 kumpf 1.2  
 666                    if (*p == 'R')
 667                    {
 668                        p++;
 669            
 670 kumpf 1.16             type = CIMKeyBinding::REFERENCE;
 671 kumpf 1.2  
 672                        if (*p++ != '"')
 673 kumpf 1.10                 throw MalformedObjectNameException(objectName);
 674 kumpf 1.2  
 675                        while (*p && *p != '"')
 676                        {
 677                            // ATTN: need to handle special characters here:
 678            
 679                            if (*p == '\\')
 680                                *p++;
 681            
 682                            valueString.append(*p++);
 683                        }
 684            
 685                        if (*p++ != '"')
 686 kumpf 1.10                 throw MalformedObjectNameException(objectName);
 687 kumpf 1.2          }
 688                    else if (*p == '"')
 689                    {
 690                        p++;
 691            
 692 kumpf 1.16             type = CIMKeyBinding::STRING;
 693 kumpf 1.2  
 694                        while (*p && *p != '"')
 695                        {
 696                            // ATTN: need to handle special characters here:
 697            
 698                            if (*p == '\\')
 699                                *p++;
 700            
 701                            valueString.append(*p++);
 702                        }
 703            
 704                        if (*p++ != '"')
 705 kumpf 1.10                 throw MalformedObjectNameException(objectName);
 706 kumpf 1.2          }
 707                    else if (toupper(*p) == 'T' || toupper(*p) == 'F')
 708                    {
 709 kumpf 1.16             type = CIMKeyBinding::BOOLEAN;
 710 kumpf 1.2  
 711                        char* r = p;
 712                        Uint32 n = 0;
 713            
 714                        while (*r && *r != ',')
 715                        {
 716                            *r = toupper(*r);
 717                            r++;
 718                            n++;
 719                        }
 720            
 721                        if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) ||
 722                              ((strncmp(p, "FALSE", n) == 0) && n == 5)))
 723 kumpf 1.10                 throw MalformedObjectNameException(objectName);
 724 kumpf 1.2  
 725                        valueString.assign(p, n);
 726            
 727                        p = p + n;
 728                    }
 729                    else
 730                    {
 731 kumpf 1.16             type = CIMKeyBinding::NUMERIC;
 732 kumpf 1.2  
 733                        char* r = p;
 734                        Uint32 n = 0;
 735            
 736                        while (*r && *r != ',')
 737                        {
 738                            r++;
 739                            n++;
 740                        }
 741            
 742                        Boolean isComma = false;
 743                        if (*r)
 744                        {
 745                            *r = '\0';
 746                            isComma = true;
 747                        }
 748            
 749                        Sint64 x;
 750            
 751                        if (!XmlReader::stringToSignedInteger(p, x))
 752 kumpf 1.10                 throw MalformedObjectNameException(objectName);
 753 kumpf 1.2  
 754                        valueString.assign(p, n);
 755            
 756                        if (isComma)
 757                        {
 758                            *r = ',';
 759                        }
 760            
 761                        p = p + n;
 762                    }
 763            
 764 kumpf 1.17         keyBindings.append(CIMKeyBinding(keyName.getString (), valueString, 
 765                        type));
 766 kumpf 1.2  
 767                    if (*p)
 768                    {
 769                        if (*p++ != ',')
 770                        {
 771 kumpf 1.10                 throw MalformedObjectNameException(objectName);
 772 kumpf 1.2              }
 773                    }
 774                }
 775            
 776                _BubbleSort(keyBindings);
 777            }
 778            
 779 kumpf 1.9  void CIMObjectPath::set(const String& objectName)  
 780 kumpf 1.2  {
 781                clear();
 782            
 783                //--------------------------------------------------------------------------
 784                // We will extract components from an object name. Here is an sample
 785                // object name:
 786                //
 787                //     //atp:9999/root/cimv25:TennisPlayer.first="Patrick",last="Rafter"
 788                //--------------------------------------------------------------------------
 789            
 790                // Convert to a C String first:
 791            
 792 kumpf 1.26     CString pCString = objectName.getCString();
 793                char* p = const_cast<char*>((const char*) pCString);
 794 kumpf 1.2      Boolean gotHost;
 795                Boolean gotNamespace;
 796            
 797                gotHost = _parseHostElement(objectName, p, _rep->_host);
 798                gotNamespace = _parseNamespaceElement(objectName, p, _rep->_nameSpace);
 799            
 800                if (gotHost && !gotNamespace)
 801                {
 802 kumpf 1.10         throw MalformedObjectNameException(objectName);
 803 kumpf 1.2      }
 804            
 805                // Extract the class name:
 806            
 807                char* dot = strchr(p, '.');
 808            
 809                if (!dot)
 810                {
 811                    if (!CIMName::legal(p))
 812                    {
 813 kumpf 1.10             throw MalformedObjectNameException(objectName);
 814 kumpf 1.2          }
 815            
 816                    // ATTN: remove this later: a reference should only be able to hold
 817                    // an instance name.
 818            
 819 kumpf 1.17         _rep->_className = CIMName (p);
 820 kumpf 1.2          return;
 821                }
 822            
 823 kumpf 1.7      String className = String(p, dot - p);
 824                if (!CIMName::legal(className))
 825                {
 826 kumpf 1.10         throw MalformedObjectNameException(objectName);
 827 kumpf 1.7      }
 828                _rep->_className = className;
 829 kumpf 1.2  
 830                // Advance past dot:
 831            
 832                p = dot + 1;
 833            
 834                _parseKeyBindingPairs(objectName, p, _rep->_keyBindings);
 835            }
 836            
 837            CIMObjectPath& CIMObjectPath::operator=(const String& objectName)
 838            {
 839                set(objectName);
 840                return *this;
 841            }
 842            
 843            const String& CIMObjectPath::getHost() const
 844            {
 845                return _rep->_host;
 846            }
 847            
 848            void CIMObjectPath::setHost(const String& host)
 849            {
 850 kumpf 1.2      _rep->_host = host;
 851            }
 852            
 853 kumpf 1.7  const CIMNamespaceName& CIMObjectPath::getNameSpace() const
 854 kumpf 1.2  {
 855                return _rep->_nameSpace;
 856            }
 857            
 858 kumpf 1.7  void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace)
 859 kumpf 1.2  {
 860               _rep->_nameSpace = nameSpace;
 861            }
 862            
 863 kumpf 1.7  const CIMName& CIMObjectPath::getClassName() const
 864 kumpf 1.2  {
 865                return _rep->_className;
 866            }
 867            
 868 kumpf 1.7  void CIMObjectPath::setClassName(const CIMName& className)
 869 kumpf 1.2  {
 870                _rep->_className = className;
 871            }
 872            
 873 kumpf 1.16 const Array<CIMKeyBinding>& CIMObjectPath::getKeyBindings() const
 874 kumpf 1.2  {
 875                return _rep->_keyBindings;
 876            }
 877            
 878 kumpf 1.16 void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings)
 879 kumpf 1.2  {
 880                _rep->_keyBindings = keyBindings;
 881                _BubbleSort(_rep->_keyBindings);
 882            }
 883            
 884 kumpf 1.15 String CIMObjectPath::toString() const
 885 kumpf 1.2  {
 886                String objectName;
 887            
 888                // Get the host:
 889            
 890 kumpf 1.15     if (_rep->_host.size())
 891 kumpf 1.2      {
 892                    objectName = "//";
 893 kumpf 1.13         objectName.append(_rep->_host);
 894                    objectName.append("/");
 895 kumpf 1.2      }
 896            
 897                // Get the namespace (if we have a host name, we must write namespace):
 898            
 899 kumpf 1.7      if (!_rep->_nameSpace.isNull() || _rep->_host.size())
 900 kumpf 1.2      {
 901 kumpf 1.17         objectName.append(_rep->_nameSpace.getString ());
 902 kumpf 1.13         objectName.append(":");
 903 kumpf 1.2      }
 904            
 905                // Get the class name:
 906            
 907 kumpf 1.17     objectName.append(getClassName().getString ());
 908 kumpf 1.2  
 909 kumpf 1.9      //
 910                //  ATTN-CAKG-P2-20020726:  The following condition does not correctly
 911                //  distinguish instanceNames from classNames in every case
 912                //  The instanceName of a singleton instance of a keyless class has no
 913                //  key bindings
 914                //
 915                if (_rep->_keyBindings.size () != 0)
 916 kumpf 1.2      {
 917                    objectName.append('.');
 918            
 919                    // Append each key-value pair:
 920            
 921 kumpf 1.16         const Array<CIMKeyBinding>& keyBindings = getKeyBindings();
 922 kumpf 1.2  
 923                    for (Uint32 i = 0, n = keyBindings.size(); i < n; i++)
 924                    {
 925 kumpf 1.17             objectName.append(keyBindings[i].getName().getString ());
 926 kumpf 1.2              objectName.append('=');
 927            
 928                        const String& value = _escapeSpecialCharacters(
 929                            keyBindings[i].getValue());
 930            
 931 kumpf 1.16             CIMKeyBinding::Type type = keyBindings[i].getType();
 932 kumpf 1.2          
 933 kumpf 1.16             if (type == CIMKeyBinding::REFERENCE)
 934 kumpf 1.2                  objectName.append('R');
 935            
 936 kumpf 1.16             if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
 937 kumpf 1.2                  objectName.append('"');
 938            
 939                        objectName.append(value);
 940            
 941 kumpf 1.16             if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE)
 942 kumpf 1.2                  objectName.append('"');
 943            
 944                        if (i + 1 != n)
 945                            objectName.append(',');
 946                    }
 947                }
 948            
 949                return objectName;
 950            }
 951            
 952 kumpf 1.15 String CIMObjectPath::_toStringCanonical() const
 953 kumpf 1.2  {
 954                CIMObjectPath ref = *this;
 955            
 956                // ATTN-RK-P2-20020510: Need to make hostname and namespace lower case?
 957            
 958 kumpf 1.17     String classNameLower = ref._rep->_className.getString ();
 959 kumpf 1.7      classNameLower.toLower();
 960                ref._rep->_className = classNameLower;
 961 kumpf 1.2  
 962                for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++)
 963                {
 964 kumpf 1.17         String keyBindingNameLower = 
 965                        ref._rep->_keyBindings[i]._rep->_name.getString ();
 966 kumpf 1.7          keyBindingNameLower.toLower();
 967                    ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower;
 968 kumpf 1.2      }
 969            
 970 kumpf 1.12     // ATTN-RK-20020826: Need to sort keys?
 971            
 972 kumpf 1.15     return ref.toString();
 973 kumpf 1.2  }
 974            
 975            Boolean CIMObjectPath::identical(const CIMObjectPath& x) const
 976            {
 977                return
 978                    String::equal(_rep->_host, x._rep->_host) &&
 979 kumpf 1.7          _rep->_nameSpace.equal(x._rep->_nameSpace) &&
 980                    _rep->_className.equal(x._rep->_className) &&
 981 kumpf 1.2          _rep->_keyBindings == x._rep->_keyBindings;
 982            }
 983            
 984            Uint32 CIMObjectPath::makeHashCode() const
 985            {
 986 kumpf 1.12     return HashFunc<String>::hash(_toStringCanonical());
 987 kumpf 1.2  }
 988            
 989            Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y)
 990            {
 991                return x.identical(y);
 992            }
 993            
 994            Boolean operator!=(const CIMObjectPath& x, const CIMObjectPath& y)
 995            {
 996                return !operator==(x, y);
 997            }
 998            
 999 kumpf 1.22 #ifndef PEGASUS_REMOVE_DEPRECATED
1000 kumpf 1.2  PEGASUS_STD(ostream)& operator<<(
1001                PEGASUS_STD(ostream)& os,
1002                const CIMObjectPath& x)
1003            {
1004                return os << x.toString();
1005            }
1006 kumpf 1.22 #endif
1007 chip  1.1  
1008            PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2