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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2