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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2