version 1.22, 2002/09/20 19:40:11
|
version 1.30, 2003/10/22 14:26:02
|
|
|
//%///////////////////////////////////////////////////////////////////////////// |
//%2003//////////////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM, |
// Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Development |
// 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.; |
|
// IBM Corp.; EMC 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 |
|
|
{ | { |
switch (str[i]) | switch (str[i]) |
{ | { |
case '\n': |
case '\\': |
result.append("\\n"); |
result.append("\\\\"); |
break; |
|
|
|
case '\r': |
|
result.append("\\r"); |
|
break; |
|
|
|
case '\t': |
|
result.append("\\t"); |
|
break; | break; |
| |
case '"': | case '"': |
|
|
{ | { |
Uint32 n = x.size(); | Uint32 n = x.size(); |
| |
|
// |
|
// If the key is a reference, the keys in the reference must also be |
|
// sorted |
|
// |
|
for (Uint32 k = 0; k < n ; k++) |
|
if (x[k].getType () == CIMKeyBinding::REFERENCE) |
|
{ |
|
CIMObjectPath tmp (x[k].getValue ()); |
|
Array <CIMKeyBinding> keyBindings = tmp.getKeyBindings (); |
|
_BubbleSort (keyBindings); |
|
tmp.setKeyBindings (keyBindings); |
|
x[k].setValue (tmp.toString ()); |
|
} |
|
|
if (n < 2) | if (n < 2) |
return; | return; |
| |
|
|
p += 2; | p += 2; |
| |
//---------------------------------------------------------------------- | //---------------------------------------------------------------------- |
// Validate the hostname. Hostnames must match the following |
// Validate the hostname. A domain is allowed after the hostname. |
// regular expression: "[A-Za-z][A-Za-z0-9-]*" |
// Eg. xyz.company.com |
|
// Hostnames must match the following regular expression: |
|
// ^([A-Za-z][A-Za-z0-9-]*)(\.[A-Za-z][A-Za-z0-9-]*)*$ |
//---------------------------------------------------------------------- | //---------------------------------------------------------------------- |
| |
char* q = p; | char* q = p; |
| |
|
Boolean foundDot = true; |
|
while (foundDot == true) |
|
{ |
|
foundDot = false; |
|
|
if (!isalpha(*q)) | if (!isalpha(*q)) |
throw MalformedObjectNameException(objectName); | throw MalformedObjectNameException(objectName); |
| |
q++; | q++; |
| |
while (isalnum(*q) || *q == '-') | while (isalnum(*q) || *q == '-') |
|
{ |
|
q++; |
|
} |
|
|
|
if (*q == '.') |
|
{ |
q++; | q++; |
|
foundDot = true; |
|
} |
|
} |
| |
// We now expect a port (or default the port). | // We now expect a port (or default the port). |
| |
|
|
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 MalformedObjectNameException(objectName); | throw MalformedObjectNameException(objectName); |
|
|
} | } |
| |
/** | /** |
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 CIMKeyBinding type (REFERENCE) has been defined to denote |
|
keys in a CIMObjectPath that are of reference type. This |
|
CIMKeyBinding 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 _parseKeyBindingPairs( | void _parseKeyBindingPairs( |
const String& objectName, | const String& objectName, |
|
|
p = equalsign + 1; | p = equalsign + 1; |
CIMKeyBinding::Type type; | CIMKeyBinding::Type type; |
| |
if (*p == 'R') |
if (*p == '"') |
{ | { |
p++; |
// Could be CIMKeyBinding::STRING or CIMKeyBinding::REFERENCE |
| |
type = CIMKeyBinding::REFERENCE; |
p++; |
|
|
if (*p++ != '"') |
|
throw MalformedObjectNameException(objectName); |
|
| |
while (*p && *p != '"') | while (*p && *p != '"') |
{ | { |
// ATTN: need to handle special characters here: |
|
|
|
if (*p == '\\') | if (*p == '\\') |
|
{ |
*p++; | *p++; |
| |
|
if ((*p != '\\') && (*p != '"')) |
|
{ |
|
throw MalformedObjectNameException(objectName); |
|
} |
|
} |
|
|
valueString.append(*p++); | valueString.append(*p++); |
} | } |
| |
if (*p++ != '"') | if (*p++ != '"') |
throw MalformedObjectNameException(objectName); | throw MalformedObjectNameException(objectName); |
} |
|
else if (*p == '"') |
|
{ |
|
p++; |
|
| |
|
/* |
|
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; | type = CIMKeyBinding::STRING; |
| |
while (*p && *p != '"') |
try |
{ | { |
// ATTN: need to handle special characters here: |
CIMObjectPath testForPath(valueString); |
|
if (testForPath.getKeyBindings().size() > 0) |
if (*p == '\\') |
{ |
*p++; |
// We've found a reference value! |
|
type = CIMKeyBinding::REFERENCE; |
valueString.append(*p++); |
} |
|
} |
|
catch (Exception & e) |
|
{ |
|
// Not a reference value; leave type as STRING |
} | } |
|
|
if (*p++ != '"') |
|
throw MalformedObjectNameException(objectName); |
|
} | } |
else if (toupper(*p) == 'T' || toupper(*p) == 'F') | else if (toupper(*p) == 'T' || toupper(*p) == 'F') |
{ | { |
|
|
| |
// Convert to a C String first: | // Convert to a C String first: |
| |
char* p = strdup(objectName.getCString()); |
CString pCString = objectName.getCStringUTF8(); |
Destroyer<char> destroyer(p); |
char* p = const_cast<char*>((const char*) pCString); |
Boolean gotHost; | Boolean gotHost; |
Boolean gotNamespace; | Boolean gotNamespace; |
| |
|
|
return; | return; |
} | } |
| |
String className = String(p, dot - p); |
String className = String(p, (Uint32)(dot - p)); |
if (!CIMName::legal(className)) | if (!CIMName::legal(className)) |
{ | { |
throw MalformedObjectNameException(objectName); | throw MalformedObjectNameException(objectName); |
|
|
| |
CIMKeyBinding::Type type = keyBindings[i].getType(); | CIMKeyBinding::Type type = keyBindings[i].getType(); |
| |
if (type == CIMKeyBinding::REFERENCE) |
|
objectName.append('R'); |
|
|
|
if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE) | if (type == CIMKeyBinding::STRING || type == CIMKeyBinding::REFERENCE) |
objectName.append('"'); | objectName.append('"'); |
| |
|
|
// ATTN-RK-P2-20020510: Need to make hostname and namespace lower case? | // ATTN-RK-P2-20020510: Need to make hostname and namespace lower case? |
| |
String classNameLower = ref._rep->_className.getString (); | String classNameLower = ref._rep->_className.getString (); |
classNameLower.toLower(); |
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++) |