![]() ![]() |
![]() |
File: [Pegasus] / pegasus / src / Pegasus / Common / Attic / CIMReference.cpp
(download)
Revision: 1.32, Tue Jul 10 21:31:10 2001 UTC (22 years, 11 months ago) by mike Branch: MAIN CVS Tags: version_0_99_1, version_0_99, main Branch point for: dev Changes since 1.31: +725 -725 lines Removed \r\r\n from all files. |
//%///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the 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. // //============================================================================== // // Author: Mike Brasher (mbrasher@bmc.com) // // Modified By: // //%///////////////////////////////////////////////////////////////////////////// #include <cctype> #include <cstring> #include "HashTable.h" #include "CIMReference.h" #include "Indentor.h" #include "CIMName.h" #include "Destroyer.h" #include "XmlWriter.h" #include "XmlReader.h" #include "Array.h" PEGASUS_NAMESPACE_BEGIN #define PEGASUS_ARRAY_T CIMReference # include "ArrayImpl.h" #undef PEGASUS_ARRAY_T #define PEGASUS_ARRAY_T KeyBinding # include "ArrayImpl.h" #undef PEGASUS_ARRAY_T // ATTN: add a resolve method to this class to verify that the // reference is correct (that the class name corresponds to a real // class and that the property names are really keys and that all keys // of the class or used. Also be sure that there is a valid conversion // between the string value and the value of that property). // // ATTN: also check to see that the reference refers to a class that is the // same or derived from the _className member. static String _escapeSpecialCharacters(const String& str) { String result; for (Uint32 i = 0, n = str.size(); i < n; i++) { switch (str[i]) { case '\n': result += "\\n"; break; case '\r': result += "\\r"; break; case '\t': result += "\\t"; break; case '"': result += "\\\""; break; default: result += str[i]; } } return result; } //////////////////////////////////////////////////////////////////////////////// // // Local routines: // //////////////////////////////////////////////////////////////////////////////// int _Compare(const String& s1_, const String& s2_) { const Char16* s1 = s1_.getData(); const Char16* s2 = s2_.getData(); while (*s1 && *s2) { char c1 = tolower(*s1++); char c2 = tolower(*s2++); int r = c1 - c2; if (r) return r; } if (*s2) return -1; else if (*s1) return 1; return 0; } static void _BubbleSort(Array<KeyBinding>& x) { Uint32 n = x.size(); if (n < 2) return; for (Uint32 i = 0; i < n - 1; i++) { for (Uint32 j = 0; j < n - 1; j++) { if (_Compare(x[j].getName(), x[j+1].getName()) > 0) { KeyBinding t = x[j]; x[j] = x[j+1]; x[j+1] = t; } } } } //////////////////////////////////////////////////////////////////////////////// // // KeyBinding // //////////////////////////////////////////////////////////////////////////////// KeyBinding::KeyBinding() { } KeyBinding::KeyBinding(const KeyBinding& x) : _name(x._name), _value(x._value), _type(x._type) { } KeyBinding::KeyBinding(const String& name, const String& value, Type type) : _name(name), _value(value), _type(type) { } KeyBinding::~KeyBinding() { } KeyBinding& KeyBinding::operator=(const KeyBinding& x) { _name = x._name; _value = x._value; _type = x._type; return *this; } //////////////////////////////////////////////////////////////////////////////// // // CIMReference // //////////////////////////////////////////////////////////////////////////////// CIMReference::CIMReference() { } CIMReference::CIMReference(const CIMReference& x) : _host(x._host), _nameSpace(x._nameSpace), _className(x._className), _keyBindings(x._keyBindings) { _BubbleSort(_keyBindings); } CIMReference::CIMReference(const String& objectName) { set(objectName); } CIMReference::CIMReference(const char* objectName) { set(objectName); } CIMReference::CIMReference( const String& host, const String& nameSpace, const String& className, const Array<KeyBinding>& keyBindings) { set(host, nameSpace, className, keyBindings); } CIMReference::~CIMReference() { } CIMReference& CIMReference::operator=(const CIMReference& x) { if (&x != this) { _host = x._host; _nameSpace = x._nameSpace; _className = x._className; _keyBindings = x._keyBindings; } return *this; } void CIMReference::clear() { _host.clear(); _nameSpace.clear(); _className.clear(); _keyBindings.clear(); } void CIMReference::set( const String& host, const String& nameSpace, const String& className, const Array<KeyBinding>& keyBindings) { setHost(host); setNameSpace(nameSpace); setClassName(className); setKeyBindings(keyBindings); } void CIMReference::set(const String& objectName) { _host.clear(); _nameSpace.clear(); _className.clear(); _keyBindings.clear(); //-------------------------------------------------------------------------- // We will extract components from an object name. Here is an sample // object name: // // //atp:9999/root/cimv25:TennisPlayer.first="Patrick",last="Rafter" //-------------------------------------------------------------------------- // Convert to a C String first: char* p = objectName.allocateCString(); ArrayDestroyer<char> destroyer(p); // See if there is a host name (true if it begins with "//"): // Host is of the from <hostname>-<port> and begins with "//" // and ends with "/": if (p[0] == '/' && p[1] == '/') { p += 2; //---------------------------------------------------------------------- // Validate the hostname. Hostnames must match the following // 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 colon (before the port): if (*q != ':') throw IllformedObjectName(objectName); q++; // Check for a port number: if (!isdigit(*q)) throw IllformedObjectName(objectName); while (isdigit(*q)) q++; // Check for slash terminating the entire sequence: if (*q != '/') throw IllformedObjectName(objectName); // Finally, assign the host name: _host.assign(p, q - p); p = ++q; //---------------------------------------------------------------------- // Validate the namespace path: //---------------------------------------------------------------------- q = strchr(p, ':'); if (!q) throw IllformedObjectName(objectName); q = p; for (;;) { // Pass next next token: if (!*q || (!isalpha(*q) && *q != '_')) throw IllformedObjectName(objectName); q++; while (isalnum(*q) || *q == '_') q++; if (!*q) throw IllformedObjectName(objectName); if (*q == ':') break; if (*q == '/') { q++; continue; } throw IllformedObjectName(objectName); } _nameSpace.assign(p, q - p); p = ++q; } // Extract the class name: char* dot = strchr(p, '.'); if (!dot) { if (!CIMName::legal(p)) throw IllformedObjectName(objectName); // ATTN: remove this later: a reference should only be able to hold // an instance name. _className.assign(p); return; } _className.assign(p, dot - p); // Advance past dot: p = dot + 1; // Get the key-value pairs: for (p = strtok(p, ","); p; p = strtok(NULL, ",")) { // Split about the equal sign: char* equal = strchr(p, '='); if (!equal) throw IllformedObjectName(objectName); *equal = '\0'; // Get key part: String keyString(p); if (!CIMName::legal(keyString)) throw IllformedObjectName(objectName); // Get the value part: String valueString; char* q = equal + 1; KeyBinding::Type type; if (*q == '"') { q++; type = KeyBinding::STRING; while (*q && *q != '"') { // ATTN: need to handle special characters here: if (*q == '\\') *q++; valueString.append(*q++); } if (*q++ != '"') throw IllformedObjectName(objectName); if (*q) throw IllformedObjectName(objectName); } else if (toupper(*q) == 'T' || toupper(*q) == 'F') { type = KeyBinding::BOOLEAN; char* r = q; while (*r) { *r = toupper(*r); r++; } if (strcmp(q, "TRUE") != 0 && strcmp(q, "FALSE") != 0) throw IllformedObjectName(objectName); valueString.assign(q); } else { type = KeyBinding::NUMERIC; Sint64 x; if (!XmlReader::stringToSignedInteger(q, x)) throw IllformedObjectName(objectName); valueString.assign(q); } _keyBindings.append(KeyBinding(keyString, valueString, type)); } _BubbleSort(_keyBindings); } void CIMReference::setNameSpace(const String& nameSpace) { String temp; // check each namespace segment (delimted by '/') for correctness for(Uint32 i = 0; i < nameSpace.size(); i += temp.size() + 1) { // isolate the segment beginning at i and ending at the first // ocurrance of '/' after i or eos temp = nameSpace.subString(i, nameSpace.subString(i).find('/')); // check segment for correctness if(!CIMName::legal(temp)) { throw IllegalName() ; } } _nameSpace = nameSpace; } void CIMReference::setClassName(const String& className) { if (!CIMName::legal(className)) throw IllegalName(); _className = className; } void CIMReference::setKeyBindings(const Array<KeyBinding>& keyBindings) { _keyBindings = keyBindings; _BubbleSort(_keyBindings); } String CIMReference::toString() const { String objectName; // Get the host: if (_host.size() && _nameSpace.size()) { objectName = "//"; objectName += _host; objectName += "/"; objectName += _nameSpace; objectName += ":"; } // Get the class name: const String& className = getClassName(); objectName.append(className); if (isClassName()) return objectName; objectName.append('.'); // Append each key-value pair: const Array<KeyBinding>& keyBindings = getKeyBindings(); for (Uint32 i = 0, n = keyBindings.size(); i < n; i++) { objectName.append(keyBindings[i].getName()); objectName.append('='); const String& value = _escapeSpecialCharacters( keyBindings[i].getValue()); KeyBinding::Type type = keyBindings[i].getType(); if (type == KeyBinding::STRING) objectName.append('"'); objectName.append(value); if (type == KeyBinding::STRING) objectName.append('"'); if (i + 1 != n) objectName.append(','); } return objectName; } String CIMReference::toStringCanonical() const { CIMReference ref = *this; ref._className.toLower(); for (Uint32 i = 0, n = ref._keyBindings.size(); i < n; i++) ref._keyBindings[i]._name.toLower(); return ref.toString(); } Boolean CIMReference::identical(const CIMReference& x) const { return String::equal(_host, x._host) && String::equal(_nameSpace, x._nameSpace) && CIMName::equal(_className, x._className) && _keyBindings == x._keyBindings; } void CIMReference::nameSpaceToXml(Array<Sint8>& out) const { if (_host.size()) { out << "<NAMESPACEPATH>\n"; out << "<HOST>" << _host << "</HOST>\n"; } XmlWriter::appendLocalNameSpaceElement(out, _nameSpace); if (_host.size()) out << "</NAMESPACEPATH>\n"; } void CIMReference::localNameSpaceToXml(Array<Sint8>& out) const { out << "<LOCALNAMESPACEPATH>\n"; char* tmp = _nameSpace.allocateCString(); for (char* p = strtok(tmp, "/"); p; p = strtok(NULL, "/")) { out << "<NAMESPACE NAME=\"" << p << "\"/>\n"; } delete [] tmp; out << "</LOCALNAMESPACEPATH>\n"; } void CIMReference::classNameToXml(Array<Sint8>& out) const { out << "<CLASSNAME NAME=\"" << _className << "\"/>\n"; } void CIMReference::instanceNameToXml(Array<Sint8>& out) const { out << "<INSTANCENAME CLASSNAME=\"" << _className << "\">\n"; for (Uint32 i = 0, n = _keyBindings.size(); i < n; i++) { out << "<KEYBINDING NAME=\"" << _keyBindings[i].getName() << "\">\n"; out << "<KEYVALUE VALUETYPE=\""; out << KeyBinding::typeToString(_keyBindings[i].getType()); out << "\">"; out << _keyBindings[i].getValue(); out << "</KEYVALUE>\n"; out << "</KEYBINDING>\n"; } out << "</INSTANCENAME>\n"; } void CIMReference::toXml(Array<Sint8>& out, Boolean putValueWrapper) const { if (putValueWrapper) out << "<VALUE.REFERENCE>\n"; // See if it is a class or instance reference (instance references have // key-bindings; class references do not). if (_keyBindings.size()) { if (_host.size()) { out << "<INSTANCEPATH>\n"; nameSpaceToXml(out); instanceNameToXml(out); out << "</INSTANCEPATH>\n"; } else if (_nameSpace.size()) { out << "<LOCALINSTANCEPATH>\n"; localNameSpaceToXml(out); instanceNameToXml(out); out << "</LOCALINSTANCEPATH>\n"; } else instanceNameToXml(out); } else { if (_host.size()) { out << "<CLASSPATH>\n"; nameSpaceToXml(out); classNameToXml(out); out << "</CLASSPATH>"; } else if (_nameSpace.size()) { out << "<LOCALCLASSPATH>\n"; nameSpaceToXml(out); classNameToXml(out); out << "</LOCALCLASSPATH>"; } else classNameToXml(out); } if (putValueWrapper) out << "</VALUE.REFERENCE>\n"; } void CIMReference::print(PEGASUS_STD(ostream)& os) const { Array<Sint8> tmp; toXml(tmp); XmlWriter::indentedPrint(os, tmp.getData()); } const char* KeyBinding::typeToString(Type type) { switch (type) { case KeyBinding::BOOLEAN: return "boolean"; case KeyBinding::STRING: return "string"; case KeyBinding::NUMERIC: return "numeric"; } return "unknown"; } Uint32 CIMReference::makeHashCode() const { CIMReference ref = *this; ref._className.toLower(); for (Uint32 i = 0, n = ref._keyBindings.size(); i < n; i++) ref._keyBindings[i]._name.toLower(); return HashFunc<String>::hash(ref.toString()); } KeyBindingArray CIMReference::getKeyBindingArray() { return KeyBindingArray(); } PEGASUS_NAMESPACE_END
No CVS admin address has been configured |
Powered by ViewCVS 0.9.2 |