//BEGIN_LICENSE // // Copyright (c) 2000 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 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. // //END_LICENSE //BEGIN_HISTORY // // Author: // // $Log: XmlWriter.cpp,v $ // Revision 1.6 2001/02/19 01:47:17 mike // Renamed names of the form CIMConst to ConstCIM. // // Revision 1.5 2001/02/18 03:56:01 mike // Changed more class names (e.g., ConstClassDecl -> ConstCIMClass) // // Revision 1.4 2001/02/16 02:06:07 mike // Renamed many classes and headers. // // Revision 1.3 2001/01/31 08:20:51 mike // Added dispatcher framework. // Added enumerateInstanceNames. // // Revision 1.2 2001/01/29 02:23:44 mike // Added support for GetInstance operation // // Revision 1.1.1.1 2001/01/14 19:53:36 mike // Pegasus import // // //END_HISTORY #include #include #include "CIMClass.h" #include "CIMQualifierDecl.h" #include "XmlWriter.h" #include "XmlParser.h" PEGASUS_NAMESPACE_BEGIN inline void AppendChar(Array& out, Char16 c) { out.append(Sint8(c)); } inline void AppendSpecialChar(Array& out, Char16 c) { // ATTN-B: Only UTF-8 handled for now. switch (c) { case '&': out.append("&", 5); break; case '<': out.append("<", 4); break; case '>': out.append(">", 4); break; case '"': out.append(""", 6); break; case '\'': out.append("'", 6); break; default: out.append(Sint8(c)); } } void XmlWriter::append(Array& out, Char16 x) { AppendChar(out, x); } void XmlWriter::append(Array& out, Uint32 x) { char buffer[32]; sprintf(buffer, "%d", x); append(out, buffer); } void XmlWriter::append(Array& out, const char* str) { while (*str) AppendChar(out, *str++); } void XmlWriter::appendSpecial(Array& out, Char16 x) { AppendSpecialChar(out, x); } void XmlWriter::appendSpecial(Array& out, char x) { AppendSpecialChar(out, Char16(x)); } void XmlWriter::appendSpecial(Array& out, const char* str) { while (*str) AppendSpecialChar(out, *str++); } void XmlWriter::appendSpecial(Array& out, const String& str) { const Char16* tmp = str.getData(); while (*tmp) AppendSpecialChar(out, *tmp++); } void XmlWriter::append(Array& out, const String& str) { const Char16* tmp = str.getData(); while (*tmp) AppendChar(out, *tmp++); } void XmlWriter::append(Array& out, const Indentor& x) { for (Uint32 i = 0; i < 4 * x.getLevel(); i++) out.append(' '); } void XmlWriter::appendLocalNameSpaceElement( Array& out, const String& nameSpace) { out << "\n"; char* tmp = nameSpace.allocateCString(); for (char* p = strtok(tmp, "/"); p; p = strtok(NULL, "/")) { out << "\n"; } out << "\n"; } static inline void AppendSpecialChar(std::ostream& os, char c) { switch (c) { case '&': os << "&"; break; case '<': os << "<"; break; case '>': os << ">"; break; case '"': os << """; break; case '\'': os << "'"; break; default: os << c; } } static inline void AppendSpecial(std::ostream& os, const char* str) { while (*str) AppendSpecialChar(os, *str++); } //------------------------------------------------------------------------------ // // formatGetHeader() // //------------------------------------------------------------------------------ Array XmlWriter::formatGetHeader( const char* documentPath) { Array out; return out << "GET " << documentPath << "HTTP/1.0\r\n\r\n"; } //------------------------------------------------------------------------------ // // formatMPostHeader() // // Build HTTP request header. // //------------------------------------------------------------------------------ Array XmlWriter::formatMPostHeader( const char* host, const char* cimOperation, const char* cimMethod, const String& cimObject, const Array& content) { Array out; out.reserve(1024); char nn[] = { '0' + (rand() % 10), '0' + (rand() % 10), '\0' }; out << "M-POST /cimom HTTP/1.1\r\n"; out << "HOST: " << host << "\r\n"; out << "Content-CIMType: application/xml; charset=\"utf-8\"\r\n"; out << "Content-Length: " << content.getSize() << "\r\n"; out << "Man: http://www.dmtf.org/cim/mapping/http/v1.0; ns="; out << nn <<"\r\n"; out << nn << "-CIMOperation: " << cimOperation << "\r\n"; out << nn << "-CIMMethod: " << cimMethod << "\r\n"; out << nn << "-CIMObject: " << cimObject << "\r\n\r\n"; out << content; return out; } //------------------------------------------------------------------------------ // // formatMethodResponseHeader() // // Build HTTP response header. // //------------------------------------------------------------------------------ Array XmlWriter::formatMethodResponseHeader( const Array& content) { Array out; out.reserve(1024); char nn[] = { '0' + (rand() % 10), '0' + (rand() % 10), '\0' }; out << "HTTP/1.1 200 OK\r\n"; out << "Content-CIMType: application/xml; charset=\"utf-8\"\r\n"; out << "Content-Length: " << content.getSize() << "\r\n"; out << "Ext:\r\n"; out << "Cache-Control: no-cache\r\n"; out << "Man: http://www.dmtf.org/cim/mapping/http/v1.0; ns="; out << nn <<"\r\n"; out << nn << "-CIMOperation: MethodResponse\r\n\r\n"; out << content; return out; } //------------------------------------------------------------------------------ // // formatMessageElement() // // // // //------------------------------------------------------------------------------ Array XmlWriter::formatMessageElement( Uint32 messageId, const Array& body) { Array out; out.reserve(1024); out << "\n"; out << "\n"; out << "\n"; out << body; out << "\n"; out << "\n"; return out; } //------------------------------------------------------------------------------ // // formatSimpleReqElement() // // // //------------------------------------------------------------------------------ Array XmlWriter::formatSimpleReqElement( const Array& body) { Array out; return out << "\n" << body << "\n"; } //------------------------------------------------------------------------------ // // formatSimpleRspElement() // // // //------------------------------------------------------------------------------ Array XmlWriter::formatSimpleRspElement( const Array& body) { Array out; return out << "\n" << body << "\n"; } //------------------------------------------------------------------------------ // // formatIMethodCallElement() // // // // //------------------------------------------------------------------------------ Array XmlWriter::formatIMethodCallElement( const char* name, const String& nameSpace, const Array& iParamValues) { Array out; out << "\n"; XmlWriter::appendLocalNameSpaceElement(out, nameSpace); out << iParamValues; out << "\n"; return out; } //------------------------------------------------------------------------------ // // formatIMethodResponseElement() // // // // //------------------------------------------------------------------------------ Array XmlWriter::formatIMethodResponseElement( const char* name, const Array& body) { Array out; out << "\n"; out << body; out << "\n"; return out; } //------------------------------------------------------------------------------ // // formatIReturnValueElement() // // // //------------------------------------------------------------------------------ Array XmlWriter::formatIReturnValueElement( const Array& body) { Array out; return out << "\n" << body << "\n"; } //------------------------------------------------------------------------------ // // formatIParamValueElement() // // // // //------------------------------------------------------------------------------ Array& XmlWriter::formatIParamValueElement( Array& out, const char* name, const Array& body) { out << "\n"; out << body; out << "\n"; return out; } //------------------------------------------------------------------------------ // // formatErrorElement() // //------------------------------------------------------------------------------ Array XmlWriter::formatErrorElement( CimException::Code code, const char* description) { Array out; out << ""; return out; } //------------------------------------------------------------------------------ // // appendBooleanParameter() // //------------------------------------------------------------------------------ Array& XmlWriter::appendBooleanParameter( Array& out, const char* name, Boolean flag) { Array tmp; tmp << "" << (flag ? "TRUE" : "FALSE") << "\n"; return formatIParamValueElement(out, name, tmp); } //------------------------------------------------------------------------------ // // appendClassNameParameter() // //------------------------------------------------------------------------------ Array& XmlWriter::appendClassNameParameter( Array& out, const char* name, const String& className) { Array tmp; appendClassNameElement(tmp, className); return formatIParamValueElement(out, name, tmp); } //------------------------------------------------------------------------------ // // appendQualifierNameParameter() // //------------------------------------------------------------------------------ Array& XmlWriter::appendQualifierNameParameter( Array& out, const char* name, const String& qualifierName) { // // // ATTN: notice that there is really no way to pass a qualifier name // as an IPARAMVALUE element according to the spec (look above). So we // just pass it as a class name. An answer must be obtained later. Array tmp; appendClassNameElement(tmp, qualifierName); return formatIParamValueElement(out, name, tmp); } //------------------------------------------------------------------------------ // // appendClassParameter() // //------------------------------------------------------------------------------ Array& XmlWriter::appendClassParameter( Array& out, const char* parameterName, const ConstCIMClass& cimClass) { Array tmp; cimClass.toXml(tmp); return formatIParamValueElement(out, parameterName, tmp); } //------------------------------------------------------------------------------ // // appendInstanceNameParameter() // //------------------------------------------------------------------------------ Array& XmlWriter::appendInstanceNameParameter( Array& out, const char* parameterName, const CIMReference& instanceName) { Array tmp; instanceName.instanceNameToXml(tmp); return formatIParamValueElement(out, parameterName, tmp); } //------------------------------------------------------------------------------ // // appendClassParameter() // //------------------------------------------------------------------------------ Array& XmlWriter::appendQualifierDeclarationParameter( Array& out, const char* parameterName, const CIMConstQualifierDecl& qualifierDecl) { Array tmp; qualifierDecl.toXml(tmp); return formatIParamValueElement(out, parameterName, tmp); } //------------------------------------------------------------------------------ // // appendClassNameElement() // //------------------------------------------------------------------------------ Array& XmlWriter::appendClassNameElement( Array& out, const String& className) { return out << "\n"; } //------------------------------------------------------------------------------ // // appendInstanceNameElement() // //------------------------------------------------------------------------------ Array& XmlWriter::appendInstanceNameElement( Array& out, const CIMReference& instanceName) { instanceName.instanceNameToXml(out); return out; } //------------------------------------------------------------------------------ // // _printAttributes() // //------------------------------------------------------------------------------ static void _printAttributes( std::ostream& os, const XmlAttribute* attributes, Uint32 attributeCount) { for (Uint32 i = 0; i < attributeCount; i++) { os << attributes[i].name << "="; os << '"'; AppendSpecial(os, attributes[i].value); os << '"'; if (i + 1 != attributeCount) os << ' '; } } //------------------------------------------------------------------------------ // // _indent() // //------------------------------------------------------------------------------ static void _indent(std::ostream& os, Uint32 level, Uint32 indentChars) { Uint32 n = level * indentChars; for (Uint32 i = 0; i < n; i++) os << ' '; } //------------------------------------------------------------------------------ // // indentedPrint() // //------------------------------------------------------------------------------ void XmlWriter::indentedPrint( std::ostream& os, const char* text, Uint32 indentChars) { char* tmp = strcpy(new char[strlen(text) + 1], text); XmlParser parser(tmp); XmlEntry entry; Stack stack; while (parser.next(entry)) { switch (entry.type) { case XmlEntry::XML_DECLARATION: { _indent(os, stack.getSize(), indentChars); os << ""; break; } case XmlEntry::START_TAG: { _indent(os, stack.getSize(), indentChars); os << "<" << entry.text; if (entry.attributeCount) os << ' '; _printAttributes(os, entry.attributes, entry.attributeCount); os << ">"; stack.push(entry.text); break; } case XmlEntry::EMPTY_TAG: { _indent(os, stack.getSize(), indentChars); os << "<" << entry.text << " "; _printAttributes(os, entry.attributes, entry.attributeCount); os << "/>"; break; } case XmlEntry::END_TAG: { if (!stack.isEmpty() && strcmp(stack.top(), entry.text) == 0) stack.pop(); _indent(os, stack.getSize(), indentChars); os << ""; break; } case XmlEntry::COMMENT: { _indent(os, stack.getSize(), indentChars); os << ""; break; } case XmlEntry::CONTENT: { _indent(os, stack.getSize(), indentChars); AppendSpecial(os, entry.text); break; } case XmlEntry::CDATA: { _indent(os, stack.getSize(), indentChars); os << ""; break; } case XmlEntry::DOCTYPE: { _indent(os, stack.getSize(), indentChars); os << ""; break; } } os << std::endl; } delete [] tmp; } //------------------------------------------------------------------------------ // // XmlWriter::getNextMessageId() // //------------------------------------------------------------------------------ Uint32 XmlWriter::getNextMessageId() { // ATTN: make thread-safe: static Uint32 messageId = 1000; messageId++; if (messageId < 1000) messageId = 1001; return messageId; } //------------------------------------------------------------------------------ // // XmlWriter::formatSimpleReqMessage() // //------------------------------------------------------------------------------ Array XmlWriter::formatSimpleReqMessage( const char* host, const String& nameSpace, const char* iMethodName, const Array& body) { return XmlWriter::formatMPostHeader( host, "MethodCall", iMethodName, nameSpace, XmlWriter::formatMessageElement( XmlWriter::getNextMessageId(), XmlWriter::formatSimpleReqElement( XmlWriter::formatIMethodCallElement( iMethodName, nameSpace, body)))); } Array XmlWriter::formatSimpleRspMessage( const char* iMethodName, const Array& body) { return XmlWriter::formatMethodResponseHeader( XmlWriter::formatMessageElement( XmlWriter::getNextMessageId(), XmlWriter::formatSimpleRspElement( XmlWriter::formatIMethodResponseElement( iMethodName, XmlWriter::formatIReturnValueElement(body))))); } PEGASUS_NAMESPACE_END