version 1.35, 2003/11/14 19:32:24
|
version 1.64, 2007/10/31 07:52:22
|
|
|
//%2003//////////////////////////////////////////////////////////////////////// |
//%2006//////////////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Development |
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development |
// Company, L. P., IBM Corp., The Open Group, Tivoli Systems. |
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. |
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.; | // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.; |
// IBM Corp.; EMC Corporation, The Open Group. | // IBM Corp.; EMC Corporation, The Open Group. |
|
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; |
|
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; Symantec Corporation; The Open Group. |
// | // |
// 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 copy |
// of this software and associated documentation files (the "Software"), to | // of this software and associated documentation files (the "Software"), to |
|
|
// | // |
//============================================================================== | //============================================================================== |
// | // |
// Author: Mike Brasher (mbrasher@bmc.com) |
|
// |
|
// Modified By: Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
|
// Carol Ann Krug Graves, Hewlett-Packard Company |
|
// (carolann_graves@hp.com) |
|
// |
|
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
#include <Pegasus/Common/Config.h> | #include <Pegasus/Common/Config.h> |
#include <cctype> |
|
#include <cstring> | #include <cstring> |
#include <iostream> | #include <iostream> |
#include "HashTable.h" | #include "HashTable.h" |
#include "CIMObjectPath.h" | #include "CIMObjectPath.h" |
#include "Indentor.h" | #include "Indentor.h" |
#include "CIMName.h" | #include "CIMName.h" |
#include "Destroyer.h" |
|
#include "XmlWriter.h" | #include "XmlWriter.h" |
#include "XmlReader.h" | #include "XmlReader.h" |
#include "ArrayInternal.h" | #include "ArrayInternal.h" |
|
#include "HostLocator.h" |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
|
|
_rep = new CIMKeyBindingRep(*x._rep); | _rep = new CIMKeyBindingRep(*x._rep); |
} | } |
| |
CIMKeyBinding::CIMKeyBinding(const CIMName& name, const String& value, Type type) |
CIMKeyBinding::CIMKeyBinding( |
|
const CIMName& name, |
|
const String& value, |
|
Type type) |
{ | { |
_rep = new CIMKeyBindingRep(name, value, type); | _rep = new CIMKeyBindingRep(name, value, type); |
} | } |
|
|
case CIMTYPE_REFERENCE: | case CIMTYPE_REFERENCE: |
kbType = REFERENCE; | kbType = REFERENCE; |
break; | break; |
|
// case CIMTYPE_REAL32: |
|
// case CIMTYPE_REAL64: |
|
case CIMTYPE_OBJECT: |
|
#ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT |
|
case CIMTYPE_INSTANCE: |
|
#endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT |
|
// From PEP 194: EmbeddedObjects cannot be keys. |
|
throw TypeMismatchException(); |
|
break; |
default: | default: |
kbType = NUMERIC; | kbType = NUMERIC; |
break; | break; |
|
|
kbValue = XmlReader::stringToValue(0, getValue().getCString(), | kbValue = XmlReader::stringToValue(0, getValue().getCString(), |
value.getType()); | value.getType()); |
break; | break; |
|
// case CIMTYPE_REAL32: |
|
// case CIMTYPE_REAL64: |
|
case CIMTYPE_OBJECT: |
|
#ifdef PEGASUS_EMBEDDED_INSTANCE_SUPPORT |
|
case CIMTYPE_INSTANCE: |
|
#endif // PEGASUS_EMBEDDED_INSTANCE_SUPPORT |
|
// From PEP 194: EmbeddedObjects cannot be keys. |
|
return false; |
|
break; |
default: // Numerics | default: // Numerics |
if (getType() != NUMERIC) return false; | if (getType() != NUMERIC) return false; |
kbValue = XmlReader::stringToValue(0, getValue().getCString(), | kbValue = XmlReader::stringToValue(0, getValue().getCString(), |
|
|
catch (Exception&) | catch (Exception&) |
{ | { |
// If CIMObjectPath parsing fails, just compare strings | // If CIMObjectPath parsing fails, just compare strings |
return (String::equal(x.getValue(), y.getValue())); |
return String::equal(x.getValue(), y.getValue()); |
} | } |
break; | break; |
case CIMKeyBinding::BOOLEAN: | case CIMKeyBinding::BOOLEAN: |
// Case-insensitive comparison is sufficient for booleans | // Case-insensitive comparison is sufficient for booleans |
return (String::equalNoCase(x.getValue(), y.getValue())); |
return String::equalNoCase(x.getValue(), y.getValue()); |
break; | break; |
case CIMKeyBinding::NUMERIC: | case CIMKeyBinding::NUMERIC: |
// Note: This comparison assumes XML syntax for integers | // Note: This comparison assumes XML syntax for integers |
|
|
} | } |
// Note: Keys may not be real values, so don't try comparing as reals | // 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 | // We couldn't parse the numbers, so just compare the strings |
return (String::equal(x.getValue(), y.getValue())); |
return String::equal(x.getValue(), y.getValue()); |
break; | break; |
default: // CIMKeyBinding::STRING | default: // CIMKeyBinding::STRING |
return (String::equal(x.getValue(), y.getValue())); |
return String::equal(x.getValue(), y.getValue()); |
break; | break; |
} | } |
| |
|
|
class CIMObjectPathRep | class CIMObjectPathRep |
{ | { |
public: | public: |
CIMObjectPathRep() |
CIMObjectPathRep(): _refCounter(1) |
{ | { |
} | } |
| |
CIMObjectPathRep(const CIMObjectPathRep& x) | CIMObjectPathRep(const CIMObjectPathRep& x) |
: _host(x._host), _nameSpace(x._nameSpace), |
: _refCounter(1), _host(x._host), _nameSpace(x._nameSpace), |
_className(x._className), _keyBindings(x._keyBindings) | _className(x._className), _keyBindings(x._keyBindings) |
{ | { |
} | } |
|
|
const CIMNamespaceName& nameSpace, | const CIMNamespaceName& nameSpace, |
const CIMName& className, | const CIMName& className, |
const Array<CIMKeyBinding>& keyBindings) | const Array<CIMKeyBinding>& keyBindings) |
: _host(host), _nameSpace(nameSpace), |
: _refCounter(1), _host(host), _nameSpace(nameSpace), |
_className(className), _keyBindings(keyBindings) | _className(className), _keyBindings(keyBindings) |
{ | { |
} | } |
|
|
| |
static Boolean isValidHostname(const String& hostname) | static Boolean isValidHostname(const String& hostname) |
{ | { |
//------------------------------------------------------------------ |
HostLocator addr(hostname); |
// Validate the hostname. The hostname value may or may not be a |
|
// fully-qualified domain name (e.g., xyz.company.com) or may be an |
|
// IP address. A port number may follow the hostname. |
|
// Hostnames must match one of the following regular expressions: |
|
// ^([A-Za-z][A-Za-z0-9-]*)(\.[A-Za-z][A-Za-z0-9-]*)*(:[0-9]*)?$ |
|
// ^([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)(:[0-9]*)?$ |
|
//------------------------------------------------------------------ |
|
|
|
Uint32 i = 0; |
|
|
|
if (isdigit(hostname[0])) |
|
{ |
|
// Validate an IP address |
|
|
|
for (Uint32 octet=1; octet<=4; octet++) |
|
{ |
|
Uint32 octetValue = 0; |
|
|
|
if (!isdigit(hostname[i])) |
|
{ |
|
return false; |
|
} |
|
|
|
while (isdigit(hostname[i])) |
|
{ |
|
octetValue = octetValue*10 + (hostname[i] - '0'); |
|
i++; |
|
} |
|
|
|
if (octetValue > 255) |
|
{ |
|
return false; |
|
} |
|
|
|
if ((octet != 4) && (hostname[i++] != '.')) |
|
{ |
|
return false; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
// Validate a hostname |
|
|
|
Boolean expectHostSegment = true; |
|
|
|
while (expectHostSegment == true) |
|
{ |
|
expectHostSegment = false; |
|
|
|
if (!isalpha(hostname[i++])) |
|
{ |
|
return false; |
|
} |
|
| |
while (isalnum(hostname[i]) || (hostname[i] == '-')) |
return addr.isValid(); |
{ |
|
i++; |
|
} |
|
|
|
if (hostname[i] == '.') |
|
{ |
|
i++; |
|
expectHostSegment = true; |
|
} |
|
} |
|
} |
|
|
|
// Check for a port number: |
|
|
|
if (hostname[i] == ':') |
|
{ |
|
if (!isdigit(hostname[++i])) |
|
{ |
|
return false; |
|
} |
|
|
|
while (isdigit(hostname[++i])); |
|
} |
|
|
|
return (hostname[i] == char(0)); |
|
} | } |
| |
|
// reference counter as member to avoid |
|
// virtual function resolution overhead |
|
AtomicInt _refCounter; |
// | // |
// Contains port as well (e.g., myhost:1234). | // Contains port as well (e.g., myhost:1234). |
// | // |
|
|
Array<CIMKeyBinding> _keyBindings; | Array<CIMKeyBinding> _keyBindings; |
}; | }; |
| |
|
template<class REP> |
|
inline void Ref(REP* rep) |
|
{ |
|
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( | CIMObjectPath::CIMObjectPath( |
|
|
// 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 CIMName& className, | const CIMName& className, |
const Array<CIMKeyBinding>& keyBindings) | const Array<CIMKeyBinding>& keyBindings) |
{ | { |
setHost(host); |
if ((host != String::EMPTY) && !CIMObjectPathRep::isValidHostname(host)) |
setNameSpace(nameSpace); |
{ |
setClassName(className); |
throw MalformedObjectNameException(host); |
setKeyBindings(keyBindings); |
} |
|
|
|
_rep = _copyOnWriteCIMObjectPathRep(_rep); |
|
|
|
_rep->_host.assign(host); |
|
_rep->_nameSpace = nameSpace; |
|
_rep->_className = className; |
|
_rep->_keyBindings = keyBindings; |
|
_BubbleSort(_rep->_keyBindings); |
} | } |
| |
Boolean _parseHostElement( | Boolean _parseHostElement( |
|
|
| |
p++; | p++; |
| |
|
Array<Uint8> keyValueUTF8; |
|
keyValueUTF8.reserveCapacity(128); |
|
|
while (*p && *p != '"') | while (*p && *p != '"') |
{ | { |
if (*p == '\\') | if (*p == '\\') |
{ | { |
*p++; |
p++; |
| |
if ((*p != '\\') && (*p != '"')) | if ((*p != '\\') && (*p != '"')) |
{ | { |
|
|
} | } |
} | } |
| |
valueString.append(*p++); |
keyValueUTF8.append(*p++); |
} | } |
| |
if (*p++ != '"') | if (*p++ != '"') |
throw MalformedObjectNameException(objectName); | throw MalformedObjectNameException(objectName); |
| |
|
// 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 | Guess at the type of this quoted key value. If the value |
can be parsed into a CIMObjectPath with at least one key | can be parsed into a CIMObjectPath with at least one key |
|
|
type = CIMKeyBinding::REFERENCE; | type = CIMKeyBinding::REFERENCE; |
} | } |
} | } |
catch (Exception & e) |
catch (const Exception &) |
{ | { |
// Not a reference value; leave type as STRING | // Not a reference value; leave type as STRING |
} | } |
|
|
isComma = true; | isComma = true; |
} | } |
| |
|
if (*p == '-') |
|
{ |
Sint64 x; | Sint64 x; |
|
|
if (!XmlReader::stringToSignedInteger(p, x)) | if (!XmlReader::stringToSignedInteger(p, x)) |
throw MalformedObjectNameException(objectName); | throw MalformedObjectNameException(objectName); |
|
} |
|
else |
|
{ |
|
Uint64 x; |
|
if (!XmlReader::stringToUnsignedInteger(p, x)) |
|
throw MalformedObjectNameException(objectName); |
|
} |
| |
valueString.assign(p, n); | valueString.assign(p, n); |
| |
|
|
| |
void CIMObjectPath::set(const String& objectName) | 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: |
| |
CString pCString = objectName.getCStringUTF8(); |
CString pCString = objectName.getCString(); |
char* p = const_cast<char*>((const char*) pCString); | char* p = const_cast<char*>((const char*) pCString); |
Boolean gotHost; | Boolean gotHost; |
Boolean gotNamespace; | Boolean gotNamespace; |
|
|
| |
CIMObjectPath& CIMObjectPath::operator=(const String& objectName) | CIMObjectPath& CIMObjectPath::operator=(const String& objectName) |
{ | { |
|
// set will call clear, which will cause copyOnWrite if necessary |
set(objectName); | set(objectName); |
return *this; | return *this; |
} | } |
|
|
{ | { |
throw MalformedObjectNameException(host); | throw MalformedObjectNameException(host); |
} | } |
|
_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; |
} | } |
| |
|
|
| |
void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings) | void CIMObjectPath::setKeyBindings(const Array<CIMKeyBinding>& keyBindings) |
{ | { |
|
_rep = _copyOnWriteCIMObjectPathRep(_rep); |
_rep->_keyBindings = keyBindings; | _rep->_keyBindings = keyBindings; |
_BubbleSort(_rep->_keyBindings); | _BubbleSort(_rep->_keyBindings); |
} | } |
|
|
| |
CIMKeyBinding::Type type = keyBindings[i].getType(); | CIMKeyBinding::Type type = keyBindings[i].getType(); |
| |
if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE) |
if (type == CIMKeyBinding::STRING || |
|
type == CIMKeyBinding::REFERENCE) |
objectName.append('"'); | objectName.append('"'); |
| |
objectName.append(value); | objectName.append(value); |
| |
if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE) |
if (type == CIMKeyBinding::STRING || |
|
type == CIMKeyBinding::REFERENCE) |
objectName.append('"'); | objectName.append('"'); |
| |
if (i + 1 != n) | if (i + 1 != n) |
|
|
| |
String CIMObjectPath::_toStringCanonical() const | String CIMObjectPath::_toStringCanonical() const |
{ | { |
CIMObjectPath ref = *this; |
CIMObjectPath ref; |
|
*ref._rep = *this->_rep; |
| |
// Normalize hostname by changing to lower case | // Normalize hostname by changing to lower case |
ref._rep->_host.toLower(); // ICU_TODO: | ref._rep->_host.toLower(); // ICU_TODO: |
|
|
Boolean CIMObjectPath::identical(const CIMObjectPath& x) const | Boolean CIMObjectPath::identical(const CIMObjectPath& x) const |
{ | { |
return | return |
String::equalNoCase(_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 !operator==(x, y); | return !operator==(x, y); |
} | } |
| |
#ifndef PEGASUS_REMOVE_DEPRECATED |
|
PEGASUS_STD(ostream)& operator<<( |
|
PEGASUS_STD(ostream)& os, |
|
const CIMObjectPath& x) |
|
{ |
|
return os << x.toString(); |
|
} |
|
#endif |
|
|
|
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |