version 1.8, 2002/07/30 22:03:00
|
version 1.76.4.3, 2013/06/03 22:35:12
|
|
|
//%///////////////////////////////////////////////////////////////////////////// |
//%LICENSE//////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM, |
// Licensed to The Open Group (TOG) under one or more contributor license |
// The Open Group, Tivoli Systems |
// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with |
|
// this work for additional information regarding copyright ownership. |
|
// Each contributor licenses this file to you under the OpenPegasus Open |
|
// Source License; you may not use this file except in compliance with the |
|
// License. |
// | // |
// Permission is hereby granted, free of charge, to any person obtaining a copy |
// Permission is hereby granted, free of charge, to any person obtaining a |
// of this software and associated documentation files (the "Software"), to |
// copy of this software and associated documentation files (the "Software"), |
// deal in the Software without restriction, including without limitation the |
// to deal in the Software without restriction, including without limitation |
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
// the rights to use, copy, modify, merge, publish, distribute, sublicense, |
// sell copies of the Software, and to permit persons to whom the Software is |
// and/or sell copies of the Software, and to permit persons to whom the |
// furnished to do so, subject to the following conditions: |
// Software is furnished to do so, subject to the following conditions: |
// |
|
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN |
|
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED |
|
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT |
|
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
// | // |
//============================================================================== |
// The above copyright notice and this permission notice shall be included |
|
// in all copies or substantial portions of the Software. |
// | // |
// Author: Mike Brasher (mbrasher@bmc.com) |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
|
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
// | // |
// Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
////////////////////////////////////////////////////////////////////////// |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
#include <Pegasus/Common/Config.h> | #include <Pegasus/Common/Config.h> |
#include <cctype> |
|
#include <cstring> | #include <cstring> |
|
#include <iostream> |
#include "HashTable.h" | #include "HashTable.h" |
#include "CIMObjectPath.h" | #include "CIMObjectPath.h" |
#include "Indentor.h" |
|
#include "CIMName.h" | #include "CIMName.h" |
#include "Destroyer.h" |
#include "CIMValue.h" |
#include "XmlWriter.h" |
|
#include "XmlReader.h" | #include "XmlReader.h" |
#include "Array.h" |
#include <Pegasus/Common/StringConversion.h> |
#include "CIMOMPort.h" |
#include "ArrayInternal.h" |
|
#include "HostLocator.h" |
|
#include "System.h" |
|
#include "CIMKeyBindingRep.h" |
|
#include "CIMObjectPathRep.h" |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
#define PEGASUS_ARRAY_T KeyBinding |
#define PEGASUS_ARRAY_T CIMKeyBinding |
# include "ArrayImpl.h" | # include "ArrayImpl.h" |
#undef PEGASUS_ARRAY_T | #undef PEGASUS_ARRAY_T |
| |
|
|
{ | { |
switch (str[i]) | switch (str[i]) |
{ | { |
case '\n': |
case '\\': |
result += "\\n"; |
result.append("\\\\"); |
break; |
|
|
|
case '\r': |
|
result += "\\r"; |
|
break; |
|
|
|
case '\t': |
|
result += "\\t"; |
|
break; | break; |
| |
case '"': | case '"': |
result += "\\\""; |
result.append("\\\""); |
break; | break; |
| |
default: | default: |
result += str[i]; |
result.append(str[i]); |
} | } |
} | } |
| |
return result; | return result; |
} | } |
| |
static void _BubbleSort(Array<KeyBinding>& x) |
static int _compare(const void* p1, const void* p2) |
{ | { |
Uint32 n = x.size(); |
const CIMKeyBinding* kb1 = (const CIMKeyBinding*)p1; |
|
const CIMKeyBinding* kb2 = (const CIMKeyBinding*)p2; |
| |
if (n < 2) |
return String::compareNoCase( |
return; |
kb1->getName().getString(), |
|
kb2->getName().getString()); |
|
} |
| |
for (Uint32 i = 0; i < n - 1; i++) |
static void _Sort(Array<CIMKeyBinding>& x) |
{ | { |
for (Uint32 j = 0; j < n - 1; j++) |
CIMKeyBinding* data = (CIMKeyBinding*)x.getData(); |
|
Uint32 size = x.size(); |
|
|
|
// |
|
// If the key is a reference, the keys in the reference must also be |
|
// sorted |
|
// |
|
for (Uint32 k = 0; k < size; k++) |
{ | { |
if (String::compareNoCase(x[j].getName(), x[j+1].getName()) > 0) |
CIMKeyBinding& kb = data[k]; |
|
|
|
if (kb.getType() == CIMKeyBinding::REFERENCE) |
{ | { |
KeyBinding t = x[j]; |
CIMObjectPath tmp(kb.getValue()); |
x[j] = x[j+1]; |
Array<CIMKeyBinding> keyBindings = tmp.getKeyBindings(); |
x[j+1] = t; |
_Sort(keyBindings); |
} |
tmp.setKeyBindings(keyBindings); |
|
kb.setValue(tmp.toString()); |
} | } |
} | } |
|
|
|
if (size < 2) |
|
return; |
|
|
|
qsort((void*)data, size, sizeof(CIMKeyBinding), _compare); |
} | } |
| |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
// | // |
// KeyBinding |
// CIMKeyBinding |
// | // |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
| |
class KeyBindingRep |
CIMKeyBinding::CIMKeyBinding() |
{ |
|
public: |
|
KeyBindingRep() |
|
{ | { |
|
_rep = new CIMKeyBindingRep(); |
} | } |
| |
KeyBindingRep(const KeyBindingRep& x) |
CIMKeyBinding::CIMKeyBinding(const CIMKeyBinding& x) |
: _name(x._name), _value(x._value), _type(x._type) |
|
{ | { |
|
_rep = new CIMKeyBindingRep(*x._rep); |
} | } |
| |
KeyBindingRep( |
CIMKeyBinding::CIMKeyBinding( |
const CIMName& name, | const CIMName& name, |
const String& value, | const String& value, |
KeyBinding::Type type) |
Type type) |
: _name(name), _value(value), _type(type) |
|
{ | { |
|
_rep = new CIMKeyBindingRep(name, value, type); |
} | } |
| |
~KeyBindingRep() |
CIMKeyBinding::CIMKeyBinding(const CIMName& name, const CIMValue& value) |
{ | { |
} |
if (value.isArray()) |
|
|
KeyBindingRep& operator=(const KeyBindingRep& x) |
|
{ | { |
if (&x != this) |
throw TypeMismatchException(); |
{ |
|
_name = x._name; |
|
_value = x._value; |
|
_type = x._type; |
|
} |
|
return *this; |
|
} | } |
| |
CIMName _name; |
String kbValue = value.toString(); |
String _value; |
Type kbType; |
KeyBinding::Type _type; |
|
}; |
|
| |
|
switch (value.getType()) |
KeyBinding::KeyBinding() |
|
{ |
|
_rep = new KeyBindingRep(); |
|
} |
|
|
|
KeyBinding::KeyBinding(const KeyBinding& x) |
|
{ | { |
_rep = new KeyBindingRep(*x._rep); |
case CIMTYPE_BOOLEAN: |
|
kbType = BOOLEAN; |
|
break; |
|
case CIMTYPE_CHAR16: |
|
case CIMTYPE_STRING: |
|
case CIMTYPE_DATETIME: |
|
kbType = STRING; |
|
break; |
|
case CIMTYPE_REFERENCE: |
|
kbType = REFERENCE; |
|
break; |
|
// case CIMTYPE_REAL32: |
|
// case CIMTYPE_REAL64: |
|
case CIMTYPE_OBJECT: |
|
case CIMTYPE_INSTANCE: |
|
// From PEP 194: EmbeddedObjects cannot be keys. |
|
throw TypeMismatchException(); |
|
break; |
|
default: |
|
kbType = NUMERIC; |
|
break; |
} | } |
| |
KeyBinding::KeyBinding(const CIMName& name, const String& value, Type type) |
_rep = new CIMKeyBindingRep(name, kbValue, kbType); |
{ |
|
_rep = new KeyBindingRep(name, value, type); |
|
} | } |
| |
KeyBinding::~KeyBinding() |
CIMKeyBinding::~CIMKeyBinding() |
{ | { |
delete _rep; | delete _rep; |
} | } |
| |
KeyBinding& KeyBinding::operator=(const KeyBinding& x) |
CIMKeyBinding& CIMKeyBinding::operator=(const CIMKeyBinding& x) |
{ | { |
*_rep = *x._rep; | *_rep = *x._rep; |
return *this; | return *this; |
} | } |
| |
const CIMName& KeyBinding::getName() const |
const CIMName& CIMKeyBinding::getName() const |
{ | { |
return _rep->_name; | return _rep->_name; |
} | } |
| |
void KeyBinding::setName(const CIMName& name) |
void CIMKeyBinding::setName(const CIMName& name) |
{ | { |
_rep->_name = name; | _rep->_name = name; |
} | } |
| |
const String& KeyBinding::getValue() const |
const String& CIMKeyBinding::getValue() const |
{ | { |
return _rep->_value; | return _rep->_value; |
} | } |
| |
void KeyBinding::setValue(const String& value) |
void CIMKeyBinding::setValue(const String& value) |
{ | { |
_rep->_value = value; | _rep->_value = value; |
} | } |
| |
KeyBinding::Type KeyBinding::getType() const |
CIMKeyBinding::Type CIMKeyBinding::getType() const |
{ | { |
return _rep->_type; | return _rep->_type; |
} | } |
| |
void KeyBinding::setType(KeyBinding::Type type) |
void CIMKeyBinding::setType(CIMKeyBinding::Type type) |
{ | { |
_rep->_type = type; | _rep->_type = type; |
} | } |
| |
const char* KeyBinding::typeToString(KeyBinding::Type type) |
Boolean CIMKeyBinding::equal(CIMValue value) |
{ | { |
switch (type) |
if (value.isArray()) |
{ | { |
case KeyBinding::BOOLEAN: |
return false; |
return "boolean"; |
} |
|
|
case KeyBinding::STRING: |
|
return "string"; |
|
| |
case KeyBinding::NUMERIC: |
CIMValue kbValue; |
return "numeric"; |
|
| |
case KeyBinding::REFERENCE: |
try |
default: |
{ |
PEGASUS_ASSERT(false); |
switch (value.getType()) |
|
{ |
|
case CIMTYPE_CHAR16: |
|
if (getType() != STRING) return false; |
|
kbValue.set(getValue()[0]); |
|
break; |
|
case CIMTYPE_DATETIME: |
|
if (getType() != STRING) return false; |
|
kbValue.set(CIMDateTime(getValue())); |
|
break; |
|
case CIMTYPE_STRING: |
|
if (getType() != STRING) return false; |
|
kbValue.set(getValue()); |
|
break; |
|
case CIMTYPE_REFERENCE: |
|
if (getType() != REFERENCE) return false; |
|
kbValue.set(CIMObjectPath(getValue())); |
|
break; |
|
case CIMTYPE_BOOLEAN: |
|
if (getType() != BOOLEAN) return false; |
|
kbValue = XmlReader::stringToValue(0, getValue().getCString(), |
|
value.getType()); |
|
break; |
|
// case CIMTYPE_REAL32: |
|
// case CIMTYPE_REAL64: |
|
case CIMTYPE_OBJECT: |
|
case CIMTYPE_INSTANCE: |
|
// From PEP 194: EmbeddedObjects cannot be keys. |
|
return false; |
|
default: // Numerics |
|
if (getType() != NUMERIC) return false; |
|
kbValue = XmlReader::stringToValue(0, getValue().getCString(), |
|
value.getType()); |
|
break; |
} | } |
|
|
return "unknown"; |
|
} | } |
|
catch (Exception&) |
Boolean operator==(const KeyBinding& x, const KeyBinding& y) |
|
{ | { |
return |
return false; |
x.getName().equal(y.getName()) && |
|
String::equal(x.getValue(), y.getValue()) && |
|
x.getType() == y.getType(); |
|
} | } |
| |
|
return value.equal(kbValue); |
|
} |
| |
//////////////////////////////////////////////////////////////////////////////// |
Boolean operator==(const CIMKeyBinding& x, const CIMKeyBinding& y) |
// |
|
// CIMObjectPath |
|
// |
|
//////////////////////////////////////////////////////////////////////////////// |
|
|
|
class CIMObjectPathRep |
|
{ | { |
public: |
// Check that the names and types match |
CIMObjectPathRep() |
if (!(x.getName().equal(y.getName())) || |
|
!(x.getType() == y.getType())) |
{ | { |
|
return false; |
} | } |
| |
CIMObjectPathRep(const CIMObjectPathRep& x) |
switch (x.getType()) |
: _host(x._host), _nameSpace(x._nameSpace), |
|
_className(x._className), _keyBindings(x._keyBindings) |
|
{ | { |
|
case CIMKeyBinding::REFERENCE: |
|
try |
|
{ |
|
// References should be compared as CIMObjectPaths |
|
return (CIMObjectPath(x.getValue()) == CIMObjectPath(y.getValue())); |
} | } |
|
catch (Exception&) |
CIMObjectPathRep( |
|
const String& host, |
|
const CIMNamespaceName& nameSpace, |
|
const CIMName& className, |
|
const Array<KeyBinding>& keyBindings) |
|
: _host(host), _nameSpace(nameSpace), |
|
_className(className), _keyBindings(keyBindings) |
|
{ | { |
|
// If CIMObjectPath parsing fails, just compare strings |
|
return String::equal(x.getValue(), y.getValue()); |
} | } |
|
case CIMKeyBinding::BOOLEAN: |
~CIMObjectPathRep() |
// Case-insensitive comparison is sufficient for booleans |
|
return String::equalNoCase(x.getValue(), y.getValue()); |
|
case CIMKeyBinding::NUMERIC: |
|
// Note: This comparison assumes XML syntax for integers |
|
// First try comparing as unsigned integers |
|
{ |
|
Uint64 xValue; |
|
Uint64 yValue; |
|
if (StringConversion::stringToUnsignedInteger( |
|
x.getValue().getCString(), xValue) && |
|
StringConversion::stringToUnsignedInteger( |
|
y.getValue().getCString(), yValue)) |
{ | { |
|
return (xValue == yValue); |
} | } |
|
} |
CIMObjectPathRep& operator=(const CIMObjectPathRep& x) |
// Next try comparing as signed integers |
{ | { |
if (&x != this) |
Sint64 xValue; |
|
Sint64 yValue; |
|
if (StringConversion::stringToSignedInteger( |
|
x.getValue().getCString(), xValue) && |
|
StringConversion::stringToSignedInteger( |
|
y.getValue().getCString(), yValue)) |
{ | { |
_host = x._host; |
return (xValue == yValue); |
_nameSpace = x._nameSpace; |
|
_className = x._className; |
|
_keyBindings = x._keyBindings; |
|
} | } |
return *this; |
} |
|
// Note: Keys may not be real values, so don't try comparing as reals |
|
// We couldn't parse the numbers, so just compare the strings |
|
return String::equal(x.getValue(), y.getValue()); |
|
default: // CIMKeyBinding::STRING |
|
return String::equal(x.getValue(), y.getValue()); |
} | } |
| |
|
PEGASUS_UNREACHABLE(return false;) |
|
} |
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////// |
// | // |
// Contains port as well (e.g., myhost:1234). |
// CIMObjectPath |
// | // |
String _host; |
//////////////////////////////////////////////////////////////////////////////// |
| |
CIMNamespaceName _nameSpace; |
template<class REP> |
CIMName _className; |
inline void Ref(REP* rep) |
Array<KeyBinding> _keyBindings; |
{ |
}; |
rep->_refCounter++; |
|
} |
| |
|
template<class REP> |
|
inline void Unref(REP* rep) |
|
{ |
|
if (rep->_refCounter.decAndTestIfZero()) |
|
delete rep; |
|
} |
| |
CIMObjectPath::CIMObjectPath() | CIMObjectPath::CIMObjectPath() |
{ | { |
|
|
| |
CIMObjectPath::CIMObjectPath(const CIMObjectPath& x) | CIMObjectPath::CIMObjectPath(const CIMObjectPath& x) |
{ | { |
_rep = new CIMObjectPathRep(*x._rep); |
_rep = x._rep; |
|
Ref(_rep); |
} | } |
| |
CIMObjectPath::CIMObjectPath(const String& objectName) | CIMObjectPath::CIMObjectPath(const String& objectName) |
|
|
CIMObjectPath tmpRef; | CIMObjectPath tmpRef; |
tmpRef.set(objectName); | tmpRef.set(objectName); |
| |
_rep = new CIMObjectPathRep(*tmpRef._rep); |
_rep = tmpRef._rep; |
} |
Ref(_rep); |
|
|
CIMObjectPath::CIMObjectPath(const char* objectName) |
|
{ |
|
// Test the objectName out to see if we get an exception |
|
CIMObjectPath tmpRef; |
|
tmpRef.set(objectName); |
|
|
|
_rep = new CIMObjectPathRep(*tmpRef._rep); |
|
} | } |
| |
CIMObjectPath::CIMObjectPath( | CIMObjectPath::CIMObjectPath( |
const String& host, | const String& host, |
const CIMNamespaceName& nameSpace, | const CIMNamespaceName& nameSpace, |
const CIMName& className, | const CIMName& className, |
const Array<KeyBinding>& keyBindings) |
const Array<CIMKeyBinding>& keyBindings) |
{ | { |
// Test the objectName out to see if we get an exception | // Test the objectName out to see if we get an exception |
CIMObjectPath tmpRef; | CIMObjectPath tmpRef; |
tmpRef.set(host, nameSpace, className, keyBindings); | tmpRef.set(host, nameSpace, className, keyBindings); |
|
_rep = tmpRef._rep; |
_rep = new CIMObjectPathRep(*tmpRef._rep); |
Ref(_rep); |
} | } |
| |
CIMObjectPath::~CIMObjectPath() | CIMObjectPath::~CIMObjectPath() |
{ | { |
delete _rep; |
Unref(_rep); |
} | } |
| |
CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x) | CIMObjectPath& CIMObjectPath::operator=(const CIMObjectPath& x) |
{ | { |
*_rep = *x._rep; |
if (x._rep != _rep) |
|
{ |
|
Unref(_rep); |
|
_rep = x._rep; |
|
Ref(_rep); |
|
} |
return *this; | return *this; |
} | } |
| |
|
static inline CIMObjectPathRep* _copyOnWriteCIMObjectPathRep( |
|
CIMObjectPathRep* rep) |
|
{ |
|
if (rep->_refCounter.get() > 1) |
|
{ |
|
CIMObjectPathRep* tmpRep= new CIMObjectPathRep(*rep); |
|
Unref(rep); |
|
return tmpRep; |
|
} |
|
else |
|
{ |
|
return rep; |
|
} |
|
} |
|
|
void CIMObjectPath::clear() | void CIMObjectPath::clear() |
{ | { |
|
// If there is more than one reference |
|
// remove reference and get a new shiny empty representation |
|
if (_rep->_refCounter.get() > 1) |
|
{ |
|
Unref(_rep); |
|
_rep = new CIMObjectPathRep(); |
|
} |
|
else |
|
{ |
|
// If there is only one reference |
|
// no need to copy the data, we own it |
|
// just clear the fields |
_rep->_host.clear(); | _rep->_host.clear(); |
_rep->_nameSpace.clear(); | _rep->_nameSpace.clear(); |
_rep->_className.clear(); | _rep->_className.clear(); |
_rep->_keyBindings.clear(); | _rep->_keyBindings.clear(); |
} | } |
|
} |
| |
void CIMObjectPath::set( | void CIMObjectPath::set( |
const String& host, | const String& host, |
const CIMNamespaceName& nameSpace, | const CIMNamespaceName& nameSpace, |
const CIMName& className, | const CIMName& className, |
const Array<KeyBinding>& keyBindings) |
const Array<CIMKeyBinding>& keyBindings) |
|
{ |
|
if ((host != String::EMPTY) && !CIMObjectPathRep::isValidHostname(host)) |
{ | { |
setHost(host); |
MessageLoaderParms mlParms( |
setNameSpace(nameSpace); |
"Common.CIMObjectPath.INVALID_HOSTNAME", |
setClassName(className); |
"$0, reason:\"invalid hostname\"", |
setKeyBindings(keyBindings); |
host); |
|
|
|
throw MalformedObjectNameException(mlParms); |
|
} |
|
|
|
_rep = _copyOnWriteCIMObjectPathRep(_rep); |
|
|
|
_rep->_host.assign(host); |
|
_rep->_nameSpace = nameSpace; |
|
_rep->_className = className; |
|
_rep->_keyBindings = keyBindings; |
|
_Sort(_rep->_keyBindings); |
} | } |
| |
Boolean CIMObjectPath::_parseHostElement( |
Boolean _parseHostElement( |
const String& objectName, | const String& objectName, |
char*& p, | char*& p, |
String& host) throw(IllformedObjectName) |
String& host) |
{ | { |
// See if there is a host name (true if it begins with "//"): | // See if there is a host name (true if it begins with "//"): |
// Host is of the from <hostname>-<port> and begins with "//" |
// Host is of the form <hostname>:<port> and begins with "//" |
// and ends with "/": | // and ends with "/": |
| |
if (p[0] != '/' || p[1] != '/') | if (p[0] != '/' || p[1] != '/') |
|
|
| |
p += 2; | p += 2; |
| |
//---------------------------------------------------------------------- |
char* slash = strchr(p, '/'); |
// Validate the hostname. Hostnames must match the following |
if (!slash) |
// regular expression: "[A-Za-z][A-Za-z0-9-]*" |
|
//---------------------------------------------------------------------- |
|
|
|
char* q = p; |
|
|
|
if (!isalpha(*q)) |
|
throw IllformedObjectName(objectName); |
|
|
|
q++; |
|
|
|
while (isalnum(*q) || *q == '-') |
|
q++; |
|
|
|
// We now expect a port (or default the port). |
|
|
|
if (*q == ':') |
|
{ |
|
q++; |
|
// Check for a port number: |
|
|
|
if (!isdigit(*q)) |
|
throw IllformedObjectName(objectName); |
|
|
|
while (isdigit(*q)) |
|
q++; |
|
|
|
// Finally, assign the host name: |
|
|
|
host.assign(p, q - p); |
|
} |
|
else |
|
{ | { |
host.assign(p, q - p); |
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.MISSING_SLASH_AFTER_HOST", |
// Assign the default port number: |
"$0, reason:\"missing slash after hostname\"", |
|
objectName); |
host.append(":"); |
throw MalformedObjectNameException(mlParms); |
host.append(PEGASUS_CIMOM_DEFAULT_PORT_STRING); |
|
} | } |
| |
// Check for slash terminating the entire sequence: |
String hostname = String(p, (Uint32)(slash - p)); |
|
if (!CIMObjectPathRep::isValidHostname(hostname)) |
if (*q != '/') |
|
{ | { |
host.clear(); |
MessageLoaderParms mlParms( |
throw IllformedObjectName(objectName); |
"Common.CIMObjectPath.INVALID_HOSTNAME", |
|
"$0, reason:\"invalid hostname\"", |
|
objectName); |
|
throw MalformedObjectNameException(mlParms); |
} | } |
|
host = hostname; |
| |
p = ++q; |
// Do not step past the '/'; it will be consumed by the namespace parser |
|
p = slash; |
| |
return true; | return true; |
} | } |
| |
Boolean CIMObjectPath::_parseNamespaceElement( |
Boolean _parseNamespaceElement( |
const String& objectName, | const String& objectName, |
char*& p, | char*& p, |
CIMNamespaceName& nameSpace) | CIMNamespaceName& nameSpace) |
|
|
return false; | return false; |
} | } |
| |
|
// A ':' as part of a keybinding value should not be interpreted as |
|
// a namespace delimiter. Since keybinding pairs follow the first '.' |
|
// in the object path string, the ':' delimiter only counts if it |
|
// appears before the '.'. |
|
|
|
char* dot = strchr(p, '.'); |
|
if (dot && (dot < colon)) |
|
{ |
|
return false; |
|
} |
|
|
//---------------------------------------------------------------------- | //---------------------------------------------------------------------- |
// Validate the namespace path. Namespaces must match the following | // Validate the namespace path. Namespaces must match the following |
// regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*" | // regular expression: "[A-Za-z_]+(/[A-Za-z_]+)*" |
//---------------------------------------------------------------------- | //---------------------------------------------------------------------- |
| |
String namespaceName = String(p, colon - p); |
String namespaceName = String(p, (Uint32)(colon - p)); |
if (!CIMNamespaceName::legal(namespaceName)) | if (!CIMNamespaceName::legal(namespaceName)) |
{ | { |
throw IllformedObjectName(objectName); |
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_NAMESPACE", |
|
"$0, reason:\"invalid namespace name\"", |
|
objectName); |
|
throw MalformedObjectNameException(mlParms); |
} | } |
nameSpace = namespaceName; | nameSpace = namespaceName; |
| |
|
|
} | } |
| |
/** | /** |
ATTN: RK - Association classes have keys whose types are |
ATTN-RK: The DMTF specification for the string form of an |
references. These reference values must be treated specially |
object path makes it impossible for a parser to distinguish |
in the XML encoding, using the VALUE.REFERENCE tag structure. |
between a key values of String type and Reference type. |
|
|
Pegasus had been passing reference values simply as String |
Given the ambiguity, this implementation takes a guess at the |
values. For example, EnumerateInstanceNames returned |
type of a quoted key value. If the value can be parsed into |
KEYVALUEs of string type rather than VALUE.REFERENCEs. |
a CIMObjectPath with at least one key binding, the type is |
|
set to REFERENCE. Otherwise, the type is set to STRING. |
I've modified the XmlReader::getKeyBindingElement() and |
Note: This algorithm appears to be in line with what the Sun |
XmlWriter::appendInstanceNameElement() methods to read and write |
WBEM Services implementation does. |
the XML in the proper format. However, making that change |
|
required that a CIMObjectPath object be able to distinguish |
To be totally correct, it would be necessary to retrieve the |
between a key of String type and a key of reference type. |
class definition and look up the types of the key properties |
|
to determine how to interpret the key values. This is clearly |
I've modified the String format of CIMObjectPaths slightly to |
too inefficient for internal transformations between |
allow efficient processing of references whose keys are also |
CIMObjectPaths and String values. |
of reference type. The "official" form uses the same |
|
encoding for key values of String type and of reference type, |
|
and so it would be necessary to retrieve the class definition |
|
and look up the types of the key properties to determine how |
|
to treat the key values. This is clearly too inefficient for |
|
internal transformations between CIMObjectPaths and String |
|
values. |
|
|
|
The workaround is to encode a 'R' at the beginning of the |
|
value for a key of reference type (before the opening '"'). |
|
This allows the parser to know a priori whether the key is of |
|
String or reference type. |
|
|
|
In this example: |
|
|
|
MyClass.Key1="StringValue",Key2=R"RefClass.KeyA="StringA",KeyB=10" |
|
|
|
Property Key1 of class MyClass is of String type, and so it |
|
gets the usual encoding. Key2 is a reference property, so |
|
the extra 'R' is inserted before its encoded value. Note |
|
that this algorithm is recursive, such that RefClass could |
|
include KeyC of reference type, which would also get encoded |
|
with the 'R' notation. |
|
|
|
The toString() method inserts the 'R' to provide symmetry. A |
|
new KeyBinding type (REFERENCE) has been defined to denote |
|
keys in a CIMObjectPath that are of reference type. This |
|
KeyBinding type must be used appropriately for |
|
CIMObjectPath::toString() to behave correctly. |
|
|
|
A result of this change is that instances names in the |
|
instance repository will include this extra 'R' character. |
|
Note that for user-facing uses of the String encoding of |
|
instance names (such as might appear in MOF for static |
|
association instances or in the CGI client), this solution |
|
is non-standard and therefore unacceptable. It is likely |
|
that these points will need to process the more expensive |
|
operation of retrieving the class definition to determine |
|
the key property types. |
|
*/ | */ |
void CIMObjectPath::_parseKeyBindingPairs( |
void _parseKeyBindingPairs( |
const String& objectName, | const String& objectName, |
char*& p, | char*& p, |
Array<KeyBinding>& keyBindings) throw(IllformedObjectName) |
Array<CIMKeyBinding>& keyBindings) |
{ | { |
// Get the key-value pairs: | // Get the key-value pairs: |
| |
|
|
char* equalsign = strchr(p, '='); | char* equalsign = strchr(p, '='); |
if (!equalsign) | if (!equalsign) |
{ | { |
throw IllformedObjectName(objectName); |
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_KEYVALUEPAIR", |
|
"$0, reason:\"invalid key-value pair, missing equal sign\"", |
|
objectName); |
|
throw MalformedObjectNameException(mlParms); |
} | } |
| |
*equalsign = 0; | *equalsign = 0; |
CIMName keyString(p); |
|
| |
if (!CIMName::legal(keyString)) |
if (!CIMName::legal(p)) |
throw IllformedObjectName(objectName); |
{ |
|
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_KEYNAME", |
|
"$0, reason:\"invalid key-value pair, invalid key name:$1\"", |
|
objectName, |
|
p); |
|
throw MalformedObjectNameException(mlParms); |
|
} |
|
|
|
CIMName keyName (p); |
| |
// Get the value part: | // Get the value part: |
| |
String valueString; | String valueString; |
p = equalsign + 1; | p = equalsign + 1; |
KeyBinding::Type type; |
CIMKeyBinding::Type type; |
| |
if (*p == 'R') |
if (*p == '"') |
{ | { |
p++; |
// Could be CIMKeyBinding::STRING or CIMKeyBinding::REFERENCE |
| |
type = KeyBinding::REFERENCE; |
p++; |
| |
if (*p++ != '"') |
Buffer keyValueUTF8(128); |
throw IllformedObjectName(objectName); |
|
| |
while (*p && *p != '"') | while (*p && *p != '"') |
{ | { |
// ATTN: need to handle special characters here: |
|
|
|
if (*p == '\\') | if (*p == '\\') |
*p++; |
|
|
|
valueString.append(*p++); |
|
} |
|
|
|
if (*p++ != '"') |
|
throw IllformedObjectName(objectName); |
|
} |
|
else if (*p == '"') |
|
{ | { |
p++; | p++; |
| |
type = KeyBinding::STRING; |
if ((*p != '\\') && (*p != '"')) |
|
|
while (*p && *p != '"') |
|
{ | { |
// ATTN: need to handle special characters here: |
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_KEYVALUE", |
if (*p == '\\') |
"$0, reason:\"invalid key-value pair, " |
*p++; |
"malformed value\"", |
|
objectName); |
|
throw MalformedObjectNameException(mlParms); |
|
} |
|
} |
| |
valueString.append(*p++); |
keyValueUTF8.append(*p++); |
} | } |
| |
if (*p++ != '"') | if (*p++ != '"') |
throw IllformedObjectName(objectName); |
{ |
|
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_KEYVALUEPAIR_MISSINGQUOTE", |
|
"$0, reason:\"invalid key-value pair, " |
|
"missing quote in key value\"", |
|
objectName); |
|
throw MalformedObjectNameException(mlParms); |
|
} |
|
|
|
// Convert the UTF-8 value to a UTF-16 String |
|
|
|
valueString.assign( |
|
(const char*)keyValueUTF8.getData(), |
|
keyValueUTF8.size()); |
|
|
|
/* |
|
Guess at the type of this quoted key value. If the value |
|
can be parsed into a CIMObjectPath with at least one key |
|
binding, the type is assumed to be a REFERENCE. Otherwise, |
|
the type is set to STRING. (See method header for details.) |
|
*/ |
|
type = CIMKeyBinding::STRING; |
|
|
|
/* Performance shortcut will check for |
|
equal sign instead of doing the full |
|
CIMObjectPath creation and exception handling |
|
*/ |
|
if (strchr(keyValueUTF8.getData(), '=')) |
|
{ |
|
// found an equal sign, high probability for a reference |
|
try |
|
{ |
|
CIMObjectPath testForPath(valueString); |
|
if (testForPath.getKeyBindings().size() > 0) |
|
{ |
|
// We've found a reference value! |
|
type = CIMKeyBinding::REFERENCE; |
|
} |
|
} |
|
catch (const Exception &) |
|
{ |
|
// Not a reference value; leave type as STRING |
|
} |
|
} |
} | } |
else if (toupper(*p) == 'T' || toupper(*p) == 'F') | else if (toupper(*p) == 'T' || toupper(*p) == 'F') |
{ | { |
type = KeyBinding::BOOLEAN; |
type = CIMKeyBinding::BOOLEAN; |
| |
char* r = p; | char* r = p; |
Uint32 n = 0; | Uint32 n = 0; |
|
|
| |
if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) || | if (!(((strncmp(p, "TRUE", n) == 0) && n == 4) || |
((strncmp(p, "FALSE", n) == 0) && n == 5))) | ((strncmp(p, "FALSE", n) == 0) && n == 5))) |
throw IllformedObjectName(objectName); |
{ |
|
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_BOOLVALUE", |
|
"$0, reason:\"invalid key-value pair, " |
|
"value should be TRUE or FALSE\"", |
|
objectName); |
|
throw MalformedObjectNameException(mlParms); |
|
} |
| |
valueString.assign(p, n); | valueString.assign(p, n); |
| |
|
|
} | } |
else | else |
{ | { |
type = KeyBinding::NUMERIC; |
type = CIMKeyBinding::NUMERIC; |
| |
char* r = p; | char* r = p; |
Uint32 n = 0; | Uint32 n = 0; |
|
|
isComma = true; | isComma = true; |
} | } |
| |
|
if (*p == '-') |
|
{ |
Sint64 x; | Sint64 x; |
|
if (!StringConversion::stringToSignedInteger(p, x)) |
if (!XmlReader::stringToSignedInteger(p, x)) |
{ |
throw IllformedObjectName(objectName); |
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_NEGATIVNUMBER_VALUE", |
|
"$0, reason:\"invalid key-value pair, " |
|
"invalid negative number value $1\"", |
|
objectName, |
|
p); |
|
throw MalformedObjectNameException(mlParms); |
|
} |
|
} |
|
else |
|
{ |
|
Uint64 x; |
|
if (!StringConversion::stringToUnsignedInteger(p, x)) |
|
{ |
|
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_NEGATIVNUMBER_VALUE", |
|
"$0, reason:\"invalid key-value pair, " |
|
"invalid number value $1\"", |
|
objectName, |
|
p); |
|
throw MalformedObjectNameException(mlParms); |
|
} |
|
} |
| |
valueString.assign(p, n); | valueString.assign(p, n); |
| |
|
|
p = p + n; | p = p + n; |
} | } |
| |
keyBindings.append(KeyBinding(keyString, valueString, type)); |
keyBindings.append(CIMKeyBinding(keyName.getString (), valueString, |
|
type)); |
| |
if (*p) | if (*p) |
{ | { |
if (*p++ != ',') | if (*p++ != ',') |
{ | { |
throw IllformedObjectName(objectName); |
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_KEYVALUEPAIR_MISSCOMMA", |
|
"$0, reason:\"invalid key-value pair, " |
|
"next key-value pair has to start with comma\"", |
|
objectName); |
|
throw MalformedObjectNameException(mlParms); |
} | } |
} | } |
} | } |
| |
_BubbleSort(keyBindings); |
_Sort(keyBindings); |
} | } |
| |
void CIMObjectPath::set(const String& objectName) throw(IllformedObjectName) |
void CIMObjectPath::set(const String& objectName) |
{ | { |
|
// the clear automatically ensures |
|
// we have our own copy of the representation |
clear(); | clear(); |
| |
//-------------------------------------------------------------------------- | //-------------------------------------------------------------------------- |
|
|
| |
// Convert to a C String first: | // Convert to a C String first: |
| |
char* p = objectName.allocateCString(); |
CString pCString = objectName.getCString(); |
ArrayDestroyer<char> destroyer(p); |
char* p = const_cast<char*>((const char*) pCString); |
Boolean gotHost; | Boolean gotHost; |
Boolean gotNamespace; | Boolean gotNamespace; |
| |
|
|
| |
if (gotHost && !gotNamespace) | if (gotHost && !gotNamespace) |
{ | { |
throw IllformedObjectName(objectName); |
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.MISSING_NAMESPACE", |
|
"$0, reason:\"host specified, missing namespace\"", |
|
objectName); |
|
throw MalformedObjectNameException(mlParms); |
} | } |
| |
// Extract the class name: | // Extract the class name: |
|
|
{ | { |
if (!CIMName::legal(p)) | if (!CIMName::legal(p)) |
{ | { |
throw IllformedObjectName(objectName); |
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_CLASSNAME", |
|
"$0, reason:\"class name $1 not a legal CIM name\"", |
|
objectName, |
|
p); |
|
throw MalformedObjectNameException(mlParms); |
} | } |
| |
// ATTN: remove this later: a reference should only be able to hold | // ATTN: remove this later: a reference should only be able to hold |
// an instance name. | // an instance name. |
| |
_rep->_className = p; |
_rep->_className = CIMName (p); |
return; | return; |
} | } |
| |
String className = String(p, dot - p); |
String className = String(p, (Uint32)(dot - p)); |
if (!CIMName::legal(className)) | if (!CIMName::legal(className)) |
{ | { |
throw IllformedObjectName(objectName); |
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_CLASSNAME", |
|
"$0, reason:\"class name $1 not a legal CIM name\"", |
|
objectName, |
|
className); |
|
throw MalformedObjectNameException(mlParms); |
} | } |
_rep->_className = className; | _rep->_className = className; |
| |
|
|
| |
CIMObjectPath& CIMObjectPath::operator=(const String& objectName) | CIMObjectPath& CIMObjectPath::operator=(const String& objectName) |
{ | { |
set(objectName); |
// set will call clear, which will cause copyOnWrite if necessary |
return *this; |
|
} |
|
|
|
CIMObjectPath& CIMObjectPath::operator=(const char* objectName) |
|
{ |
|
set(objectName); | set(objectName); |
return *this; | return *this; |
} | } |
|
|
| |
void CIMObjectPath::setHost(const String& host) | void CIMObjectPath::setHost(const String& host) |
{ | { |
|
if ((host != String::EMPTY) && |
|
(host != System::getHostName()) && |
|
!CIMObjectPathRep::isValidHostname(host)) |
|
{ |
|
MessageLoaderParms mlParms( |
|
"Common.CIMObjectPath.INVALID_HOSTNAME", |
|
"$0, reason:\"invalid hostname\"", |
|
host); |
|
throw MalformedObjectNameException(mlParms); |
|
} |
|
_rep = _copyOnWriteCIMObjectPathRep(_rep); |
|
|
_rep->_host = host; | _rep->_host = host; |
} | } |
| |
|
|
| |
void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace) | void CIMObjectPath::setNameSpace(const CIMNamespaceName& nameSpace) |
{ | { |
|
_rep = _copyOnWriteCIMObjectPathRep(_rep); |
_rep->_nameSpace = nameSpace; | _rep->_nameSpace = nameSpace; |
} | } |
| |
|
|
| |
void CIMObjectPath::setClassName(const CIMName& className) | void CIMObjectPath::setClassName(const CIMName& className) |
{ | { |
|
_rep = _copyOnWriteCIMObjectPathRep(_rep); |
_rep->_className = className; | _rep->_className = className; |
} | } |
| |
const Array<KeyBinding>& CIMObjectPath::getKeyBindings() const |
const Array<CIMKeyBinding>& CIMObjectPath::getKeyBindings() const |
{ | { |
return _rep->_keyBindings; | return _rep->_keyBindings; |
} | } |
| |
void CIMObjectPath::setKeyBindings(const Array<KeyBinding>& keyBindings) |
void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings) |
{ | { |
|
_rep = _copyOnWriteCIMObjectPathRep(_rep); |
_rep->_keyBindings = keyBindings; | _rep->_keyBindings = keyBindings; |
_BubbleSort(_rep->_keyBindings); |
_Sort(_rep->_keyBindings); |
} | } |
| |
String CIMObjectPath::toString(Boolean includeHost) const |
String CIMObjectPath::toString() const |
{ | { |
String objectName; | String objectName; |
| |
// Get the host: | // Get the host: |
| |
if (_rep->_host.size() && includeHost) |
if (_rep->_host.size()) |
{ | { |
objectName = "//"; | objectName = "//"; |
objectName += _rep->_host; |
objectName.append(_rep->_host); |
objectName += "/"; |
objectName.append("/"); |
} | } |
| |
// Get the namespace (if we have a host name, we must write namespace): | // Get the namespace (if we have a host name, we must write namespace): |
| |
if (!_rep->_nameSpace.isNull() || _rep->_host.size()) | if (!_rep->_nameSpace.isNull() || _rep->_host.size()) |
{ | { |
objectName += _rep->_nameSpace; |
objectName.append(_rep->_nameSpace.getString ()); |
objectName += ":"; |
objectName.append(":"); |
} | } |
| |
// Get the class name: | // Get the class name: |
| |
objectName.append(getClassName()); |
objectName.append(getClassName().getString ()); |
| |
if (isInstanceName()) |
// |
|
// ATTN-CAKG-P2-20020726: The following condition does not correctly |
|
// distinguish instanceNames from classNames in every case |
|
// The instanceName of a singleton instance of a keyless class has no |
|
// key bindings. See BUG_3302 |
|
// |
|
if (_rep->_keyBindings.size () != 0) |
{ | { |
objectName.append('.'); | objectName.append('.'); |
| |
// Append each key-value pair: | // Append each key-value pair: |
| |
const Array<KeyBinding>& keyBindings = getKeyBindings(); |
const Array<CIMKeyBinding>& keyBindings = getKeyBindings(); |
| |
for (Uint32 i = 0, n = keyBindings.size(); i < n; i++) | for (Uint32 i = 0, n = keyBindings.size(); i < n; i++) |
{ | { |
objectName.append(keyBindings[i].getName()); |
objectName.append(keyBindings[i].getName().getString ()); |
objectName.append('='); | objectName.append('='); |
| |
const String& value = _escapeSpecialCharacters( | const String& value = _escapeSpecialCharacters( |
keyBindings[i].getValue()); | keyBindings[i].getValue()); |
| |
KeyBinding::Type type = keyBindings[i].getType(); |
CIMKeyBinding::Type type = keyBindings[i].getType(); |
| |
if (type == KeyBinding::REFERENCE) |
if (type == CIMKeyBinding::STRING || |
objectName.append('R'); |
type == CIMKeyBinding::REFERENCE) |
|
|
if (type == KeyBinding::STRING || type == KeyBinding::REFERENCE) |
|
objectName.append('"'); | objectName.append('"'); |
| |
objectName.append(value); | objectName.append(value); |
| |
if (type == KeyBinding::STRING || type == KeyBinding::REFERENCE) |
if (type == CIMKeyBinding::STRING || |
|
type == CIMKeyBinding::REFERENCE) |
objectName.append('"'); | objectName.append('"'); |
| |
if (i + 1 != n) | if (i + 1 != n) |
|
|
return objectName; | return objectName; |
} | } |
| |
String CIMObjectPath::toStringCanonical(Boolean includeHost) const |
String CIMObjectPath::_toStringCanonical() const |
{ | { |
CIMObjectPath ref = *this; |
CIMObjectPath ref; |
|
*ref._rep = *this->_rep; |
|
|
|
// Normalize hostname by changing to lower case |
|
ref._rep->_host.toLower(); // ICU_TODO: |
| |
// ATTN-RK-P2-20020510: Need to make hostname and namespace lower case? |
// Normalize namespace by changing to lower case |
|
if (!ref._rep->_nameSpace.isNull()) |
|
{ |
|
String nameSpaceLower = ref._rep->_nameSpace.getString(); |
|
nameSpaceLower.toLower(); // ICU_TODO: |
|
ref._rep->_nameSpace = nameSpaceLower; |
|
} |
| |
String classNameLower = ref._rep->_className; |
// Normalize class name by changing to lower case |
classNameLower.toLower(); |
if (!ref._rep->_className.isNull()) |
|
{ |
|
String classNameLower = ref._rep->_className.getString(); |
|
classNameLower.toLower(); // ICU_TODO: |
ref._rep->_className = classNameLower; | ref._rep->_className = classNameLower; |
|
} |
| |
for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++) | for (Uint32 i = 0, n = ref._rep->_keyBindings.size(); i < n; i++) |
{ | { |
String keyBindingNameLower = ref._rep->_keyBindings[i]._rep->_name; |
// Normalize key binding name by changing to lower case |
keyBindingNameLower.toLower(); |
if (!ref._rep->_keyBindings[i]._rep->_name.isNull()) |
|
{ |
|
String keyBindingNameLower = |
|
ref._rep->_keyBindings[i]._rep->_name.getString(); |
|
keyBindingNameLower.toLower(); // ICU_TODO: |
ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower; | ref._rep->_keyBindings[i]._rep->_name = keyBindingNameLower; |
} | } |
| |
return ref.toString(includeHost); |
// Normalize the key value |
|
switch (ref._rep->_keyBindings[i]._rep->_type) |
|
{ |
|
case CIMKeyBinding::REFERENCE: |
|
try |
|
{ |
|
// Convert reference to CIMObjectPath and recurse |
|
ref._rep->_keyBindings[i]._rep->_value = |
|
CIMObjectPath(ref._rep->_keyBindings[i]._rep->_value). |
|
_toStringCanonical(); |
} | } |
|
catch (Exception&) |
CIMObjectPath CIMObjectPath::clone() const |
|
{ | { |
return CIMObjectPath(*this); |
// Leave value unchanged if the CIMObjectPath parsing fails |
|
} |
|
break; |
|
case CIMKeyBinding::BOOLEAN: |
|
// Normalize the boolean string by changing to lower case |
|
ref._rep->_keyBindings[i]._rep->_value.toLower(); // ICU_TODO: |
|
break; |
|
case CIMKeyBinding::NUMERIC: |
|
// Normalize the numeric string by converting to integer and back |
|
Uint64 uValue; |
|
Sint64 sValue; |
|
// First try converting to unsigned integer |
|
if (StringConversion::stringToUnsignedInteger( |
|
ref._rep->_keyBindings[i]._rep->_value.getCString(), |
|
uValue)) |
|
{ |
|
char buffer[32]; // Should need 21 chars max |
|
sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", uValue); |
|
ref._rep->_keyBindings[i]._rep->_value = String(buffer); |
|
} |
|
// Next try converting to signed integer |
|
else if (StringConversion::stringToSignedInteger( |
|
ref._rep->_keyBindings[i]._rep->_value.getCString(), |
|
sValue)) |
|
{ |
|
char buffer[32]; // Should need 21 chars max |
|
sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "d", sValue); |
|
ref._rep->_keyBindings[i]._rep->_value = String(buffer); |
|
} |
|
// Leave value unchanged if it cannot be converted to an integer |
|
break; |
|
default: // CIMKeyBinding::STRING |
|
// No normalization required for STRING |
|
break; |
|
} |
|
} |
|
|
|
// Note: key bindings are sorted when set in the CIMObjectPath |
|
|
|
return ref.toString(); |
} | } |
| |
Boolean CIMObjectPath::identical(const CIMObjectPath& x) const | Boolean CIMObjectPath::identical(const CIMObjectPath& x) const |
{ | { |
return | return |
String::equal(_rep->_host, x._rep->_host) && |
(_rep == x._rep) || |
|
(String::equalNoCase(_rep->_host, x._rep->_host) && |
_rep->_nameSpace.equal(x._rep->_nameSpace) && | _rep->_nameSpace.equal(x._rep->_nameSpace) && |
_rep->_className.equal(x._rep->_className) && | _rep->_className.equal(x._rep->_className) && |
_rep->_keyBindings == x._rep->_keyBindings; |
(_rep->_keyBindings == x._rep->_keyBindings)); |
} | } |
| |
Uint32 CIMObjectPath::makeHashCode() const | Uint32 CIMObjectPath::makeHashCode() const |
{ | { |
return HashFunc<String>::hash(toStringCanonical()); |
return HashFunc<String>::hash(_toStringCanonical()); |
} | } |
| |
Boolean CIMObjectPath::isInstanceName() const |
|
{ |
|
return _rep->_keyBindings.size() != 0; |
|
} |
|
|
|
KeyBindingArray CIMObjectPath::getKeyBindingArray() |
|
{ |
|
return KeyBindingArray(); |
|
} |
|
|
|
|
|
Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y) | Boolean operator==(const CIMObjectPath& x, const CIMObjectPath& y) |
{ | { |
return x.identical(y); | return x.identical(y); |
|
|
return !operator==(x, y); | return !operator==(x, y); |
} | } |
| |
PEGASUS_STD(ostream)& operator<<( |
|
PEGASUS_STD(ostream)& os, |
|
const CIMObjectPath& x) |
|
{ |
|
return os << x.toString(); |
|
} |
|
|
|
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |