Return to WsmWriter.cpp CVS log | Up to [Pegasus] / pegasus / src / Pegasus / WsmServer |
File: [Pegasus] / pegasus / src / Pegasus / WsmServer / WsmWriter.cpp
(download)
Revision: 1.10, Mon Nov 30 16:49:50 2009 UTC (14 years, 7 months ago) by mike Branch: MAIN CVS Tags: TASK_PEP317_1JUNE_2013, TASK-PEP348_SCMO-merged_out_from_trunk, TASK-PEP317_pullop-root, RELEASE_2_11_2-RC1, RELEASE_2_11_2, RELEASE_2_11_1-RC1, RELEASE_2_11_1, RELEASE_2_11_0-RC1, RELEASE_2_11_0-FC, RELEASE_2_11_0, RELEASE_2_11-root, RELEASE_2_11-branch, RELEASE_2_10_1-RC1, RELEASE_2_10_1, RELEASE_2_10_0-RC2, RELEASE_2_10_0-RC1, RELEASE_2_10_0, RELEASE_2_10-root, RELEASE_2_10-branch, BeforeUpdateToHeadOct82011 Branch point for: TASK-PEP317_pullop-branch Changes since 1.9: +118 -27 lines BUG#: 8647 TITLE: WS-Management Enhancements DESCRIPTION: WS-Management Enhancements: custom actions, enumerate with filter, and identify. |
//%LICENSE//////////////////////////////////////////////////////////////// // // Licensed to The Open Group (TOG) under one or more contributor license // 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 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. // ////////////////////////////////////////////////////////////////////////// // //%//////////////////////////////////////////////////////////////////////////// #include <cstdlib> #include <cstdio> #include <Pegasus/Common/Config.h> #include <Pegasus/Common/Constants.h> #include <Pegasus/Common/XmlWriter.h> #include <Pegasus/Common/Buffer.h> #include <Pegasus/Common/StrLit.h> #include <Pegasus/Common/StringConversion.h> #include "WsmConstants.h" #include "WsmUtils.h" #include "WsmWriter.h" #include "WsmSelectorSet.h" PEGASUS_NAMESPACE_BEGIN inline void _writeNewlineForReadability(Buffer& out) { // Uncomment this statement for XML response readability. // out << '\n'; } // Append something like this to buffer: "<class:" static inline void _appendStartPrefix(Buffer& out, const char* ns) { out.append('<'); out.append(ns, strlen(ns)); out.append(':'); } // Append something like this to buffer: "</class:" static inline void _appendEndPrefix(Buffer& out, const char* ns) { out.append('<'); out.append('/'); out.append(ns, strlen(ns)); out.append(':'); } //----------------------------------------------------------------------------- // // WsmWriter::formatHttpErrorRspMessage() // //----------------------------------------------------------------------------- Buffer WsmWriter::formatHttpErrorRspMessage( const String& status, const String& cimError, const String& errorDetail) { return XmlWriter::formatHttpErrorRspMessage(status, cimError, errorDetail); } void WsmWriter::appendSoapFaultHeaders( Buffer& out, const SoapNotUnderstoodFault& fault, const String& action, const String& messageId, const String& relatesTo) { // Append the 'NotUnderstood' tag out << STRLIT("<"); out << WsmNamespaces::supportedNamespaces[ WsmNamespaces::SOAP_ENVELOPE].localName; out << STRLIT(":NotUnderstood qname=\""); if (fault.getNamespace().size()) { out << STRLIT("ns:"); } out << fault.getHeaderName(); out << STRLIT("\""); if (fault.getNamespace().size()) { out << STRLIT(" xmlns:ns=\""); out << fault.getNamespace(); out << STRLIT("\""); } out << STRLIT("/>"); _writeNewlineForReadability(out); appendSoapHeader(out, action, messageId, relatesTo); } void WsmWriter::appendSoapFaultBody( Buffer& out, const SoapNotUnderstoodFault& fault) { ContentLanguageList msgLang = fault.getMessageLanguage(); appendStartTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Fault")); appendStartTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Code")); String codeValue = String(WsmNamespaces::supportedNamespaces[ WsmNamespaces::SOAP_ENVELOPE].localName) + String(":MustUnderstand"); appendTagValue( out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Value"), codeValue); appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Code")); String msg = fault.getMessage(); if (msg.size() != 0) { String lang; if (msgLang.size() == 0) lang = "en-US"; else lang = msgLang.getLanguageTag(0).toString(); appendStartTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Reason")); appendTagValue(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Text"), msg, "xml:lang", lang); appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Reason")); } appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Fault")); } void WsmWriter::appendWsmFaultBody( Buffer& out, const WsmFault& fault) { ContentLanguageList reasonLang = fault.getReasonLanguage(); appendStartTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Fault")); appendStartTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Code")); appendTagValue(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Value"), fault.getCode()); appendStartTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Subcode")); appendTagValue(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Value"), fault.getSubcode()); appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Subcode")); appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Code")); String reason = fault.getReason(); if (reason.size() != 0) { String lang; if (reasonLang.size() == 0) lang = "en-US"; else lang = reasonLang.getLanguageTag(0).toString(); appendStartTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Reason")); appendTagValue(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Text"), reason, "xml:lang", lang); appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Reason")); } String detail = fault.getFaultDetail(); if (detail.size() != 0) { appendStartTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Detail")); appendTagValue( out, WsmNamespaces::WS_MAN, STRLIT("FaultDetail"), detail); appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Detail")); } appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Fault")); } void WsmWriter::appendInstanceElement( Buffer& out, const String& resourceUri, WsmInstance& instance, const char* ns, Boolean isEmbedded) { size_t nsLength = strlen(ns); // Class opening element: _appendStartPrefix(out, ns); out << instance.getClassName(); out << STRLIT(" xmlns:"); out.append(ns, nsLength); out << STRLIT("=\""); out << WsmUtils::getRootResourceUri(resourceUri); out << STRLIT("/") << instance.getClassName(); out << STRLIT("\""); // DSP0230, section 7.2.5.2. The property element MUST contain an // xsi:type attribute with the XSD type of the class of the instance // (see section 7.3.1). if (isEmbedded) { out << STRLIT(" "); out << WsmNamespaces::supportedNamespaces[ WsmNamespaces::XML_SCHEMA_INSTANCE].localName; out << STRLIT(":type=\""); out << instance.getClassName(); out << STRLIT("_Type\""); } out << STRLIT(">"); _writeNewlineForReadability(out); // Sort properties before writing them out instance.sortProperties(); // Properties: for (Uint32 i = 0, n = instance.getPropertyCount(); i < n; i++) appendPropertyElement(out, resourceUri, instance.getProperty(i), ns); // Class closing element: _appendEndPrefix(out, ns); out << instance.getClassName() << STRLIT(">"); _writeNewlineForReadability(out); } void WsmWriter::appendPropertyElement( Buffer& out, const String& resourceUri, WsmProperty& property, const char* ns) { WsmValue val = property.getValue(); String propName = property.getName(); // Form start element prefix. For example: "<class:" Buffer startBuffer; _appendStartPrefix(startBuffer, ns); StrLit start(startBuffer.getData(), startBuffer.size()); // Form end element prefix. For example: "</class:" Buffer endBuffer; _appendEndPrefix(endBuffer, ns); StrLit end(endBuffer.getData(), endBuffer.size()); if (val.isNull()) { out << start << propName; out << " " << WsmNamespaces::supportedNamespaces[ WsmNamespaces::XML_SCHEMA_INSTANCE].localName; out << STRLIT(":nil=\"true\"/>"); return; } if (val.isArray()) { switch (val.getType()) { case WSMTYPE_REFERENCE: { Array<WsmEndpointReference> eprs; val.get(eprs); for (Uint32 i = 0, n = eprs.size(); i < n; i++) { out << start << propName << STRLIT(">"); _writeNewlineForReadability(out); appendEPRElement(out, eprs[i]); out << end << propName << STRLIT(">"); _writeNewlineForReadability(out); } break; } case WSMTYPE_INSTANCE: { Array<WsmInstance> instances; val.get(instances); for (Uint32 i = 0, n = instances.size(); i < n; i++) { out << start << propName << STRLIT(">"); _writeNewlineForReadability(out); appendInstanceElement(out, resourceUri, instances[i], PEGASUS_INSTANCE_NS, true); out << end << propName << STRLIT(">"); _writeNewlineForReadability(out); } break; } case WSMTYPE_OTHER: { Array<String> strs; val.get(strs); for (Uint32 i = 0, n = strs.size(); i < n; i++) { out << start << propName << STRLIT(">"); _writeNewlineForReadability(out); appendStringElement(out, strs[i]); out << end << propName << STRLIT(">"); _writeNewlineForReadability(out); } break; } default: { PEGASUS_ASSERT(0); } } } else { switch (val.getType()) { case WSMTYPE_REFERENCE: { WsmEndpointReference epr; val.get(epr); out << start << propName << STRLIT(">"); _writeNewlineForReadability(out); appendEPRElement(out, epr); out << end << propName << STRLIT(">"); _writeNewlineForReadability(out); break; } case WSMTYPE_INSTANCE: { WsmInstance instance; val.get(instance); out << start << propName << STRLIT(">"); _writeNewlineForReadability(out); appendInstanceElement(out, resourceUri, instance, PEGASUS_INSTANCE_NS, true); out << end << propName << STRLIT(">"); _writeNewlineForReadability(out); break; } case WSMTYPE_OTHER: { String str; val.get(str); out << start << propName << STRLIT(">"); _writeNewlineForReadability(out); appendStringElement(out, str); out << end << propName << STRLIT(">"); _writeNewlineForReadability(out); break; } default: { PEGASUS_ASSERT(0); } } } } void WsmWriter::appendEPRElement( Buffer& out, const WsmEndpointReference& epr) { appendTagValue( out, WsmNamespaces::WS_ADDRESSING, STRLIT("Address"), epr.address); appendStartTag( out, WsmNamespaces::WS_ADDRESSING, STRLIT("ReferenceParameters")); appendTagValue( out, WsmNamespaces::WS_MAN, STRLIT("ResourceURI"), epr.resourceUri); if (epr.selectorSet && epr.selectorSet->selectors.size() > 0) { appendStartTag(out, WsmNamespaces::WS_MAN, STRLIT("SelectorSet")); for (Uint32 i = 0, n = epr.selectorSet->selectors.size(); i < n; i++) { WsmSelector selector = epr.selectorSet->selectors[i]; appendStartTag(out, WsmNamespaces::WS_MAN, STRLIT("Selector"), "Name", selector.name); if (selector.type == WsmSelector::EPR) { appendStartTag(out, WsmNamespaces::WS_ADDRESSING, STRLIT("EndpointReference")); appendEPRElement(out, selector.epr); appendEndTag(out, WsmNamespaces::WS_ADDRESSING, STRLIT("EndpointReference")); } else { XmlGenerator::appendSpecial(out, selector.value); _writeNewlineForReadability(out); } appendEndTag(out, WsmNamespaces::WS_MAN, STRLIT("Selector")); } appendEndTag(out, WsmNamespaces::WS_MAN, STRLIT("SelectorSet")); } appendEndTag( out, WsmNamespaces::WS_ADDRESSING, STRLIT("ReferenceParameters")); } void WsmWriter::appendStringElement( Buffer& out, const String& str) { XmlGenerator::appendSpecial(out, str); _writeNewlineForReadability(out); } void WsmWriter::appendStartTag( Buffer& out, WsmNamespaces::Type nsType, const StrLit& tagName, const char* attrName, const String& attrValue) { out << STRLIT("<"); out << WsmNamespaces::supportedNamespaces[nsType].localName; out << STRLIT(":") << tagName; if (attrName) { out << STRLIT(" ") << attrName << STRLIT("="); out << STRLIT("\"") << attrValue << STRLIT("\""); } out << STRLIT(">"); _writeNewlineForReadability(out); } void WsmWriter::appendEndTag( Buffer& out, WsmNamespaces::Type nsType, const StrLit& tagName) { out << STRLIT("</"); out << WsmNamespaces::supportedNamespaces[nsType].localName; out << STRLIT(":") << tagName << STRLIT(">"); _writeNewlineForReadability(out); } void WsmWriter::appendEmptyTag( Buffer& out, WsmNamespaces::Type nsType, const StrLit& tagName) { out << STRLIT("<"); out << WsmNamespaces::supportedNamespaces[nsType].localName; out << STRLIT(":") << tagName << STRLIT("/>"); _writeNewlineForReadability(out); } void WsmWriter::appendTagValue( Buffer& out, WsmNamespaces::Type nsType, const StrLit& tagName, const String& value, const char* attrName, const String& attrValue) { appendStartTag(out, nsType, tagName, attrName, attrValue); out << value; _writeNewlineForReadability(out); appendEndTag(out, nsType, tagName); } void WsmWriter::appendHTTPResponseHeader( Buffer& out, const String& action, HttpMethod httpMethod, Boolean omitXMLProcessingInstruction, const ContentLanguageList& contentLanguages, Boolean isFault, Uint32 contentLength) { if (isFault) { out << STRLIT("HTTP/1.1 " HTTP_STATUS_INTERNALSERVERERROR "\r\n"); } else { out << STRLIT("HTTP/1.1 " HTTP_STATUS_OK "\r\n"); } out << STRLIT("Content-Type: application/soap+xml;charset=UTF-8\r\n"); OUTPUT_CONTENTLENGTH(out, contentLength); if (contentLanguages.size() > 0) { out << STRLIT("Content-Language: ") << contentLanguages << STRLIT("\r\n"); } if (httpMethod == HTTP_METHOD_M_POST) { char nn[] = { '0' + (rand() % 10), '0' + (rand() % 10), '\0' }; out << STRLIT("Ext:\r\n"); out << STRLIT("Cache-Control: no-cache\r\n"); out << STRLIT("Man: urn:schemas-xmlsoap-org:soap.v1; ns=") << nn << STRLIT("\r\n"); out << nn << STRLIT("-SOAPAction: ") << action << STRLIT("\r\n"); } else { out << STRLIT("SOAPAction: "); out << action << STRLIT("\r\n"); } out << STRLIT("\r\n"); if (!omitXMLProcessingInstruction) { out << STRLIT("<?xml version=\"1.0\" encoding=\"utf-8\" ?>"); } _writeNewlineForReadability(out); } void WsmWriter::appendSoapEnvelopeStart( Buffer& out, const ContentLanguageList& contentLanguages) { out << STRLIT("<"); out << WsmNamespaces::supportedNamespaces[ WsmNamespaces::SOAP_ENVELOPE].localName; out << STRLIT(":Envelope"); // DSP0226 R6.3-4: In any response, event, or singleton message, the // service should include the xml:lang attribute in the s:Envelope (or // other elements) to signal to the receiver that localized content // appears in the body of the message. This attribute may be omitted // if no descriptive content appears in the body. Including the // xml:lang attribute is not an error, even if no descriptive content // occurs. if (contentLanguages.size() > 0) { out << STRLIT(" xml:lang=\""); out << contentLanguages.getLanguageTag(0).toString() << STRLIT("\""); } for (Uint32 i = 0; i < WsmNamespaces::LAST; i++) { _writeNewlineForReadability(out); out << STRLIT(" xmlns:"); out << WsmNamespaces::supportedNamespaces[i].localName; out << STRLIT("=\""); out << WsmNamespaces::supportedNamespaces[i].extendedName; out << STRLIT("\""); } out << STRLIT(">"); _writeNewlineForReadability(out); } void WsmWriter::appendSoapEnvelopeEnd(Buffer& out) { appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Envelope")); } void WsmWriter::appendSoapHeaderStart(Buffer& out) { appendStartTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Header")); } void WsmWriter::appendSoapHeaderEnd(Buffer& out) { appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Header")); } void WsmWriter::appendSoapBodyStart(Buffer& out) { appendStartTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Body")); } void WsmWriter::appendSoapBodyEnd(Buffer& out) { appendEndTag(out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Body")); } void WsmWriter::appendSoapHeader( Buffer& out, const String& action, const String& messageId, const String& relatesTo) { // Add <wsa:To> entry appendStartTag(out, WsmNamespaces::WS_ADDRESSING, STRLIT("To")); // Note: The reply is always written on the requestor's connection. // The WsmRequestDecoder checks that the wsa:ReplyTo header is anonymous. out << STRLIT(WSM_ADDRESS_ANONYMOUS); _writeNewlineForReadability(out); appendEndTag(out, WsmNamespaces::WS_ADDRESSING, STRLIT("To")); // Add <wsa:Action> entry appendTagValue(out, WsmNamespaces::WS_ADDRESSING, STRLIT("Action"), action); // Add <wsa:MessageID> entry appendTagValue( out, WsmNamespaces::WS_ADDRESSING, STRLIT("MessageID"), messageId); // Add <wsa:RelatesTo> entry only if necessary. An empty relates to tag // breaks some WS-Management clients (such as WinRM). if (relatesTo.size()) { appendTagValue( out, WsmNamespaces::WS_ADDRESSING, STRLIT("RelatesTo"), relatesTo); } } void WsmWriter::appendInvokeOutputElement( Buffer& out, const String& resourceUri, const String& className, const String& methodName, WsmInstance& instance, const char* ns) { CString mn(methodName.getCString()); // Form tagname. Buffer tagBuffer; tagBuffer.append(ns, strlen(ns)); tagBuffer.append(':'); tagBuffer.append(mn, strlen(mn)); tagBuffer.append("_OUTPUT", 7); const char* tag = tagBuffer.getData(); size_t tagSize = tagBuffer.size(); // Write start tag. out.append('<'); out.append(tag, tagSize); out << STRLIT(" xmlns:"); out.append(ns, strlen(ns)); out << STRLIT("=\""); out << WsmUtils::getRootResourceUri(resourceUri); out << STRLIT("/"); out << className; out << STRLIT("\">"); _writeNewlineForReadability(out); // Write properties: for (Uint32 i = 0, n = instance.getPropertyCount(); i < n; i++) appendPropertyElement(out, resourceUri, instance.getProperty(i), ns); // Write end tag. out << STRLIT("</"); out.append(tag, tagSize); out.append('>'); _writeNewlineForReadability(out); } PEGASUS_NAMESPACE_END
No CVS admin address has been configured |
Powered by ViewCVS 0.9.2 |