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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2