BUG#: 8647 TASK-PEP348_SCMO-merged_out_from_trunk
authormike <mike>
Mon, 30 Nov 2009 16:49:46 +0000 (16:49 +0000)
committermike <mike>
Mon, 30 Nov 2009 16:49:46 +0000 (16:49 +0000)
TITLE: WS-Management Enhancements

DESCRIPTION: WS-Management Enhancements: custom actions, enumerate with filter, and identify.

33 files changed:
src/Pegasus/Common/Print.cpp
src/Pegasus/Common/Print.h
src/Pegasus/Common/XmlParser.cpp
src/Pegasus/Common/XmlParser.h
src/Pegasus/Common/XmlReader.cpp
src/Pegasus/Common/tests/XmlParser/XmlParser.cpp
src/Pegasus/WsmServer/CimToWsmResponseMapper.cpp
src/Pegasus/WsmServer/CimToWsmResponseMapper.h
src/Pegasus/WsmServer/Makefile
src/Pegasus/WsmServer/SoapResponse.cpp
src/Pegasus/WsmServer/WsmConstants.h
src/Pegasus/WsmServer/WsmReader.cpp
src/Pegasus/WsmServer/WsmReader.h
src/Pegasus/WsmServer/WsmRequest.h
src/Pegasus/WsmServer/WsmRequestDecoder.cpp
src/Pegasus/WsmServer/WsmRequestDecoder.h
src/Pegasus/WsmServer/WsmResponse.h
src/Pegasus/WsmServer/WsmResponseEncoder.cpp
src/Pegasus/WsmServer/WsmResponseEncoder.h
src/Pegasus/WsmServer/WsmToCimRequestMapper.cpp
src/Pegasus/WsmServer/WsmToCimRequestMapper.h
src/Pegasus/WsmServer/WsmUtils.cpp
src/Pegasus/WsmServer/WsmUtils.h
src/Pegasus/WsmServer/WsmValue.cpp
src/Pegasus/WsmServer/WsmValue.h
src/Pegasus/WsmServer/WsmWriter.cpp
src/Pegasus/WsmServer/WsmWriter.h
src/Pegasus/WsmServer/tests/CimToWsmMapper/CimToWsmMapper.cpp
src/Pegasus/WsmServer/tests/WsmReader/WsmReader.cpp
src/Pegasus/WsmServer/tests/WsmReader/wsfilter.xml [new file with mode: 0644]
src/Pegasus/WsmServer/tests/WsmReader/wsidentify.xml [new file with mode: 0644]
src/Pegasus/WsmServer/tests/WsmReader/wsinvoke.xml [new file with mode: 0644]
src/Pegasus/WsmServer/tests/WsmWriter/WsmWriter.cpp

index 0eed843b3de7f792546eb74f673c58aac80c3757..5c1178f94b9b11965e9b7bac788804a3bab1a250 100644 (file)
@@ -73,44 +73,62 @@ static const char* _typeStrings[] =
 };
 
 template<class T>
-static void _print(ostream& os, const T& x)
+struct Print
 {
-    os << x;
-}
+    static void func(ostream& os, const T& x)
+    {
+        os << x;
+    }
+};
 
 PEGASUS_TEMPLATE_SPECIALIZATION
-void _print(ostream& os, const Boolean& x)
+struct Print<Boolean>
 {
-    os << (x ? "true" : "false");
-}
+    static void func(ostream& os, const Boolean& x)
+    {
+        os << (x ? "true" : "false");
+    }
+};
 
 PEGASUS_TEMPLATE_SPECIALIZATION
-void _print(ostream& os, const Uint64& x)
+struct Print<Uint64>
 {
-    char buf[32];
-    sprintf(buf, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", x);
-    os << buf;
-}
+    static void func(ostream& os, const Uint64& x)
+    {
+        char buf[32];
+        sprintf(buf, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", x);
+        os << buf;
+    }
+};
 
 PEGASUS_TEMPLATE_SPECIALIZATION
-void _print(ostream& os, const Sint64& x)
+struct Print<Sint64>
 {
-    char buf[32];
-    sprintf(buf, "%" PEGASUS_64BIT_CONVERSION_WIDTH "d", x);
-    os << buf;
-}
+    static void func(ostream& os, const Sint64& x)
+    {
+        char buf[32];
+        sprintf(buf, "%" PEGASUS_64BIT_CONVERSION_WIDTH "d", x);
+        os << buf;
+    }
+};
 
 PEGASUS_TEMPLATE_SPECIALIZATION
-void _print(ostream& os, const Char16& x)
+struct Print<Uint16>
 {
-    os << Uint16(x);
-}
+    static void func(ostream& os, const Char16& x)
+    {
+        os << Uint16(x);
+    }
+};
 
 PEGASUS_TEMPLATE_SPECIALIZATION
-void _print(ostream& os, const CIMDateTime& x)
+struct Print<CIMDateTime>
 {
-    os << x.toString();
-}
+    static void func(ostream& os, const CIMDateTime& x)
+    {
+        os << x.toString();
+    }
+};
 
 template<class T>
 struct PrintArray
@@ -124,7 +142,8 @@ struct PrintArray
 
         for (Uint32 i = 0; i < a.size(); i++)
         {
-            _print<T>(os, a[i]);
+            const T& r = a[i];
+            Print<T>::func(os, r);
 
             if (i + 1 != a.size())
                 os << ", ";
@@ -143,7 +162,7 @@ struct PrintScalar
     {
         T x;
         cv.get(x);
-        _print<T>(os, x);
+        Print<T>::func(os, x);
         os << endl;
     }
 };
@@ -508,6 +527,34 @@ void PEGASUS_COMMON_LINKAGE PrintQualifierDecl(
     os << Ind(n) << "}" << endl;
 }
 
+PEGASUS_COMMON_LINKAGE void PrintParamValue(
+    PEGASUS_STD(ostream)& os,
+    const CIMParamValue& x,
+    Uint32 n)
+{
+    os << Ind(n) << "CIMParamValue" << endl;
+    os << Ind(n) << "{" << endl;
+    os << Ind(n) << "    name=" << x.getParameterName() << endl;
+    PrintValue(os, x.getValue(), n + 1);
+    os << Ind(n) << "}" << endl;
+}
+
+PEGASUS_COMMON_LINKAGE void PrintParamValueArray(
+    PEGASUS_STD(ostream)& os,
+    const Array<CIMParamValue>& x,
+    Uint32 n)
+{
+    os << Ind(n) << "Array<CIMParamValue>" << endl;
+    os << Ind(n) << "{" << endl;
+
+    for (Uint32 i = 0; i < x.size(); i++)
+    {
+        PrintParamValue(os, x[i], n + 1);
+    }
+
+    os << Ind(n) << "}" << endl;
+}
+
 #endif /* defined(PEGASUS_DEBUG) */
 
 PEGASUS_NAMESPACE_END
index 743231ec6eec50e283864127acff450109d103a1..437dff6b32df3fdddc3afd0cc82db914cd76ea8e 100644 (file)
@@ -35,6 +35,7 @@
 #include <Pegasus/Common/Config.h>
 #include <Pegasus/Common/CIMInstance.h>
 #include <Pegasus/Common/CIMQualifierDecl.h>
+#include <Pegasus/Common/CIMParamValue.h>
 #include <Pegasus/Common/Linkage.h>
 #include <iostream>
 
@@ -85,6 +86,16 @@ PEGASUS_COMMON_LINKAGE void PrintQualifierDecl(
     const CIMConstQualifierDecl& x,
     Uint32 n = 0);
 
+PEGASUS_COMMON_LINKAGE void PrintParamValue(
+    PEGASUS_STD(ostream)& os, 
+    const CIMParamValue& x, 
+    Uint32 n = 0);
+
+PEGASUS_COMMON_LINKAGE void PrintParamValueArray(
+    PEGASUS_STD(ostream)& os, 
+    const Array<CIMParamValue>& x, 
+    Uint32 n = 0);
+
 PEGASUS_NAMESPACE_END
 
 #endif /* Pegasus_Print_h */
index fdd7a24129d92588f9bd15231c01df942e3d77ef..a6f2079e49605c4eaa4d5d537f99bbba50323d4f 100644 (file)
@@ -306,14 +306,15 @@ XmlSemanticError::XmlSemanticError(
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-XmlParser::XmlParser(char* text, XmlNamespace* ns)
+XmlParser::XmlParser(char* text, XmlNamespace* ns, Boolean hideEmptyTags)
     : _line(1),
       _current(text),
       _restoreChar('\0'),
       _foundRoot(false),
       _supportedNamespaces(ns),
       // Start valid indexes with -2. -1 is reserved for not found.
-      _currentUnsupportedNSType(-2)
+      _currentUnsupportedNSType(-2),
+      _hideEmptyTags(hideEmptyTags)
 {
 }
 
@@ -554,7 +555,7 @@ static inline void _normalizeAttributeValue(
     }
 }
 
-Boolean XmlParser::next(
+Boolean XmlParser::_next(
     XmlEntry& entry,
     Boolean includeComment)
 {
@@ -728,6 +729,38 @@ Boolean XmlParser::next(
     return true;
 }
 
+Boolean XmlParser::next(XmlEntry& entry, Boolean includeComment)
+{
+    if (_hideEmptyTags)
+    {
+        // Get the next tag.
+
+        if (!_next(entry, includeComment))
+            return false;
+
+        // If an EMPTY_TAG is encountered, then convert it to a START_TAG and 
+        // push a matching END_TAG on the put-back stack. This hides every
+        // EMPTY_TAG from the caller.
+
+        if (entry.type == XmlEntry::EMPTY_TAG)
+        {
+            entry.type = XmlEntry::START_TAG;
+
+            XmlEntry tmp;
+            tmp.type = XmlEntry::END_TAG;
+            tmp.text = entry.text;
+            tmp.nsType = entry.nsType;
+            tmp.localName = entry.localName;
+
+            _putBackStack.push(tmp);
+        }
+
+        return true;
+    }
+    else
+        return _next(entry, includeComment);
+}
+
 // Get the namespace type of the given tag
 int XmlParser::_getNamespaceType(const char* tag)
 {
index 77ef281d1e8aaa0b37eb48e2cb7c048c846a8058..4d1e1d67cd8a7ce56d66026a32541c36050e31a4 100644 (file)
@@ -166,7 +166,12 @@ public:
 
     // Warning: this constructor modifies the text.
 
-    XmlParser(char* text, XmlNamespace* ns = 0);
+    /** If hideEmptyTags if true, next() hides empty tags from the caller.
+        Instead, next() returns a fake start tag. The subsequent next() call
+        returns a fake end tag. This relieves the caller from having to do
+        special processing of empty tags, which can be tricky and error-prone.
+    */
+    XmlParser(char* text, XmlNamespace* ns = 0, Boolean hideEmptyTags = false);
 
     /** Comments are returned with entry if includeComment is true else
         XmlParser ignores comments. Default is false.
@@ -183,8 +188,14 @@ public:
 
     XmlNamespace* getNamespace(int nsType);
 
+    void setHideEmptyTags(bool flag) { _hideEmptyTags = flag; }
+
+    bool getHideEmptyTags(bool flag) const { return _hideEmptyTags; }
+
 private:
 
+    Boolean _next(XmlEntry& entry, Boolean includeComment = false);
+
     Boolean _getElementName(char*& p, const char*& localName);
 
     Boolean _getOpenElementName(
@@ -216,6 +227,7 @@ private:
     XmlNamespace* _supportedNamespaces;
     Stack<XmlNamespace> _nameSpaces;
     int _currentUnsupportedNSType;
+    Boolean _hideEmptyTags;
 };
 
 PEGASUS_COMMON_LINKAGE void XmlAppendCString(
index a1bbf996b171ba531bb66f9bc624d74a693dd435..5b66dfa1a5fe4342b7eb82a21dad1f73d9399587 100644 (file)
@@ -204,7 +204,7 @@ Boolean XmlReader::expectContentOrCData(
     {
         MessageLoaderParms mlParms(
             "Common.XmlReader.EXPECTED_CDATA",
-            "Expected content of CDATA");
+            "Expected content or CDATA");
         throw XmlValidationError(parser.getLine(), mlParms);
     }
 
index b07581e04c141b4f135dce979c27645c3378e129..ca9efc901d9c350cb8260a49c3c67dbb6da4ef79 100644 (file)
@@ -40,14 +40,14 @@ PEGASUS_USING_STD;
 
 Boolean verbose = false;
 
-static void _parseFile(const char* fileName)
+static void _parseFile(const char* fileName, Boolean hideEmptyTags)
 {
     // cout << "Parsing: " << fileName << endl;
 
     Buffer text;
     FileSystem::loadFileToMemory(text, fileName);
 
-    XmlParser parser((char*)text.getData());
+    XmlParser parser((char*)text.getData(), 0, hideEmptyTags);
 
     XmlEntry entry;
 
@@ -90,7 +90,7 @@ static void _parseFile(const char* fileName)
         PEGASUS_ASSERT(caughtException); \
     } while(0)
 
-void testNamespaceSupport()
+void testNamespaceSupport(Boolean hideEmptyTags)
 {
     XmlNamespace testNamespaces[] =
     {
@@ -131,7 +131,7 @@ void testNamespaceSupport()
             " <d:tag xmlns:d=\"urn:x\"/>"
             " <b:tag xmlns:b=\"urn:1\"/>"
             "</a:tag>";
-        XmlParser p(xmlContent, testNamespaces);
+        XmlParser p(xmlContent, testNamespaces, hideEmptyTags);
 
         // <a:tag xmlns:a=\"urn:0\" xmlns:b=\"urn:1\">
         PEGASUS_ASSERT(p.next(entry));
@@ -164,13 +164,28 @@ void testNamespaceSupport()
         PEGASUS_ASSERT(strcmp(attr->localName, "ignore") == 0);
         PEGASUS_ASSERT(strcmp(attr->value, "false") == 0);
 
-        // <tag/>
+        // <tag>
         PEGASUS_ASSERT(p.next(entry));
-        PEGASUS_ASSERT(entry.type == XmlEntry::EMPTY_TAG);
+
+        if (hideEmptyTags)
+            PEGASUS_ASSERT(entry.type == XmlEntry::START_TAG);
+        else
+            PEGASUS_ASSERT(entry.type == XmlEntry::EMPTY_TAG);
+
         PEGASUS_ASSERT(!strcmp(entry.text, "tag"));
         PEGASUS_ASSERT(entry.nsType == 2);
         PEGASUS_ASSERT(!strcmp(entry.localName, "tag"));
 
+        if (hideEmptyTags)
+        {
+            // </tag>
+            PEGASUS_ASSERT(p.next(entry));
+            PEGASUS_ASSERT(entry.type == XmlEntry::END_TAG);
+            PEGASUS_ASSERT(!strcmp(entry.text, "tag"));
+            PEGASUS_ASSERT(entry.nsType == 2);
+            PEGASUS_ASSERT(!strcmp(entry.localName, "tag"));
+        }
+
         // </b:tag>
         PEGASUS_ASSERT(p.next(entry));
         PEGASUS_ASSERT(entry.type == XmlEntry::END_TAG);
@@ -209,17 +224,38 @@ void testNamespaceSupport()
         PEGASUS_ASSERT(entry.nsType == 0);
         PEGASUS_ASSERT(!strcmp(entry.localName, "tag"));
 
-        // <d:tag xmlns:d=\"urn:x\"/>
+        // <d:tag xmlns:d=\"urn:x\">
         PEGASUS_ASSERT(p.next(entry));
-        PEGASUS_ASSERT(entry.type == XmlEntry::EMPTY_TAG);
+
+        if (hideEmptyTags)
+            PEGASUS_ASSERT(entry.type == XmlEntry::START_TAG);
+        else
+            PEGASUS_ASSERT(entry.type == XmlEntry::EMPTY_TAG);
+
         PEGASUS_ASSERT(!strcmp(entry.text, "d:tag"));
         PEGASUS_ASSERT(entry.nsType == -2);
         PEGASUS_ASSERT(!strcmp(entry.localName, "tag"));
         PEGASUS_ASSERT(p.getNamespace(-2) != 0);
 
-        // <b:tag xmlns:b=\"urn:1\"/>
+        if (hideEmptyTags)
+        {
+            // </d:tag>
+            PEGASUS_ASSERT(p.next(entry));
+            PEGASUS_ASSERT(entry.type == XmlEntry::END_TAG);
+            PEGASUS_ASSERT(!strcmp(entry.text, "d:tag"));
+            PEGASUS_ASSERT(entry.nsType == -2);
+            PEGASUS_ASSERT(!strcmp(entry.localName, "tag"));
+            PEGASUS_ASSERT(p.getNamespace(-2) != 0);
+        }
+
+        // <b:tag xmlns:b=\"urn:1\">
         PEGASUS_ASSERT(p.next(entry));
-        PEGASUS_ASSERT(entry.type == XmlEntry::EMPTY_TAG);
+
+        if (hideEmptyTags)
+            PEGASUS_ASSERT(entry.type == XmlEntry::START_TAG);
+        else
+            PEGASUS_ASSERT(entry.type == XmlEntry::EMPTY_TAG);
+
         PEGASUS_ASSERT(!strcmp(entry.text, "b:tag"));
         PEGASUS_ASSERT(entry.nsType == 1);
         PEGASUS_ASSERT(!strcmp(entry.localName, "tag"));
@@ -228,6 +264,20 @@ void testNamespaceSupport()
         PEGASUS_ASSERT(p.getNamespace(1) != 0);
         PEGASUS_ASSERT(p.getNamespace(2) == 0);
 
+        if (hideEmptyTags)
+        {
+            // </b:tag xmlns:b=\"urn:1\">
+            PEGASUS_ASSERT(p.next(entry));
+            PEGASUS_ASSERT(entry.type == XmlEntry::END_TAG);
+            PEGASUS_ASSERT(!strcmp(entry.text, "b:tag"));
+            PEGASUS_ASSERT(entry.nsType == 1);
+            PEGASUS_ASSERT(!strcmp(entry.localName, "tag"));
+            PEGASUS_ASSERT(p.getNamespace(-2) == 0);
+            PEGASUS_ASSERT(p.getNamespace(0) != 0);
+            PEGASUS_ASSERT(p.getNamespace(1) != 0);
+            PEGASUS_ASSERT(p.getNamespace(2) == 0);
+        }
+
         // </a:tag>
         PEGASUS_ASSERT(p.next(entry));
         PEGASUS_ASSERT(entry.type == XmlEntry::END_TAG);
@@ -241,38 +291,38 @@ void testNamespaceSupport()
     // Test undeclared namespace
     {
         char xmlContent[] = "<a:tag xmlns:b=\"urn:1\"/>";
-        XmlParser p(xmlContent, testNamespaces);
+        XmlParser p(xmlContent, testNamespaces, hideEmptyTags);
         ASSERT_XML_EXCEPTION(p.next(entry));
     }
 
     // Test invalid QNames
     {
         char xmlContent[] = "<.a:tag xmlns:a=\"urn:0\"/>";
-        XmlParser p(xmlContent, testNamespaces);
+        XmlParser p(xmlContent, testNamespaces, hideEmptyTags);
         ASSERT_XML_EXCEPTION(p.next(entry));
     }
 
     {
         char xmlContent[] = "<a&:tag xmlns:a=\"urn:0\"/>";
-        XmlParser p(xmlContent, testNamespaces);
+        XmlParser p(xmlContent, testNamespaces, hideEmptyTags);
         ASSERT_XML_EXCEPTION(p.next(entry));
     }
 
     {
         char xmlContent[] = "<a:.tag xmlns:a=\"urn:0\"/>";
-        XmlParser p(xmlContent, testNamespaces);
+        XmlParser p(xmlContent, testNamespaces, hideEmptyTags);
         ASSERT_XML_EXCEPTION(p.next(entry));
     }
 
     {
         char xmlContent[] = "<a:ta:g xmlns:a=\"urn:0\"/>";
-        XmlParser p(xmlContent, testNamespaces);
+        XmlParser p(xmlContent, testNamespaces, hideEmptyTags);
         ASSERT_XML_EXCEPTION(p.next(entry));
     }
 
     {
         char xmlContent[] = "<a:ta";
-        XmlParser p(xmlContent, testNamespaces);
+        XmlParser p(xmlContent, testNamespaces, hideEmptyTags);
         ASSERT_XML_EXCEPTION(p.next(entry));
     }
 }
@@ -313,7 +363,8 @@ int main(int argc, char** argv)
     {
         try
         {
-            _parseFile(argv[i]);
+            _parseFile(argv[i], true);
+            _parseFile(argv[i], false);
         }
         catch (Exception& e)
         {
@@ -324,7 +375,8 @@ int main(int argc, char** argv)
 
     testWhitespaceHandling();
 
-    testNamespaceSupport();
+    testNamespaceSupport(true);
+    testNamespaceSupport(false);
 
     cout << argv[0] << " +++++ passed all tests" << endl;
 
index 7525e4836816675aff5f31297ab43a38ad0aecdd..3968b71d8b380e4e5d70a87ddae4b7f7e210789a 100644 (file)
@@ -37,6 +37,8 @@
 #include <Pegasus/Common/StringConversion.h>
 #include <Pegasus/Common/MessageLoader.h>
 #include <Pegasus/WsmServer/WsmConstants.h>
+#include <Pegasus/WQL/WQLSelectStatement.h>
+#include <Pegasus/WQL/WQLParser.h>
 #include "CimToWsmResponseMapper.h"
 
 #ifdef PEGASUS_OS_VMS
@@ -127,6 +129,14 @@ WsmResponse* CimToWsmResponseMapper::mapToWsmResponse(
                 }
                 break;
 
+            case WS_INVOKE:
+            {
+                wsmResponse.reset(_mapToWsInvokeResponse(
+                    (WsInvokeRequest*)wsmRequest,
+                    (CIMInvokeMethodResponseMessage*)message));
+                break;
+            }
+
             default:
                 PEGASUS_ASSERT(0);
                 break;
@@ -226,6 +236,8 @@ WsmFault CimToWsmResponseMapper::mapCimExceptionToWsmFault(
             break;
 
         default:
+            // Initialize to prevent uninitialized subcode error.
+            subcode = WsmFault::wsman_InternalError;
             PEGASUS_ASSERT(0);
     }
 
@@ -239,6 +251,7 @@ WxfGetResponse* CimToWsmResponseMapper::_mapToWxfGetResponse(
     WsmInstance wsmInstance;
 
     convertCimToWsmInstance(
+        wsmRequest->epr.resourceUri,
         response->getResponseData().getCimInstance(),
         wsmInstance,
         wsmRequest->epr.getNamespace());
@@ -270,7 +283,10 @@ WxfCreateResponse* CimToWsmResponseMapper::_mapToWxfCreateResponse(
 {
     WsmEndpointReference epr;
 
-    convertObjPathToEPR(response->instanceName, epr,
+    convertObjPathToEPR(
+        wsmRequest->epr.resourceUri,
+        response->instanceName,
+        epr,
         wsmRequest->epr.getNamespace());
 
     WxfCreateResponse* wsmResponse =
@@ -301,24 +317,79 @@ WsenEnumerateResponse*
 {
     Array<WsmInstance> instances;
     Array<WsmEndpointReference> EPRs;
-    Array<CIMInstance>& namedInstances = 
+    Array<CIMInstance>& namedInstances =
         response->getResponseData().getNamedInstances();
-    for (Uint32 i = 0; i < namedInstances.size(); i++)
+
+    if (wsmRequest->selectStatement)
     {
-        WsmInstance wsmInstance;
-        convertCimToWsmInstance(namedInstances[i], wsmInstance,
-            wsmRequest->epr.getNamespace());
-        instances.append(wsmInstance);
+        // Filter out unwanted instances:
+
+        for (Uint32 i = 0; i < namedInstances.size(); i++)
+        {
+            try
+            {
+                if (!wsmRequest->selectStatement->evaluate(namedInstances[i]))
+                    continue;
+            }
+            catch (...)
+            {
+                // This error is unreportable since all other instance
+                // would have to  be aborted.
+                continue;
+            }
+
+            CIMInstance instance = namedInstances[i].clone();
+
+            try
+            {
+                wsmRequest->selectStatement->applyProjection(instance, false);
+            }
+            catch (...)
+            {
+                // Ignore missing properties.
+                continue;
+            }
+
+            WsmInstance wsmInstance;
+            convertCimToWsmInstance(
+                wsmRequest->epr.resourceUri,
+                instance,
+                wsmInstance,
+                wsmRequest->epr.getNamespace());
+            instances.append(wsmInstance);
+        }
+
+        WsenEnumerateResponse* wsmResponse =
+            new WsenEnumerateResponse(
+                instances,
+                instances.size(),
+                wsmRequest,
+                _getContentLanguages(response->operationContext));
+
+        return wsmResponse;
     }
+    else
+    {
+        for (Uint32 i = 0; i < namedInstances.size(); i++)
+        {
+            WsmInstance wsmInstance;
+            convertCimToWsmInstance(
+                wsmRequest->epr.resourceUri,
+                namedInstances[i],
+                wsmInstance,
+                wsmRequest->epr.getNamespace());
+            instances.append(wsmInstance);
+        }
 
-    WsenEnumerateResponse* wsmResponse =
-        new WsenEnumerateResponse(
-            instances,
-            instances.size(),
-            wsmRequest,
-            _getContentLanguages(response->operationContext));
+        WsenEnumerateResponse* wsmResponse =
+            new WsenEnumerateResponse(
+                instances,
+                instances.size(),
+                wsmRequest,
+                _getContentLanguages(response->operationContext));
 
-    return wsmResponse;
+        return wsmResponse;
+    }
 }
 
 WsenEnumerateResponse*
@@ -333,12 +404,18 @@ WsenEnumerateResponse*
     for (Uint32 i = 0; i < namedInstances.size(); i++)
     {
         WsmInstance wsmInstance;
-        convertCimToWsmInstance(namedInstances[i], wsmInstance,
+        convertCimToWsmInstance(
+            wsmRequest->epr.resourceUri,
+            namedInstances[i],
+            wsmInstance,
             wsmRequest->epr.getNamespace());
         instances.append(wsmInstance);
 
         WsmEndpointReference epr;
-        convertObjPathToEPR(namedInstances[i].getPath(), epr,
+        convertObjPathToEPR(
+            wsmRequest->epr.resourceUri,
+            namedInstances[i].getPath(),
+            epr,
             wsmRequest->epr.getNamespace());
         EPRs.append(epr);
     }
@@ -363,7 +440,10 @@ CimToWsmResponseMapper::_mapToWsenEnumerateResponseEPR(
     for (Uint32 i = 0; i < response->instanceNames.size(); i++)
     {
         WsmEndpointReference epr;
-        convertObjPathToEPR(response->instanceNames[i], epr,
+        convertObjPathToEPR(
+            wsmRequest->epr.resourceUri,
+            response->instanceNames[i],
+            epr,
             wsmRequest->epr.getNamespace());
         EPRs.append(epr);
     }
@@ -378,7 +458,34 @@ CimToWsmResponseMapper::_mapToWsenEnumerateResponseEPR(
     return wsmResponse;
 }
 
+WsInvokeResponse* CimToWsmResponseMapper::_mapToWsInvokeResponse(
+    const WsInvokeRequest* wsmRequest,
+    const CIMInvokeMethodResponseMessage* response)
+{
+    WsmInstance wsmInstance;
+    String nameSpace = wsmRequest->epr.getNamespace();
+
+    convertCimToWsmParameters(
+        wsmRequest->epr.resourceUri,
+        nameSpace,
+        response->outParameters,
+        response->retValue,
+        wsmInstance);
+
+    WsInvokeResponse* wsmResponse =
+        new WsInvokeResponse(
+            nameSpace,
+            wsmRequest->className,
+            response->methodName.getString(),
+            wsmInstance,
+            wsmRequest,
+            _getContentLanguages(response->operationContext));
+
+    return wsmResponse;
+}
+
 void CimToWsmResponseMapper::convertCimToWsmInstance(
+    const String& resourceUri,
     const CIMConstInstance& cimInstance,
     WsmInstance& wsmInstance,
     const String& nameSpace)
@@ -392,7 +499,7 @@ void CimToWsmResponseMapper::convertCimToWsmInstance(
         const CIMValue& cimValue = cimProperty.getValue();
 
         WsmValue wsmValue;
-        convertCimToWsmValue(cimValue, wsmValue, nameSpace);
+        convertCimToWsmValue(resourceUri, cimValue, wsmValue, nameSpace);
 
         WsmProperty wsmProperty(propertyName, wsmValue);
         wsmInstance.addProperty(wsmProperty);
@@ -422,6 +529,7 @@ static void _convertCimToWsmArrayValue(
 }
 
 void CimToWsmResponseMapper::convertCimToWsmValue(
+     const String& resourceUri,
      const CIMValue& cimValue,
      WsmValue& wsmValue,
      const String& nameSpace)
@@ -538,7 +646,8 @@ void CimToWsmResponseMapper::convertCimToWsmValue(
                 for (Uint32 i = 0, n = objPaths.size(); i < n; i++)
                 {
                     WsmEndpointReference epr;
-                    convertObjPathToEPR(objPaths[i], epr, nameSpace);
+                    convertObjPathToEPR(resourceUri, objPaths[i], epr,
+                        nameSpace);
                     eprs.append(epr);
                 }
                 wsmValue.set(eprs);
@@ -556,6 +665,7 @@ void CimToWsmResponseMapper::convertCimToWsmValue(
                     {
                         WsmInstance wsmInstance;
                         convertCimToWsmInstance(
+                            resourceUri,
                             CIMInstance(cimObjects[i]),
                             wsmInstance,
                             nameSpace);
@@ -584,7 +694,10 @@ void CimToWsmResponseMapper::convertCimToWsmValue(
                 {
                     WsmInstance wsmInstance;
                     convertCimToWsmInstance(
-                        cimInstances[i], wsmInstance, nameSpace);
+                        resourceUri,
+                        cimInstances[i],
+                        wsmInstance,
+                        nameSpace);
                     wsmInstances.append(wsmInstance);
                 }
                 wsmValue.set(wsmInstances);
@@ -650,7 +763,7 @@ void CimToWsmResponseMapper::convertCimToWsmValue(
                 WsmEndpointReference epr;
                 CIMObjectPath objPath;
                 cimValue.get(objPath);
-                convertObjPathToEPR(objPath, epr, nameSpace);
+                convertObjPathToEPR(resourceUri, objPath, epr, nameSpace);
                 wsmValue.set(epr);
                 break;
             }
@@ -662,6 +775,7 @@ void CimToWsmResponseMapper::convertCimToWsmValue(
                 {
                     WsmInstance wsmInstance;
                     convertCimToWsmInstance(
+                        resourceUri,
                         CIMInstance(cimObject), wsmInstance, nameSpace);
                     wsmValue.set(wsmInstance);
                 }
@@ -681,7 +795,8 @@ void CimToWsmResponseMapper::convertCimToWsmValue(
                 WsmInstance wsmInstance;
                 CIMInstance cimInstance;
                 cimValue.get(cimInstance);
-                convertCimToWsmInstance(cimInstance, wsmInstance, nameSpace);
+                convertCimToWsmInstance(
+                    resourceUri, cimInstance, wsmInstance, nameSpace);
                 wsmValue.set(wsmInstance);
                 break;
             }
@@ -694,6 +809,7 @@ void CimToWsmResponseMapper::convertCimToWsmValue(
 }
 
 void CimToWsmResponseMapper::convertObjPathToEPR(
+    const String& resourceUri,
     const CIMObjectPath& objPath,
     WsmEndpointReference& epr,
     const String& nameSpace)
@@ -706,7 +822,7 @@ void CimToWsmResponseMapper::convertObjPathToEPR(
     else
         epr.address = WSM_ADDRESS_ANONYMOUS;
 
-    epr.resourceUri = String(WSM_RESOURCEURI_CIMSCHEMAV2) + "/" +
+    epr.resourceUri = WsmUtils::getRootResourceUri(resourceUri) + "/" +
         objPath.getClassName().getString();
 
     CIMNamespaceName cimNS = objPath.getNameSpace();
@@ -729,7 +845,7 @@ void CimToWsmResponseMapper::convertObjPathToEPR(
         {
             CIMObjectPath cimRef = binding.getValue();
             WsmEndpointReference wsmRef;
-            convertObjPathToEPR(cimRef, wsmRef, nameSpace);
+            convertObjPathToEPR(resourceUri, cimRef, wsmRef, nameSpace);
             WsmSelector selector(binding.getName().getString(), wsmRef);
             epr.selectorSet->selectors.append(selector);
         }
@@ -807,6 +923,11 @@ void CimToWsmResponseMapper::convertCimToWsmDatetime(
             }
             wsmDT.append(Char16('S'));
         }
+
+        // According to spec, at least one number must be present, so if
+        // we end up with "PT", then convert to "PT0S".
+        if (wsmDT == "PT")
+            wsmDT.append("0S");
     }
     else if ((cimStr[21] == '+' || cimStr[21] == '-') &&
              firstAsteriskPos == PEG_NOT_FOUND)
@@ -882,4 +1003,33 @@ void CimToWsmResponseMapper::convertCimToWsmDatetime(
         wsmDT = cimStr;
     }
 }
+
+void CimToWsmResponseMapper::convertCimToWsmParameters(
+    const String& resourceUri,
+    const String& nameSpace,
+    const Array<CIMParamValue>& parameters,
+    const CIMValue& returnValue,
+    WsmInstance& wsmInstance)
+{
+    // Convert output properties.
+
+    for (Uint32 i = 0, n = parameters.size(); i < n; i++)
+    {
+        const CIMParamValue& cpv = parameters[i];
+        const String& name = cpv.getParameterName();
+        const CIMValue& value = cpv.getValue();
+
+        WsmValue wvalue;
+        convertCimToWsmValue(resourceUri, value, wvalue, nameSpace);
+        wsmInstance.addProperty(WsmProperty(name, wvalue));
+    }
+
+    // Convert return value.
+    {
+        WsmValue wvalue;
+        convertCimToWsmValue(resourceUri, returnValue, wvalue, nameSpace);
+        wsmInstance.addProperty(WsmProperty("ReturnValue", wvalue));
+    }
+}
+
 PEGASUS_NAMESPACE_END
index 86f9b782636159ab1a4003c0dab4f10929871c46..04238528e8fa96fd50f14544c0ca33c9f71c09f7 100644 (file)
@@ -54,14 +54,26 @@ public:
     WsmFault mapCimExceptionToWsmFault(const CIMException& cimException);
 
     void convertCimToWsmInstance(
+        const String& resourceUri,
         const CIMConstInstance& cimInstance,
         WsmInstance& wsmInstance,
         const String& nameSpace);
+
+    void convertCimToWsmParameters(
+        const String& resourceUri,
+        const String& nameSpace,
+        const Array<CIMParamValue>& parameters,
+        const CIMValue& returnValue,
+        WsmInstance& instance);
+
     void convertCimToWsmValue(
+        const String& resourceUri,
         const CIMValue& cimValue,
         WsmValue& wsmValue,
         const String& nameSpace);
+
     void convertObjPathToEPR(
+        const String& resourceUri,
         const CIMObjectPath& objPath,
         WsmEndpointReference& epr,
         const String& nameSpace);
@@ -94,6 +106,10 @@ private:
         const WsmRequest* wsmRequest,
         const CIMResponseMessage* message);
 
+    WsInvokeResponse* _mapToWsInvokeResponse(
+        const WsInvokeRequest* wsmRequest,
+        const CIMInvokeMethodResponseMessage* response);
+
     ContentLanguageList _getContentLanguages(const OperationContext& context)
     {
         if (context.contains(ContentLanguageListContainer::NAME))
index 77bca7d8e040c38c39865e7aa1ef2ea7462a35ab..6cef7fd65681a2e20bc16423f13cf0bd8d2744c2 100644 (file)
@@ -41,6 +41,7 @@ LIBRARY = pegwsmserver
 
 LIBRARIES = \
     pegrepository \
+    pegwql \
     pegconfig \
     pegcommon
 
index 16e74b3c772475ff359d3c9a0b3570c1b5aa0b0d..ec17bd9de70ace1c04980fb021fdcedfaafa9b5a 100644 (file)
@@ -99,12 +99,29 @@ SoapResponse::SoapResponse(WsmResponse* response)
                 ((SoapFaultResponse*) response)->getFault());
             break;
 
+        case WS_INVOKE:
+        {
+            WsInvokeResponse* rsp = (WsInvokeResponse*)response;
+
+            // Get root of resource URI.
+            String root = WsmUtils::getRootResourceUri(rsp->resourceUri);
+
+            // Build the action.
+            action = root;
+            action.append('/');
+            action.append(rsp->className);
+            action.append('/');
+            action.append(rsp->methodName);
+            break;
+        }
+
         default:
             PEGASUS_ASSERT(0);
     }
 
     WsmWriter::appendHTTPResponseHeader(_httpHeader, action,
-       response->getHttpMethod(), response->getContentLanguages(),
+       response->getHttpMethod(), response->getOmitXMLProcessingInstruction(),
+       response->getContentLanguages(),
        response->getType() == WSM_FAULT || response->getType() == SOAP_FAULT,
        0);
 
index 634d1d038e4e7cfcc2b1ef4ca6df8af1cf36f90f..67ab13e61c5081c5544f117ce1c4448927e1e6c2 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <Pegasus/Common/Config.h>
 #include <Pegasus/Common/CIMName.h>
+#include <Pegasus/Common/PegasusVersion.h>
 
 //
 // Message Queue Names
 #define WSM_RESOURCEURI_ALLCLASSES \
     "http://schemas.dmtf.org/wbem/wscim/1/*"
 
+// WSM_RESOURCEURI_ALLCLASSES without the leading HOST URI prefix.
+#define WSM_RESOURCEURI_ALLCLASSES_SUFFIX \
+    "/wbem/wscim/1/*"
+
 #define WSM_RESOURCEURI_CIMSCHEMAV2 \
     "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2"
 
+// WSM_RESOURCEURI_CIMSCHEMAV2 without the host URI prefix.
+#define WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX \
+    "/wbem/wscim/1/cim-schema/2"
+
+// The WQL filter dialect URI.
+#define WSMAN_FILTER_DIALECT_WQL "http://schemas.dmtf.org/wbem/wsman/1/WQL"
+
+// WSMAN_FILTER_DIALECT_WQL without the host URI prefix.
+#define WSMAN_FILTER_DIALECT_WQL_SUFFIX "/wbem/wsman/1/WQL"
 
 //
 // Action URIs
 #define WSMAN_FAULTDETAIL_ENUMERATION_MODE_UNSUPPORTED \
     "http://schemas.dmtf.org/wbem/wsman/1/wsman/faultDetail/EnumerationMode"
 
+// The namespace to encode instance response data with.
+#define PEGASUS_INSTANCE_NS "p"
+
+// The namespace to encode invoke response data with.
+#define PEGASUS_INVOKE_NS "n1"
+
+// The current version URI for WS-Management.
+#define WSMAN_PROTOCOL_VERSION "http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd"
+
+// Vendor of this WS-Management implementation.
+#define WSMAN_PRODUCT_VENDOR "The Open Group (OpenPegasus)"
+
+// Version of this WS-Management implementation.
+
+#define WSMAN_PRODUCT_VERSION PEGASUS_PRODUCT_VERSION
+
 enum WsmbPolymorphismMode
 {
     WSMB_PM_UNKNOWN,
index 94fa0089f0205f3a1a2ad5e4e55ba6a1aa799e45..0d862f2996544908ee0daa7c4d1aefb041b72862 100644 (file)
 
 #include <Pegasus/Common/Config.h>
 #include <Pegasus/Common/MessageLoader.h>
+#include <Pegasus/Common/Buffer.h>
 #include <Pegasus/Common/StringConversion.h>
 #include <Pegasus/Common/XmlReader.h>
+#include <Pegasus/WQL/WQLSelectStatement.h>
+#include <Pegasus/WQL/WQLParser.h>
 #include <Pegasus/WsmServer/WsmConstants.h>
 #include <Pegasus/WsmServer/WsmFault.h>
 #include "WsmReader.h"
@@ -58,6 +61,11 @@ WsmReader::~WsmReader()
 {
 }
 
+void WsmReader::setHideEmptyTags(Boolean flag)
+{
+    _parser.setHideEmptyTags(flag);
+}
+
 //-----------------------------------------------------------------------------
 //
 // getXmlDeclaration()
@@ -186,6 +194,40 @@ void WsmReader::expectStartTag(
     }
 }
 
+int WsmReader::expectStartTag(
+    XmlEntry& entry,
+    const char* tagName)
+{
+    if (!_parser.next(entry) ||
+        entry.type != XmlEntry::START_TAG ||
+        strcmp(entry.localName, tagName) != 0)
+    {
+        const char* nsUri;
+        int nsType = entry.nsType;
+
+        // The nsType must have already been declared in the XML or it must be
+        // a supported namespace.
+        XmlNamespace* ns = _parser.getNamespace(nsType);
+        if (ns)
+        {
+            nsUri = ns->extendedName;
+        }
+        else
+        {
+            PEGASUS_ASSERT((nsType >= 0) && (nsType < WsmNamespaces::LAST));
+            nsUri = WsmNamespaces::supportedNamespaces[nsType].extendedName;
+        }
+
+        MessageLoaderParms mlParms(
+            "WsmServer.WsmReader.EXPECTED_OPEN",
+            "Expecting a start tag for \"$0\" element in namespace \"$1\".",
+            tagName, nsUri);
+        throw XmlValidationError(_parser.getLine(), mlParms);
+    }
+
+    return entry.nsType;
+}
+
 void WsmReader::expectStartOrEmptyTag(
     XmlEntry& entry,
     int nsType,
@@ -573,7 +615,10 @@ void WsmReader::decodeRequestSoapHeaders(
     XmlEntry entry;
     Boolean gotEntry;
 
+    // The wsidentify operation may send an empty header element.
+    _parser.setHideEmptyTags(true);
     expectStartTag(entry, WsmNamespaces::SOAP_ENVELOPE, "Header");
+    _parser.setHideEmptyTags(false);
 
     while ((gotEntry = _parser.next(entry)) &&
            ((entry.type == XmlEntry::START_TAG) ||
@@ -854,11 +899,12 @@ void WsmReader::getInstanceElement(WsmInstance& instance)
         // http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/<class name>
         if (ns)
         {
-            const char* pos = strrchr(ns->extendedName, '/');
-            if ((pos == ns->extendedName +
-                sizeof(WSM_RESOURCEURI_CIMSCHEMAV2) - 1) &&
-                (strncmp(ns->extendedName, WSM_RESOURCEURI_CIMSCHEMAV2,
-                    sizeof(WSM_RESOURCEURI_CIMSCHEMAV2) - 1) == 0) &&
+            const char* suffix = WsmUtils::skipHostUri(ns->extendedName);
+            const char* pos = strrchr(suffix, '/');
+            if ((pos == suffix +
+                sizeof(WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX) - 1) &&
+                (strncmp(suffix, WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX,
+                    sizeof(WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX) - 1) == 0) &&
                 (strcmp(pos + 1, classNameTag) == 0))
             {
                 // All properties must be qualified with the class namespace
@@ -1017,7 +1063,10 @@ void WsmReader::decodeEnumerateBody(
     WsmbPolymorphismMode& polymorphismMode,
     WsenEnumerationMode& enumerationMode,
     Boolean& optimized,
-    Uint32& maxElements)
+    Uint32& maxElements,
+    String& queryLanguage,
+    String& query,
+    SharedPtr<WQLSelectStatement>& selectStatement)
 {
     XmlEntry entry;
     expectStartOrEmptyTag(
@@ -1057,14 +1106,12 @@ void WsmReader::decodeEnumerateBody(
                 checkDuplicateHeader(entry.text, expiration.size());
                 expiration = getElementContent(entry);
             }
-            else if ((nsType == WsmNamespaces::WS_ENUMERATION) &&
+            else if ((nsType == WsmNamespaces::WS_MAN) &&
                 (strcmp(elementName, "Filter") == 0))
             {
-                throw WsmFault(
-                    WsmFault::wsen_FilteringNotSupported,
-                    MessageLoaderParms(
-                        "WsmServer.WsmReader.ENUMERATE_FILTERING_UNSUPPORTED",
-                        "Filtered enumerations are not supported."));
+                _parser.putBack(entry);
+                decodeFilter(queryLanguage, query, selectStatement);
+                needEndTag = false;
             }
             else if ((nsType == WsmNamespaces::WS_MAN) &&
                 (strcmp(elementName, "OptimizeEnumeration") == 0))
@@ -1300,4 +1347,112 @@ void WsmReader::decodeReleaseBody(Uint64& enumerationContext)
     expectEndTag(WsmNamespaces::WS_ENUMERATION, "Release");
 }
 
+void WsmReader::decodeInvokeInputBody(
+    const String& className,
+    const String& methodName,
+    WsmInstance& instance)
+{
+    XmlEntry entry;
+
+    //
+    // Parse the <s:Body> element. Here is an example:
+    //
+    //   <p:Foo_INPUT xmlns:p=
+    //     "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SomeClass">
+    //     <p:Arg1>
+    //       ...
+    //     </p:Arg1>
+    //     <p:Arg2>
+    //       ...
+    //     </p:Arg2>
+    //   </p:Foo_INPUT>
+    //
+
+    // Expect <METHODNAME_INPUT>
+    Buffer tagName;
+    tagName.append(methodName.getCString(), methodName.size());
+    tagName.append("_INPUT", 6);
+
+    _parser.setHideEmptyTags(true);
+    int nsType = expectStartTag(entry, tagName.getData());
+
+    // The following elements are input parameter.
+    String name;
+    WsmValue value;
+
+    while (getPropertyElement(nsType, name, value))
+    {
+        instance.addProperty(WsmProperty(name, value));
+    }
+
+    // Expect </METHODNAME_INPUT>
+    expectEndTag(nsType, tagName.getData());
+    _parser.setHideEmptyTags(false);
+}
+
+void WsmReader::decodeFilter(
+    String& queryLanguage,
+    String& query,
+    SharedPtr<WQLSelectStatement>& selectStatement)
+{
+    // Expect "Filter" element.
+    _parser.setHideEmptyTags(true);
+    XmlEntry entry;
+    expectStartTag(entry, WsmNamespaces::WS_MAN, "Filter");
+
+    // Check Filter.Dialect attribute.
+    {
+        const char* value;
+
+        if (!entry.getAttributeValue("Dialect", value))
+        {
+            MessageLoaderParms parms(
+                "WsmServer.WsmReader.MISSING_ATTRIBUTE",
+                "The attribute $0.$1 is missing.", "Filter", "Dialect");
+            throw XmlValidationError(_parser.getLine(), parms);
+        }
+
+        const char* suffix = WsmUtils::skipHostUri(value);
+
+        if (strcmp(suffix, WSMAN_FILTER_DIALECT_WQL_SUFFIX) != 0)
+        {
+            MessageLoaderParms parms(
+                "WsmServer.WsmReader.UNSUPPORTED_FILTER_DIALECT",
+                "Unsupported filter dialect: \"$0\".",
+                value);
+            throw WsmFault(
+                WsmFault::wsen_FilterDialectRequestedUnavailable, parms);
+        }
+
+        // We only support "WQL" so far.
+        queryLanguage = "WQL";
+    }
+
+    // Expect query expression (contains the query text).
+
+    expectContentOrCData(entry);
+    query = entry.text;
+
+    // Compile the query filter.
+
+    try
+    {
+        selectStatement.reset(new WQLSelectStatement);
+        WQLParser::parse(query, *selectStatement.get());
+    }
+    catch (ParseError& e)
+    {
+        MessageLoaderParms parms(
+            "WsmServer.WsmReader.INVALID_FILTER_QUERY_EXPRESSION",
+            "Invalid filter query expression: \"$0\".",
+            entry.text);
+        throw WsmFault(WsmFault::wsen_CannotProcessFilter, parms);
+    }
+
+    // Expect </Filter>
+
+    expectEndTag(WsmNamespaces::WS_MAN, "Filter");
+    _parser.setHideEmptyTags(false);
+}
+
 PEGASUS_NAMESPACE_END
index 3d7f564700bae418a70c35068a80ee4fbaac0db0..6491aaa8707b75f13f00888d35a4748351500510 100644 (file)
 #include <Pegasus/Common/Config.h>
 #include <Pegasus/Common/XmlParser.h>
 #include <Pegasus/Common/AcceptLanguageList.h>
+#include <Pegasus/Common/SharedPtr.h>
 #include <Pegasus/WsmServer/WsmInstance.h>
 #include <Pegasus/WsmServer/WsmSelectorSet.h>
 #include <Pegasus/WsmServer/WsmEndpointReference.h>
 #include <Pegasus/WsmServer/WsmUtils.h>
+#include <Pegasus/WQL/WQLParser.h>
 
 PEGASUS_NAMESPACE_BEGIN
 
@@ -49,6 +51,8 @@ public:
     WsmReader(char* text);
     ~WsmReader();
 
+    void setHideEmptyTags(Boolean flag);
+
     Boolean getXmlDeclaration(
         const char*& xmlVersion, const char*& xmlEncoding);
 
@@ -66,10 +70,17 @@ public:
         XmlEntry& entry,
         int nsType,
         const char* tagName);
+
+    // Expect a start tag with the given name and return the namespace id.
+    int expectStartTag(
+        XmlEntry& entry,
+        const char* tagName);
+
     void expectStartOrEmptyTag(
         XmlEntry& entry,
         int nsType,
         const char* tagName);
+
     void expectEndTag(
         int nsType,
         const char* tagName);
@@ -121,7 +132,10 @@ public:
         WsmbPolymorphismMode& polymorphismMode,
         WsenEnumerationMode& enumerationMode,
         Boolean& optimized,
-        Uint32& maxElements);
+        Uint32& maxElements,
+        String& queryLanguage,
+        String& query,
+        SharedPtr<WQLSelectStatement>& selectStatement);
 
     void decodePullBody(
         Uint64& enumerationContext,
@@ -131,6 +145,11 @@ public:
 
     void decodeReleaseBody(Uint64& enumerationContext);
 
+   void decodeInvokeInputBody(
+       const String& className,
+       const String& methodName,
+       WsmInstance& instance);
+
     void getInstanceElement(WsmInstance& instance);
     Boolean getPropertyElement(
         int nsType,
@@ -138,6 +157,11 @@ public:
         WsmValue& propValue);
     void getValueElement(WsmValue& value, int nsType, const char* propNameTag);
 
+    void decodeFilter(
+        String& queryLanguage,
+        String& query,
+        SharedPtr<WQLSelectStatement>& selectStatement);
+
 private:
 
     XmlParser _parser;
index 88ee57e29ed7f8e2f96e72e80032cd6df225215b..422780777df49bfbbf9586565edcbabc3445e387 100644 (file)
 #include <Pegasus/Common/ContentLanguageList.h>
 #include <Pegasus/Common/ArrayInternal.h>
 #include <Pegasus/Common/Message.h>
+#include <Pegasus/Common/SharedPtr.h>
 #include <Pegasus/WsmServer/WsmConstants.h>
 #include <Pegasus/WsmServer/WsmSelectorSet.h>
 #include <Pegasus/WsmServer/WsmInstance.h>
+#include <Pegasus/WQL/WQLParser.h>
 
 PEGASUS_NAMESPACE_BEGIN
 
@@ -58,7 +60,10 @@ enum WsmOperationType
 
     WS_ENUMERATION_ENUMERATE,
     WS_ENUMERATION_PULL,
-    WS_ENUMERATION_RELEASE
+    WS_ENUMERATION_RELEASE,
+
+    /* WS-Management invoke */
+    WS_INVOKE
     // etc.
 };
 
@@ -72,6 +77,7 @@ public:
         : messageId(messageId_),
           httpMethod(HTTP_METHOD__POST),
           httpCloseConnect(false),
+          omitXMLProcessingInstruction(false),
           queueId(0),
           requestEpr(false),
           maxEnvelopeSize(0),
@@ -96,6 +102,7 @@ public:
     AcceptLanguageList acceptLanguages;
     ContentLanguageList contentLanguages;
     Boolean httpCloseConnect;
+    Boolean omitXMLProcessingInstruction;
     Uint32 queueId;
     Boolean requestEpr;
     Uint32 maxEnvelopeSize;
@@ -183,7 +190,10 @@ public:
         Boolean optimized_,
         Uint32 maxElements_,
         WsenEnumerationMode enumerationMode_,
-        WsmbPolymorphismMode polymorphismMode_)
+        WsmbPolymorphismMode polymorphismMode_,
+        const String& queryLanguage_,
+        const String& query_,
+        SharedPtr<WQLSelectStatement> selectStatement_)
         : WsmRequest(WS_ENUMERATION_ENUMERATE, messageId),
           epr(epr_),
           expiration(expiration_),
@@ -191,7 +201,14 @@ public:
           optimized(optimized_),
           maxElements(maxElements_),
           enumerationMode(enumerationMode_),
-          polymorphismMode(polymorphismMode_)
+          polymorphismMode(polymorphismMode_),
+          queryLanguage(queryLanguage_),
+          query(query_),
+          selectStatement(selectStatement_)
+    {
+    }
+
+    ~WsenEnumerateRequest()
     {
     }
 
@@ -202,6 +219,9 @@ public:
     Uint32 maxElements;
     WsenEnumerationMode enumerationMode;
     WsmbPolymorphismMode polymorphismMode;
+    const String queryLanguage;
+    const String query;
+    SharedPtr<WQLSelectStatement> selectStatement;
 };
 
 class WsenPullRequest : public WsmRequest
@@ -252,6 +272,31 @@ public:
     Uint64 enumerationContext;
 };
 
+class WsInvokeRequest : public WsmRequest
+{
+public:
+
+    WsInvokeRequest(
+        const String& messageId,
+        const WsmEndpointReference& epr_,
+        const String& className_,
+        const String& methodName_,
+        const WsmInstance& instance_)
+        :
+        WsmRequest(WS_INVOKE, messageId),
+        epr(epr_),
+        className(className_),
+        methodName(methodName_),
+        instance(instance_)
+    {
+    }
+
+    WsmEndpointReference epr;
+    String className;
+    String methodName;
+    WsmInstance instance;
+};
+
 PEGASUS_NAMESPACE_END
 
 #endif /* Pegasus_WsmRequest_h */
index 84ab528d8cb2e814d74e03664b35ff86de2932c4..4ab7ea86abd95c919672c9f3657543b704baff0c 100644 (file)
@@ -37,6 +37,7 @@
 #include <Pegasus/Common/CommonUTF.h>
 #include <Pegasus/Common/MessageLoader.h>
 #include <Pegasus/Common/AutoPtr.h>
+#include <Pegasus/Common/SharedPtr.h>
 
 #include "WsmConstants.h"
 #include "WsmReader.h"
 
 PEGASUS_NAMESPACE_BEGIN
 
+static bool _parseInvokeAction(
+    const String& action,
+    String& className,
+    String& methodName)
+{
+    // Parse the action as though it is a method invocation. If so, set
+    // className and methodName and return true. Else return false. Invoke
+    // actions have the following form:
+    //
+    //     http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/<CLASS>/<METHOD>
+
+    // Expect "http://" prefix.
+
+    CString cstr = action.getCString();
+    const char* p = cstr;
+
+    if (strncmp(p, "http://", 7) != 0)
+        return false;
+
+    p += 7;
+
+    // Find slash that terminates the host name.
+
+    if (!(p = strchr(p, '/')))
+        return false;
+
+    p++;
+
+    // Expect "wbem/wscim/1/cim-schema/2/" sequence.
+
+    if (strncmp(p, "wbem/wscim/1/cim-schema/2/", 26) != 0)
+        return false;
+
+    p += 26;
+
+    // Get classname:
+
+    char* slash = strchr(const_cast<char*>(p), '/');
+
+    if (!slash)
+        return false;
+
+    *slash = '\0';
+    className = p;
+    *slash = '/';
+    p = slash + 1;
+
+    // Get methodname:
+
+    methodName = p;
+
+    // If we got this far, then action refers to a method.
+    return true;
+}
+
 WsmRequestDecoder::WsmRequestDecoder(WsmProcessor* wsmProcessor)
     : MessageQueue(PEGASUS_QUEUENAME_WSMREQDECODER),
       _wsmProcessor(wsmProcessor),
@@ -208,6 +264,33 @@ void WsmRequestDecoder::handleHTTPMessage(HTTPMessage* httpMessage)
     content = (char*) httpMessage->message.getData() +
         httpMessage->message.size() - contentLength;
 
+    // Lookup HTTP "User-Agent" header. For example:
+    //
+    //     User-Agent: Microsoft WinRM Client
+    //
+    // If it contains "WinRM", then omit the XML processing instruction from
+    // the response (first line of XML response). A typical XML processing
+    // instruction looks like this:
+    //
+    //     <?xml version="1.0" encoding="utf-8"?>
+    //
+    // The WinRM user agent should never receive this line.
+
+    Boolean omitXMLProcessingInstruction;
+    {
+        String value;
+
+        if (HTTPMessage::lookupHeader(headers, "User-Agent", value, true) &&
+            value.find("WinRM") != Uint32(-1))
+        {
+            omitXMLProcessingInstruction = true;
+        }
+        else
+        {
+            omitXMLProcessingInstruction = false;
+        }
+    }
+
     // Validate the "Content-Type" header:
     const char* contentType;
     Boolean contentTypeHeaderFound = HTTPMessage::lookupHeader(
@@ -233,6 +316,21 @@ void WsmRequestDecoder::handleHTTPMessage(HTTPMessage* httpMessage)
         return;
     }
 
+    if (String::equalNoCase(charset, "utf-16"))
+    {
+        // Reject utf-16 requests.
+        WsmFault fault(
+            WsmFault::wsman_EncodingLimit,
+            "UTF-16 is not supported; Please use UTF-8",
+            ContentLanguageList(),
+            WSMAN_FAULTDETAIL_CHARACTERSET);
+         _wsmProcessor->sendResponse(new WsmFaultResponse(
+             String::EMPTY, queueId, httpMethod, httpCloseConnect,
+                omitXMLProcessingInstruction, fault));
+         PEG_METHOD_EXIT();
+         return;
+    }
+
     if (!String::equalNoCase(charset, "utf-8"))
     {
         // DSP0226 R13.1-5:  A service shall emit Responses using the same
@@ -248,7 +346,8 @@ void WsmRequestDecoder::handleHTTPMessage(HTTPMessage* httpMessage)
             ContentLanguageList(),
             WSMAN_FAULTDETAIL_CHARACTERSET);
          _wsmProcessor->sendResponse(new WsmFaultResponse(
-             String::EMPTY, queueId, httpMethod, httpCloseConnect, fault));
+              String::EMPTY, queueId, httpMethod, httpCloseConnect,
+              omitXMLProcessingInstruction, fault));
          PEG_METHOD_EXIT();
          return;
     }
@@ -301,7 +400,8 @@ void WsmRequestDecoder::handleHTTPMessage(HTTPMessage* httpMessage)
         httpMessage->ipAddress,
         httpMessage->acceptLanguages,
         httpMessage->contentLanguages,
-        httpCloseConnect);
+        httpCloseConnect,
+        omitXMLProcessingInstruction);
 
     PEG_METHOD_EXIT();
 }
@@ -317,10 +417,12 @@ void WsmRequestDecoder::handleWsmMessage(
     const String& ipAddress,
     const AcceptLanguageList& httpAcceptLanguages,
     const ContentLanguageList& httpContentLanguages,
-    Boolean httpCloseConnect)
+    Boolean httpCloseConnect,
+    Boolean omitXMLProcessingInstruction)
 {
     PEG_METHOD_ENTER(TRC_WSMSERVER, "WsmRequestDecoder::handleWsmMessage()");
 
+
     // If CIMOM is shutting down, return "Service Unavailable" response
     if (_serverTerminating)
     {
@@ -397,6 +499,15 @@ void WsmRequestDecoder::handleWsmMessage(
                 e.getContentLanguages());
         }
 
+        // If no "Action" header was found, then this might still be a legal
+        // identify request.
+
+        if (wsaAction.size() == 0 && _isIdentifyRequest(wsmReader))
+        {
+            _sendIdentifyResponse(queueId);
+            return;
+        }
+
         // Set the Locale language into the thread for processing this request.
         Thread::setLanguages(wsmLocale);
 
@@ -468,6 +579,9 @@ void WsmRequestDecoder::handleWsmMessage(
         // Parse the SOAP Body while decoding each action
         //
 
+        String className;
+        String methodName;
+
         if (wsaAction == WSM_ACTION_GET)
         {
             request.reset(_decodeWSTransferGet(
@@ -519,6 +633,15 @@ void WsmRequestDecoder::handleWsmMessage(
                 wsaMessageId,
                 epr));
         }
+        else if (_parseInvokeAction(wsaAction, className, methodName))
+        {
+            request.reset(_decodeWSInvoke(
+                wsmReader,
+                wsaMessageId,
+                epr,
+                className,
+                methodName));
+        }
         else
         {
             throw WsmFault(
@@ -539,6 +662,7 @@ void WsmRequestDecoder::handleWsmMessage(
         request->acceptLanguages = wsmLocale;
         request->contentLanguages = httpContentLanguages;
         request->httpCloseConnect = httpCloseConnect;
+        request->omitXMLProcessingInstruction = omitXMLProcessingInstruction;
         request->queueId = queueId;
         request->requestEpr = wsmRequestEpr;
         request->maxEnvelopeSize = wsmMaxEnvelopeSize;
@@ -546,14 +670,16 @@ void WsmRequestDecoder::handleWsmMessage(
     catch (WsmFault& fault)
     {
         _wsmProcessor->sendResponse(new WsmFaultResponse(
-            wsaMessageId, queueId, httpMethod, httpCloseConnect, fault));
+            wsaMessageId, queueId, httpMethod, httpCloseConnect,
+            omitXMLProcessingInstruction, fault));
         PEG_METHOD_EXIT();
         return;
     }
     catch (SoapNotUnderstoodFault& fault)
     {
         _wsmProcessor->sendResponse(new SoapFaultResponse(
-            wsaMessageId, queueId, httpMethod, httpCloseConnect, fault));
+            wsaMessageId, queueId, httpMethod, httpCloseConnect,
+            omitXMLProcessingInstruction, fault));
         PEG_METHOD_EXIT();
         return;
     }
@@ -564,7 +690,8 @@ void WsmRequestDecoder::handleWsmMessage(
             e.getMessage(),
             e.getContentLanguages());
         _wsmProcessor->sendResponse(new WsmFaultResponse(
-            wsaMessageId, queueId, httpMethod, httpCloseConnect, fault));
+            wsaMessageId, queueId, httpMethod, httpCloseConnect,
+            omitXMLProcessingInstruction, fault));
         PEG_METHOD_EXIT();
         return;
     }
@@ -575,7 +702,8 @@ void WsmRequestDecoder::handleWsmMessage(
             e.getMessage(),
             e.getContentLanguages());
         _wsmProcessor->sendResponse(new WsmFaultResponse(
-            wsaMessageId, queueId, httpMethod, httpCloseConnect, fault));
+            wsaMessageId, queueId, httpMethod, httpCloseConnect,
+            omitXMLProcessingInstruction, fault));
         PEG_METHOD_EXIT();
         return;
     }
@@ -583,7 +711,8 @@ void WsmRequestDecoder::handleWsmMessage(
     {
         WsmFault fault(WsmFault::wsman_InternalError, e.what());
         _wsmProcessor->sendResponse(new WsmFaultResponse(
-            wsaMessageId, queueId, httpMethod, httpCloseConnect, fault));
+            wsaMessageId, queueId, httpMethod, httpCloseConnect,
+            omitXMLProcessingInstruction, fault));
         PEG_METHOD_EXIT();
         return;
     }
@@ -591,7 +720,8 @@ void WsmRequestDecoder::handleWsmMessage(
     {
         WsmFault fault(WsmFault::wsman_InternalError);
         _wsmProcessor->sendResponse(new WsmFaultResponse(
-            wsaMessageId, queueId, httpMethod, httpCloseConnect, fault));
+            wsaMessageId, queueId, httpMethod, httpCloseConnect,
+            omitXMLProcessingInstruction, fault));
         PEG_METHOD_EXIT();
         return;
     }
@@ -725,6 +855,9 @@ WsenEnumerateRequest* WsmRequestDecoder::_decodeWSEnumerationEnumerate(
     WsenEnumerationMode enumerationMode = WSEN_EM_UNKNOWN;
     Boolean optimized = false;
     Uint32 maxElements = 0;
+    String queryLanguage;
+    String query;
+    SharedPtr<WQLSelectStatement> selectStatement;
 
     XmlEntry entry;
     wsmReader.expectStartOrEmptyTag(
@@ -732,7 +865,8 @@ WsenEnumerateRequest* WsmRequestDecoder::_decodeWSEnumerationEnumerate(
     if (entry.type != XmlEntry::EMPTY_TAG)
     {
         wsmReader.decodeEnumerateBody(expiration, polymorphismMode,
-            enumerationMode, optimized, maxElements);
+            enumerationMode, optimized, maxElements, queryLanguage, query,
+            selectStatement);
         wsmReader.expectEndTag(WsmNamespaces::SOAP_ENVELOPE, "Body");
     }
 
@@ -752,7 +886,11 @@ WsenEnumerateRequest* WsmRequestDecoder::_decodeWSEnumerationEnumerate(
         // wsmb:PolymorphismModeNotSupported fault for requests using the
         // all classes ResourceURI if the PolymorphismMode is present and
         // does not equal IncludeSubClassProperties.
-        if (epr.resourceUri == WSM_RESOURCEURI_ALLCLASSES &&
+
+        CString tmp(epr.resourceUri.getCString());
+        const char* suffix = WsmUtils::skipHostUri(tmp);
+
+        if (strcmp(suffix, WSM_RESOURCEURI_ALLCLASSES_SUFFIX) == 0 &&
             polymorphismMode != WSMB_PM_INCLUDE_SUBCLASS_PROPERTIES)
         {
             throw WsmFault(
@@ -786,7 +924,10 @@ WsenEnumerateRequest* WsmRequestDecoder::_decodeWSEnumerationEnumerate(
         optimized,
         maxElements,
         enumerationMode,
-        polymorphismMode);
+        polymorphismMode,
+        queryLanguage,
+        query,
+        selectStatement);
 }
 
 WsenPullRequest* WsmRequestDecoder::_decodeWSEnumerationPull(
@@ -846,4 +987,110 @@ WsenReleaseRequest* WsmRequestDecoder::_decodeWSEnumerationRelease(
         enumerationContext);
 }
 
+WsmRequest* WsmRequestDecoder::_decodeWSInvoke(
+    WsmReader& wsmReader,
+    const String& messageId,
+    const WsmEndpointReference& epr,
+    const String& className,
+    const String& methodName)
+{
+    XmlEntry entry;
+
+    //
+    // Parse the <s:Body> element. Here is an example:
+    //
+    //   <s:Body>
+    //     <p:Foo_INPUT xmlns:p=
+    //       "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/SomeClass">
+    //       <p:Arg1>
+    //         1234
+    //       </p:Arg1>
+    //       <p:Arg2>
+    //         Hello!
+    //       </p:Arg2>
+    //     </p:Foo_INPUT>
+    //   </s:Body>
+    //
+
+    WsmInstance instance;
+    wsmReader.expectStartTag(entry, WsmNamespaces::SOAP_ENVELOPE, "Body");
+    wsmReader.decodeInvokeInputBody(className, methodName, instance);
+    wsmReader.expectEndTag(WsmNamespaces::SOAP_ENVELOPE, "Body");
+
+    return new WsInvokeRequest(messageId, epr, className, methodName, instance);
+}
+
+bool WsmRequestDecoder::_isIdentifyRequest(WsmReader& wsmReader)
+{
+    // Parse the <s:Body> element. Here is an example:
+    //
+    //   <s:Body>
+    //     <wsmid:Identify>
+    //   </s:Body>
+
+    XmlEntry entry;
+    wsmReader.setHideEmptyTags(true);
+    wsmReader.expectStartTag(entry, WsmNamespaces::SOAP_ENVELOPE, "Body");
+
+    try
+    {
+        // Expect an identify element. Ignore the namespace to be more
+        // tolerant.
+        int nsType = wsmReader.expectStartTag(entry, "Identify");
+        wsmReader.expectEndTag(nsType, "Identify");
+    }
+    catch (...)
+    {
+        wsmReader.setHideEmptyTags(false);
+        return false;
+    }
+
+    wsmReader.expectEndTag(WsmNamespaces::SOAP_ENVELOPE, "Body");
+    wsmReader.setHideEmptyTags(false);
+
+    return true;
+}
+
+void WsmRequestDecoder::_sendIdentifyResponse(Uint32 queueId)
+{
+    const char HTTP[] =
+        "HTTP/1.1 200 OK\r\n"
+        "Content-Type: application/soap+xml;charset=UTF-8\r\n"
+        "Content-Length: ";
+
+    const char XML[] =
+        "<s:Envelope xmlns:s=\""
+        "http://www.w3.org/2003/05/soap-envelope"
+        "\" xmlns:wsmid=\""
+        "http://schemas.dmtf.org/wbem/wsman/identify/1/wsmanidentity.xsd"
+        "\">"
+        "<s:Header>"
+        "</s:Header>"
+        "<s:Body>"
+        "<wsmid:IdentifyResponse>"
+        "<wsmid:ProtocolVersion>"
+        WSMAN_PROTOCOL_VERSION
+        "</wsmid:ProtocolVersion>"
+        "<wsmid:ProductVendor>"
+        WSMAN_PRODUCT_VENDOR
+        "</wsmid:ProductVendor>"
+        "<wsmid:ProductVersion>"
+        WSMAN_PRODUCT_VERSION
+        "</wsmid:ProductVersion>"
+        "</wsmid:IdentifyResponse>"
+        "</s:Body>"
+        "</s:Envelope>";
+
+    Buffer message;
+    message.append(HTTP, sizeof(HTTP) - 1);
+
+    char buf[32];
+    int n = sprintf(buf, "%d\r\n\r\n", int(sizeof(XML) - 1));
+    message.append(buf, n);
+
+    message.append(XML, sizeof(XML) - 1);
+
+    sendResponse(queueId, message, false);
+}
+
 PEGASUS_NAMESPACE_END
index c6ab110415f899deb97a167c286262e3f21e7d83..6dd1281c6af79944ffcffc323ce1731ab8c30fe3 100644 (file)
@@ -83,11 +83,19 @@ public:
         const String& ipAddress,
         const AcceptLanguageList& httpAcceptLanguages,
         const ContentLanguageList& httpContentLanguages,
-        Boolean httpCloseConnect);
+        Boolean httpCloseConnect,
+        Boolean omitXMLProcessingInstruction);
 
     // Sets the flag to indicate whether or not the CIMServer is shutting down.
     void setServerTerminating(Boolean flag) { _serverTerminating = flag; }
 
+    WsmRequest* _decodeWSInvoke(
+        WsmReader& wsmReader,
+        const String& messageId,
+        const WsmEndpointReference& epr,
+        const String& className,
+        const String& methodName);
+
 private:
 
     void _checkRequiredHeader(
@@ -133,6 +141,10 @@ private:
         const String& messageId,
         const WsmEndpointReference& epr);
 
+    bool _isIdentifyRequest(WsmReader& wsmReader);
+
+    void _sendIdentifyResponse(Uint32 queueId);
+
     // The queue to which to forward the decoded WsmRequests.
     WsmProcessor* _wsmProcessor;
 
index a42da567dbca3a907f2743b1508e05286c917c32..b1f5906e7024f18206f81886d0d53694b85ffb4b 100644 (file)
@@ -56,6 +56,7 @@ protected:
           _queueId(request->queueId),
           _httpMethod(request->httpMethod),
           _httpCloseConnect(request->httpCloseConnect),
+          _omitXMLProcessingInstruction(request->omitXMLProcessingInstruction),
           _maxEnvelopeSize(request->maxEnvelopeSize),
           _contentLanguages(contentLanguages)
     {
@@ -67,6 +68,7 @@ protected:
         Uint32 queueId,
         HttpMethod httpMethod,
         Boolean httpCloseConnect,
+        Boolean omitXMLProcessingInstruction,
         const ContentLanguageList& contentLanguages)
         : _type(type),
           _messageId(WsmUtils::getMessageId()),
@@ -74,6 +76,7 @@ protected:
           _queueId(queueId),
           _httpMethod(httpMethod),
           _httpCloseConnect(httpCloseConnect),
+          _omitXMLProcessingInstruction(omitXMLProcessingInstruction),
           _maxEnvelopeSize(0),
           _contentLanguages(contentLanguages)
     {
@@ -125,6 +128,11 @@ public:
         return _contentLanguages;
     }
 
+    Boolean getOmitXMLProcessingInstruction() const
+    {
+        return _omitXMLProcessingInstruction;
+    }
+
 private:
 
     WsmResponse(const WsmResponse&);
@@ -136,6 +144,7 @@ private:
     Uint32 _queueId;
     HttpMethod _httpMethod;
     Boolean _httpCloseConnect;
+    Boolean _omitXMLProcessingInstruction;
     Uint32 _maxEnvelopeSize;
     ContentLanguageList _contentLanguages;
 };
@@ -149,6 +158,7 @@ public:
         Uint32 queueId,
         HttpMethod httpMethod,
         Boolean httpCloseConnect,
+        Boolean omitXMLProcessingInstruction,
         const WsmFault& fault)
         : WsmResponse(
               WSM_FAULT,
@@ -156,6 +166,7 @@ public:
               queueId,
               httpMethod,
               httpCloseConnect,
+              omitXMLProcessingInstruction,
               fault.getReasonLanguage()),
           _fault(fault)
     {
@@ -195,6 +206,7 @@ public:
         Uint32 queueId,
         HttpMethod httpMethod,
         Boolean httpCloseConnect,
+        Boolean omitXMLProcessingInstruction,
         const SoapNotUnderstoodFault& fault)
         : WsmResponse(
               SOAP_FAULT,
@@ -202,6 +214,7 @@ public:
               queueId,
               httpMethod,
               httpCloseConnect,
+              omitXMLProcessingInstruction,
               fault.getMessageLanguage()),
           _fault(fault)
     {
@@ -233,7 +246,8 @@ public:
               WS_TRANSFER_GET,
               request,
               contentLanguages),
-          _instance(inst)
+          _instance(inst),
+          _resourceUri(request->epr.resourceUri)
     {
     }
 
@@ -246,9 +260,15 @@ public:
         return _instance;
     }
 
+    const String& getResourceUri() const
+    {
+        return _resourceUri;
+    }
+
 private:
 
     WsmInstance _instance;
+    String _resourceUri;
 };
 
 class WxfPutResponse : public WsmResponse
@@ -289,6 +309,7 @@ private:
     // EPR in the request.
     WsmEndpointReference _reference;
     Boolean _requestedEPR;
+    String _resourceUri;
 };
 
 class WxfCreateResponse : public WsmResponse
@@ -510,7 +531,8 @@ public:
               contentLanguages),
           _enumerationContext((Uint64) -1),
           _isComplete(false),
-          _enumerationData(data)
+          _enumerationData(data),
+          _resourceUri(request->epr.resourceUri)
     {
     }
     ~WsenPullResponse()
@@ -557,11 +579,17 @@ public:
         _enumerationContext = context;
     }
 
+    const String& getResourceUri() const
+    {
+        return _resourceUri;
+    }
+
 private:
 
     Uint64 _enumerationContext;
     Boolean _isComplete;
     WsenEnumerationData _enumerationData;
+    String _resourceUri;
 };
 
 class WsenEnumerateResponse : public WsmResponse
@@ -583,7 +611,8 @@ public:
           _requestItemCount(request->requestItemCount),
           _itemCount(itemCount),
           _enumerationData(inst, epr, request->polymorphismMode,
-              request->epr.resourceUri)
+              request->epr.resourceUri),
+          _resourceUri(request->epr.resourceUri)
     {
         PEGASUS_ASSERT(request->enumerationMode == WSEN_EM_OBJECT ||
             request->enumerationMode == WSEN_EM_OBJECT_AND_EPR);
@@ -602,7 +631,8 @@ public:
           _requestItemCount(request->requestItemCount),
           _itemCount(itemCount),
           _enumerationData(inst, request->polymorphismMode,
-              request->epr.resourceUri)
+              request->epr.resourceUri),
+          _resourceUri(request->epr.resourceUri)
     {
         PEGASUS_ASSERT(request->enumerationMode == WSEN_EM_OBJECT);
     }
@@ -619,7 +649,8 @@ public:
           _isComplete(false),
           _requestItemCount(request->requestItemCount),
           _itemCount(itemCount),
-          _enumerationData(epr)
+          _enumerationData(epr),
+          _resourceUri(request->epr.resourceUri)
     {
         PEGASUS_ASSERT(request->enumerationMode == WSEN_EM_EPR);
     }
@@ -636,7 +667,8 @@ public:
           _isComplete(false),
           _requestItemCount(request->requestItemCount),
           _itemCount(itemCount),
-          _enumerationData(data)
+          _enumerationData(data),
+          _resourceUri(request->epr.resourceUri)
     {
         PEGASUS_ASSERT(request->enumerationMode == data.enumerationMode);
     }
@@ -708,6 +740,11 @@ public:
         _enumerationContext = context;
     }
 
+    const String& getResourceUri() const
+    {
+        return _resourceUri;
+    }
+
 private:
 
     Uint64 _enumerationContext;
@@ -715,6 +752,7 @@ private:
     Boolean _requestItemCount;
     Uint32 _itemCount;
     WsenEnumerationData _enumerationData;
+    String _resourceUri;
 };
 
 class WsenReleaseResponse : public WsmResponse
@@ -736,6 +774,34 @@ public:
     }
 };
 
+class WsInvokeResponse : public WsmResponse
+{
+public:
+
+    WsInvokeResponse(
+        const String& nameSpace_,
+        const String& className_,
+        const String& methodName_,
+        const WsmInstance& instance_,
+        const WsInvokeRequest* request_,
+        const ContentLanguageList& contentLanguages_)
+        :
+        WsmResponse(WS_INVOKE, request_, contentLanguages_),
+        nameSpace(nameSpace_),
+        className(className_),
+        methodName(methodName_),
+        instance(instance_),
+        resourceUri(request_->epr.resourceUri)
+    {
+    }
+
+    String nameSpace;
+    String className;
+    String methodName;
+    WsmInstance instance;
+    String resourceUri;
+};
+
 PEGASUS_NAMESPACE_END
 
 #endif /* Pegasus_WsmResponse_h */
index 2342365e83e06894dea70ae99cd7d865d69c2667..9ca8ed4eeee9975a184aeff6e6212352eb008295 100644 (file)
@@ -127,6 +127,7 @@ void WsmResponseEncoder::_sendUnreportableSuccess(WsmResponse* response)
         response->getQueueId(),
         response->getHttpMethod(),
         response->getHttpCloseConnect(),
+        response->getOmitXMLProcessingInstruction(),
         fault);
 
     SoapResponse soapResponse(&faultResponse);
@@ -147,6 +148,7 @@ SoapResponse* WsmResponseEncoder::_buildEncodingLimitFault(
         response->getQueueId(),
         response->getHttpMethod(),
         response->getHttpCloseConnect(),
+        response->getOmitXMLProcessingInstruction(),
         fault);
 
     return new SoapResponse(&faultResponse);
@@ -194,6 +196,10 @@ void WsmResponseEncoder::enqueue(WsmResponse* response)
                 _encodeSoapFaultResponse((SoapFaultResponse*) response);
                 break;
 
+            case WS_INVOKE:
+                _encodeWsInvokeResponse((WsInvokeResponse*)response);
+                break;
+
             case WS_ENUMERATION_ENUMERATE:
             case WS_ENUMERATION_PULL:
                 // These cases are handled specially to allow for the message
@@ -213,7 +219,7 @@ void WsmResponseEncoder::enqueue(WsmResponse* response)
 
         Logger::put_l(
             Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE, parms);
-        
+
         MessageQueue* queue = MessageQueue::lookup(response->getQueueId());
         HTTPConnection* httpQueue = dynamic_cast<HTTPConnection*>(queue);
         PEGASUS_ASSERT(httpQueue);
@@ -229,7 +235,8 @@ void WsmResponseEncoder::_encodeWxfGetResponse(WxfGetResponse* response)
 {
     SoapResponse soapResponse(response);
     Buffer body;
-    WsmWriter::appendInstanceElement(body, response->getInstance());
+    WsmWriter::appendInstanceElement(body, response->getResourceUri(),
+        response->getInstance(), PEGASUS_INSTANCE_NS, false);
     if (soapResponse.appendBodyContent(body))
     {
         _sendResponse(&soapResponse);
@@ -335,7 +342,8 @@ SoapResponse* WsmResponseEncoder::encodeWsenEnumerateResponse(
             response->getEnumerationContext(),
             response->isComplete(),
             response->getEnumerationData(),
-            numDataItemsEncoded))
+            numDataItemsEncoded,
+            response->getResourceUri()))
     {
         soapResponse.reset(_buildEncodingLimitFault(response));
     }
@@ -357,7 +365,8 @@ SoapResponse* WsmResponseEncoder::encodeWsenPullResponse(
             response->getEnumerationContext(),
             response->isComplete(),
             response->getEnumerationData(),
-            numDataItemsEncoded))
+            numDataItemsEncoded,
+            response->getResourceUri()))
     {
         soapResponse.reset(_buildEncodingLimitFault(response));
     }
@@ -372,7 +381,8 @@ Boolean WsmResponseEncoder::_encodeEnumerationData(
     Uint64 contextId,
     Boolean isComplete,
     WsenEnumerationData& data,
-    Uint32& numDataItemsEncoded)
+    Uint32& numDataItemsEncoded,
+    const String& resourceUri)
 {
     Buffer bodyHeader, bodyTrailer;
 
@@ -444,7 +454,7 @@ Boolean WsmResponseEncoder::_encodeEnumerationData(
     }
 
     // Now add the list of items
-    Uint32 i;
+    Uint32 i = 0;
 
     if (data.enumerationMode == WSEN_EM_OBJECT)
     {
@@ -462,7 +472,9 @@ Boolean WsmResponseEncoder::_encodeEnumerationData(
                         data.classUri).getString());
             }
 
-            WsmWriter::appendInstanceElement(body, data.instances[i]);
+            WsmWriter::appendInstanceElement(body, resourceUri,
+                data.instances[i], PEGASUS_INSTANCE_NS, false);
+
             if (!soapResponse.appendBodyContent(body))
             {
                 break;
@@ -511,7 +523,8 @@ Boolean WsmResponseEncoder::_encodeEnumerationData(
                         data.classUri).getString());
             }
 
-            WsmWriter::appendInstanceElement(body, data.instances[i]);
+            WsmWriter::appendInstanceElement(body, resourceUri,
+                data.instances[i], PEGASUS_INSTANCE_NS, false);
 
             WsmWriter::appendStartTag(
                 body,
@@ -615,4 +628,29 @@ void WsmResponseEncoder::_encodeSoapFaultResponse(SoapFaultResponse* response)
     _sendResponse(&soapResponse);
 }
 
+void WsmResponseEncoder::_encodeWsInvokeResponse(
+    WsInvokeResponse* response)
+{
+    SoapResponse* soapResponse = new SoapResponse(response);
+
+    Buffer body;
+    WsmWriter::appendInvokeOutputElement(
+        body,
+        response->resourceUri,
+        response->className,
+        response->methodName,
+        response->instance,
+        PEGASUS_INVOKE_NS);
+
+    if (soapResponse->appendBodyContent(body))
+    {
+        _sendResponse(soapResponse);
+    }
+    else
+    {
+        delete soapResponse;
+        _sendUnreportableSuccess(response);
+    }
+}
+
 PEGASUS_NAMESPACE_END
index ebde2bf0d30ea6a822f1e46a3ea74b9561d7ba90..345772941592d3ba766a67c8a5190e3b0217e821 100644 (file)
@@ -77,6 +77,7 @@ private:
     void _encodeWsenReleaseResponse(WsenReleaseResponse* response);
     void _encodeWsmFaultResponse(WsmFaultResponse* response);
     void _encodeSoapFaultResponse(SoapFaultResponse* response);
+    void _encodeWsInvokeResponse(WsInvokeResponse* response);
 
     Boolean _encodeEnumerationData(
         SoapResponse& soapResponse,
@@ -85,7 +86,8 @@ private:
         Uint64 contextId,
         Boolean isComplete,
         WsenEnumerationData& data,
-        Uint32& numDataItemsEncoded);
+        Uint32& numDataItemsEncoded,
+        const String& resourceUri);
 };
 
 PEGASUS_NAMESPACE_END
index 49a13792adb7ab0a8eb45c231efba2248d8f700b..54d83ab4d592fc223d491f5dc16f8e8c4564039b 100644 (file)
 
 PEGASUS_NAMESPACE_BEGIN
 
+static bool _isInputParameter(const CIMParameter& cp)
+{
+    // Check to see if the given parameter is an input parameter (whether
+    // it bears a true "In" qualifier).
+
+    static const CIMName IN("In");
+    Uint32 pos = cp.findQualifier(IN);
+
+    if (pos != PEG_NOT_FOUND)
+    {
+        CIMConstQualifier cq = cp.getQualifier(pos);
+        const CIMValue& cv = cq.getValue();
+
+        if (cv.getType() == CIMTYPE_BOOLEAN)
+        {
+            Boolean in;
+            cv.get(in);
+            return in;
+        }
+    }
+
+    return false;
+}
+
 WsmToCimRequestMapper::WsmToCimRequestMapper(CIMRepository* repository)
     : _repository(repository)
 {
@@ -108,6 +132,13 @@ CIMOperationRequestMessage* WsmToCimRequestMapper::mapToCimRequest(
         case WS_ENUMERATION_RELEASE:
             break;
 
+        case WS_INVOKE:
+        {
+            cimRequest.reset(mapToCimInvokeMethodRequest(
+                (WsInvokeRequest*)request));
+            break;
+        }
+
         default:
             PEGASUS_ASSERT(0);
     }
@@ -131,7 +162,7 @@ CIMOperationRequestMessage* WsmToCimRequestMapper::mapToCimRequest(
 
 CIMGetInstanceRequestMessage*
     WsmToCimRequestMapper::mapToCimGetInstanceRequest(
-        WxfGetRequest* request)
+    WxfGetRequest* request)
 {
     CIMNamespaceName nameSpace;
     CIMObjectPath instanceName;
@@ -308,6 +339,48 @@ CIMEnumerateInstanceNamesRequestMessage*
     return cimRequest;
 }
 
+CIMInvokeMethodRequestMessage*
+WsmToCimRequestMapper::mapToCimInvokeMethodRequest(
+    WsInvokeRequest* request)
+{
+    // EPR to object path does a generic conversion, including conversion
+    // of EPR address to host and namespace selector to CIM namespace.
+    // For CreateInstance operation instance name should only contain a
+    // class name and key bindings.
+
+    CIMNamespaceName nameSpace;
+    CIMObjectPath instanceName;
+    convertEPRToObjectPath(request->epr, instanceName);
+    nameSpace = instanceName.getNameSpace();
+    instanceName.setNameSpace(CIMNamespaceName());
+    instanceName.setHost(String::EMPTY);
+
+    // Convert to array of CIMParamValue.
+
+    Array<CIMParamValue> parameters;
+
+    convertWsmToCimParameters(
+        nameSpace,
+        request->className,
+        request->methodName,
+        request->instance,
+        parameters);
+
+    CIMInvokeMethodRequestMessage* cimRequest =
+        new CIMInvokeMethodRequestMessage(
+            XmlWriter::getNextMessageId(),
+            nameSpace,
+            instanceName,
+            request->methodName,
+            parameters,
+            QueueIdStack(request->queueId),
+            request->authType,
+            request->userName);
+    cimRequest->ipAddress = request->ipAddress;
+
+    return cimRequest;
+}
+
 void WsmToCimRequestMapper::_disallowAllClassesResourceUri(
     const String& resourceUri)
 {
@@ -316,7 +389,10 @@ void WsmToCimRequestMapper::_disallowAllClassesResourceUri(
     // operations, even if this ResourceURI is supported for enumerations or
     // eventing.
 
-    if (resourceUri == WSM_RESOURCEURI_ALLCLASSES)
+    CString cstr(resourceUri.getCString());
+    const char* suffix = WsmUtils::skipHostUri(cstr);
+
+    if (strcmp(suffix, WSM_RESOURCEURI_ALLCLASSES_SUFFIX) == 0)
     {
         throw WsmFault(
             WsmFault::wsa_ActionNotSupported,
@@ -331,20 +407,17 @@ void WsmToCimRequestMapper::_disallowAllClassesResourceUri(
 CIMName WsmToCimRequestMapper::convertResourceUriToClassName(
     const String& resourceUri)
 {
-    static const String RESOURCEURI_PREFIX =
-        String(WSM_RESOURCEURI_CIMSCHEMAV2) + "/";
+    CString cstr(resourceUri.getCString());
+    const char* suffix = WsmUtils::skipHostUri(cstr);
+    size_t n = sizeof(WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX) - 1;
 
-    if (String::compare(
-            resourceUri,
-            RESOURCEURI_PREFIX,
-            RESOURCEURI_PREFIX.size()) == 0)
+    if (strncmp(suffix, WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX, n) == 0 &&
+        suffix[n] == '/')
     {
-        String className = resourceUri.subString(RESOURCEURI_PREFIX.size());
+        const char* className = &suffix[n + 1];
 
-        if (CIMName::legal(className))
-        {
-            return CIMNameCast(className);
-        }
+        if (CIMNameLegalASCII(className))
+            return CIMNameCast(String(className));
     }
 
     throw WsmFault(
@@ -1385,6 +1458,69 @@ void WsmToCimRequestMapper::convertWsmToCimDatetime(
     }
 }
 
+void WsmToCimRequestMapper::convertWsmToCimParameters(
+    const CIMNamespaceName& nameSpace,
+    const String& className,
+    const String& methodName,
+    WsmInstance& instance,
+    Array<CIMParamValue>& parameters)
+{
+    parameters.clear();
+
+    // Get class from repository.
+
+    CIMClass cc = _repository->getClass(nameSpace, CIMName(className), false);
+
+    // Look up the method.
+
+    Uint32 pos = cc.findMethod(methodName);
+
+    if (pos == PEG_NOT_FOUND)
+    {
+        MessageLoaderParms params(
+            "WsmServer.WsmToCimRequestMapper.NO_SUCH_METHOD",
+            "The $0 method does not exist.",
+            methodName);
+        throw WsmFault(WsmFault::wsman_SchemaValidationError, params);
+    }
+
+    CIMMethod cm = cc.getMethod(pos);
+
+    // Translate parameters:
+
+    for (Uint32 i = 0, n = instance.getPropertyCount(); i < n; i++)
+    {
+        WsmProperty& wp = instance.getProperty(i);
+        const String& wname = wp.getName();
+        WsmValue& wvalue= wp.getValue();
+
+        if (CIMName::legal(wname))
+        {
+            Uint32 pos = cm.findParameter(CIMName(wname));
+
+            if (pos != PEG_NOT_FOUND)
+            {
+                CIMParameter cp = cm.getParameter(pos);
+
+                // Reject if not an input parameter.
+                if (_isInputParameter(cp))
+                {
+                    const CIMName& cn = cp.getName();
+                    CIMValue cv(cp.getType(), cp.isArray());
+                    convertWsmToCimValue(wvalue, nameSpace, cv);
+                    parameters.append(CIMParamValue(cn.getString(), cv));
+                    continue;
+                }
+            }
+        }
+
+        MessageLoaderParms params(
+            "WsmServer.WsmToCimRequestMapper.NO_SUCH_PARAMETER",
+            "The $0 input parameter does not exist.", wname);
+        throw WsmFault(WsmFault::wsman_SchemaValidationError, params);
+    }
+}
+
 // Values have a lexical representation consisting of a mantissa followed,
 // optionally, by the character "E" or "e", followed by an exponent.
 // The exponent must be an integer. The mantissa must be a decimal number.
index d0d35d96dad9649b4e65d25b54a81871598d6d93..da91f753fff09d3978fa4adf401daf6492780d27 100644 (file)
@@ -63,6 +63,8 @@ public:
         WsenEnumerateRequest* request);
     CIMEnumerateInstanceNamesRequestMessage*
         mapToCimEnumerateInstanceNamesRequest(WsenEnumerateRequest* request);
+    CIMInvokeMethodRequestMessage* mapToCimInvokeMethodRequest(
+        WsInvokeRequest* request);
 
     static CIMName convertResourceUriToClassName(const String& resourceUri);
     String convertEPRAddressToHostname(const String& addr);
@@ -96,6 +98,13 @@ public:
     static void convertWsmToCimDatetime(
         const String& wsmDT, CIMDateTime& cimDT);
 
+    void convertWsmToCimParameters(
+        const CIMNamespaceName& nameSpace,
+        const String& className,
+        const String& methodName,
+        WsmInstance& instance,
+        Array<CIMParamValue>& parameters);
+
 private:
 
     CIMRepository* _repository;
index 208e6643a581281d4056a944286a68b50b84a1a4..484d472dc9a28b79644f38dd803d1bc0cddc7945 100644 (file)
@@ -32,6 +32,7 @@
 #include <Pegasus/Common/String.h>
 #include <Pegasus/Common/PegasusAssert.h>
 #include "WsmUtils.h"
+#include "WsmConstants.h"
 
 PEGASUS_NAMESPACE_BEGIN
 
@@ -170,4 +171,53 @@ String WsmUtils::getMessageId()
     return String(uuid, 41);
 }
 
+const char* WsmUtils::skipHostUri(const char* uri)
+{
+    const char* p = uri;
+
+    // Skip over "http://" part:
+
+    if (p[0] != 'h')
+        return &p[0];
+    if (p[1] != 't')
+        return &p[1];
+    if (p[2] != 't')
+        return &p[2];
+    if (p[3] != 'p')
+        return &p[3];
+    if (p[4] != ':')
+        return &p[4];
+    if (p[5] != '/')
+        return &p[5];
+    if (p[6] != '/')
+        return &p[6];
+
+    p += 7;
+
+    // Return the first character that is not a '/' (or return pointer to
+    // zero terminator).
+
+    while (*p && *p != '/')
+        p++;
+
+    return p;
+}
+
+String WsmUtils::getRootResourceUri(const String& resourceUri)
+{
+    CString cstr(resourceUri.getCString());
+    const char* start = cstr;
+    const char* end = skipHostUri(start);
+    const size_t n = sizeof(WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX) - 1;
+
+    if (strncmp(end, WSM_RESOURCEURI_CIMSCHEMAV2_SUFFIX, n) == 0)
+    {
+        end += n;
+        return String(start, end - start);
+    }
+
+    const int NS = WsmNamespaces::WS_CIM_SCHEMA;
+    return String(WsmNamespaces::supportedNamespaces[NS].extendedName);
+}
+
 PEGASUS_NAMESPACE_END
index a1ec5e95e1dbe6399386a9b12ca0a7a40ae8cb4c..27a2ac4d9b07c7e25575ffbda84ffb7bbe21d690 100644 (file)
@@ -80,6 +80,17 @@ public:
 
     static String getMessageId();
 
+    // Attempt to skip over the host URI of the form: http://host
+    // return a pointer to the character immdiately after the host URI
+    // (a slash or a zero terminator). Otherwise return a pointer to the
+    // first nonmatching character.
+    static const char* skipHostUri(const char* str);
+
+    // Return the leading part of resourceUri that matches the
+    // following expression (where <SERVER> is any server expression.
+    //     http://<SERVER>/wbem/wscim/1/cim-schema/2"
+    static String getRootResourceUri(const String& resourceUri);
+
 private:
 
     WsmUtils();
index 3b4444811cf4aab6d5a92bf1ace64d2ea91a4a9c..f0da2841066d956e9a01d49ce7c18a4fb5cffd55 100644 (file)
@@ -29,6 +29,7 @@
 //
 //%/////////////////////////////////////////////////////////////////////////////
 
+#include <new>
 #include <Pegasus/Common/Exception.h>
 #include <Pegasus/Common/PegasusAssert.h>
 
 
 PEGASUS_NAMESPACE_BEGIN
 
-WsmValue::WsmValue()
-    : _type(WSMTYPE_OTHER),
-      _isArray(false),
-      _isNull(true)
-{
-    _rep.str = 0;
-}
+//==============================================================================
+//
+// WsmValueRep
+//
+//==============================================================================
 
-WsmValue::WsmValue(const WsmValue& val)
-    : _type(WSMTYPE_OTHER),
-      _isArray(false),
-      _isNull(true)
+struct WsmValueRep
 {
-    *this = val;
-}
+    typedef WsmEndpointReference Ref;
+    typedef Array<WsmEndpointReference> RefA;
+    typedef WsmInstance Inst;
+    typedef Array<WsmInstance> InstA;
+    typedef String Str;
+    typedef Array<String> StrA;
+
+    AtomicInt refCount;
+    WsmType type;
+    Boolean isArray;
+    Boolean isNull;
+
+    // This union makes enough space for each of the given types in raw memory.
+    // WsmValue takes care or doing placement construction and destruction as
+    // needed.
+    union
+    {
+        // Be sure all types are aligned on 64-bit boundary.
+        Uint64 _alignment_;
+        char _ref_[sizeof(Ref)];
+        char _refa_[sizeof(RefA)];
+        char _inst_[sizeof(Inst)];
+        char _insta_[sizeof(InstA)];
+        char _stra_[sizeof(StrA)];
+        char _str_[sizeof(Str)];
+        char buf[1];
+    };
+
+    enum EmptyRepTag { EMPTY_REP_TAG };
+
+    WsmValueRep(EmptyRepTag) :
+        refCount(2), type(WSMTYPE_OTHER), isArray(false), isNull(true)
+    {
+        // This construction is for the empty representation. By maintaining
+        // a reference count of one, it will never fall to zero and never
+        // be deleted by _unref() below.
+    }
 
-WsmValue::WsmValue(const WsmEndpointReference& ref)
-    : _type(WSMTYPE_REFERENCE),
-      _isArray(false),
-      _isNull(false)
-{
-    _rep.ref = new WsmEndpointReference(ref);
-}
+    // Construct a null rep.
+    WsmValueRep() :
+        refCount(1), type(WSMTYPE_OTHER), isArray(false), isNull(true)
+    {
+    }
 
-WsmValue::WsmValue(const Array<WsmEndpointReference>& ref)
-    : _type(WSMTYPE_REFERENCE),
-      _isArray(true),
-      _isNull(false)
-{
-    _rep.refa = new Array<WsmEndpointReference>(ref);
-}
+    WsmValueRep(const Ref& x) :
+        refCount(1), type(WSMTYPE_REFERENCE), isArray(false), isNull(false)
+    {
+        new(buf) Ref(x);
+    }
 
-WsmValue::WsmValue(const WsmInstance& inst)
-    : _type(WSMTYPE_INSTANCE),
-      _isArray(false),
-      _isNull(false)
-{
-    _rep.inst = new WsmInstance(inst);
-}
+    WsmValueRep(const RefA& x) :
+        refCount(1), type(WSMTYPE_REFERENCE), isArray(true), isNull(false)
+    {
+        new(buf) RefA(x);
+    }
 
-WsmValue::WsmValue(const Array<WsmInstance>& inst)
-    : _type(WSMTYPE_INSTANCE),
-      _isArray(true),
-      _isNull(false)
-{
-    _rep.insta = new Array<WsmInstance>(inst);
-}
+    WsmValueRep(const Inst& x) :
+        refCount(1), type(WSMTYPE_INSTANCE), isArray(false), isNull(false)
+    {
+        new(buf) Inst(x);
+    }
 
-WsmValue::WsmValue(const String& str)
-    : _type(WSMTYPE_OTHER),
-      _isArray(false),
-      _isNull(false)
-{
-    _rep.str = new String(str);
-}
+    WsmValueRep(const InstA& x) :
+        refCount(1), type(WSMTYPE_INSTANCE), isArray(true), isNull(false)
+    {
+        new(buf) InstA(x);
+    }
 
-WsmValue::WsmValue(const Array<String>& str)
-    : _type(WSMTYPE_OTHER),
-      _isArray(true),
-      _isNull(false)
-{
-    _rep.stra = new Array<String>(str);
-}
+    WsmValueRep(const Str& x) :
+        refCount(1), type(WSMTYPE_OTHER), isArray(false), isNull(false)
+    {
+        new(buf) Str(x);
+    }
 
-WsmValue& WsmValue::operator=(const WsmValue& val)
-{
-    if (this == &val)
+    WsmValueRep(const StrA& x) :
+        refCount(1), type(WSMTYPE_OTHER), isArray(true), isNull(false)
     {
-        return *this;
+        new(buf) StrA(x);
     }
 
-    _release();
+    ~WsmValueRep()
+    {
+        clear();
+    }
 
-    if (!val._isNull)
+    void clear()
     {
-        if (val._isArray)
+        if (isNull)
+            return;
+
+        if (isArray)
         {
-            switch (val._type)
+            switch (type)
             {
                 case WSMTYPE_REFERENCE:
-                    _rep.refa = new Array<WsmEndpointReference>(*val._rep.refa);
+                    ((RefA*)buf)->~RefA();
                     break;
 
                 case WSMTYPE_INSTANCE:
-                    _rep.insta = new Array<WsmInstance>(*val._rep.insta);
+                    ((InstA*)buf)->~InstA();
                     break;
 
                 case WSMTYPE_OTHER:
-                    _rep.stra = new Array<String>(*val._rep.stra);
+                    ((StrA*)buf)->~StrA();
                     break;
 
                 default:
@@ -136,18 +160,18 @@ WsmValue& WsmValue::operator=(const WsmValue& val)
         }
         else
         {
-            switch (val._type)
+            switch (type)
             {
                 case WSMTYPE_REFERENCE:
-                    _rep.ref = new WsmEndpointReference(*val._rep.ref);
+                    ((Ref*)buf)->~Ref();
                     break;
 
                 case WSMTYPE_INSTANCE:
-                    _rep.inst = new WsmInstance(*val._rep.inst);
+                    ((Inst*)buf)->~Inst();
                     break;
 
                 case WSMTYPE_OTHER:
-                    _rep.str = new String(*val._rep.str);
+                    ((Str*)buf)->~Str();
                     break;
 
                 default:
@@ -155,227 +179,311 @@ WsmValue& WsmValue::operator=(const WsmValue& val)
                     break;
             }
         }
+
+        type = WSMTYPE_OTHER;
+        isNull = true;
+        isArray = false;
     }
 
-    _type = val._type;
-    _isArray = val._isArray;
-    _isNull = val._isNull;
+    WsmValueRep* clone() const
+    {
+        if (isNull)
+            return new WsmValueRep();
 
-    return *this;
+        if (isArray)
+        {
+            switch (type)
+            {
+                case WSMTYPE_REFERENCE:
+                    return new WsmValueRep(*((RefA*)buf));
+                case WSMTYPE_INSTANCE:
+                    return new WsmValueRep(*((InstA*)buf));
+                case WSMTYPE_OTHER:
+                    return new WsmValueRep(*((StrA*)buf));
+                default:
+                    PEGASUS_ASSERT(0);
+                    break;
+            }
+        }
+        else
+        {
+            switch (type)
+            {
+                case WSMTYPE_REFERENCE:
+                    return new WsmValueRep(*((Ref*)buf));
+                case WSMTYPE_INSTANCE:
+                    return new WsmValueRep(*((Inst*)buf));
+                case WSMTYPE_OTHER:
+                    return new WsmValueRep(*((Str*)buf));
+                default:
+                    PEGASUS_ASSERT(0);
+                    break;
+            }
+        }
+
+        // Unreachable!
+        return 0;
+    }
+
+    Ref& ref() { return *((Ref*)buf); }
+    const Ref& ref() const { return *((Ref*)buf); }
+
+    RefA& refa() { return *((RefA*)buf); }
+    const RefA& refa() const { return *((RefA*)buf); }
+
+    Inst& inst() { return *((Inst*)buf); }
+    const Inst& inst() const { return *((Inst*)buf); }
+
+    InstA& insta() { return *((InstA*)buf); }
+    const InstA& insta() const { return *((InstA*)buf); }
+
+    Str& str() { return *((Str*)buf); }
+    const Str& str() const { return *((Str*)buf); }
+
+    StrA& stra() { return *((StrA*)buf); }
+    const StrA& stra() const { return *((StrA*)buf); }
+};
+
+static WsmValueRep _emptyRep(WsmValueRep::EMPTY_REP_TAG);
+
+inline void _ref(const WsmValueRep* rep_)
+{
+    WsmValueRep* rep = (WsmValueRep*)rep_;
+
+    if (rep && rep != &_emptyRep)
+        rep->refCount.inc();
 }
 
-Uint32 WsmValue::getArraySize()
+inline void _unref(const WsmValueRep* rep_)
 {
-    if (_isArray)
-    {
-        switch (_type)
-        {
-            case WSMTYPE_REFERENCE:
-                return _rep.refa->size();
+    WsmValueRep* rep = (WsmValueRep*)rep_;
 
-            case WSMTYPE_INSTANCE:
-                return _rep.insta->size();
+    if (rep && rep != &_emptyRep && rep->refCount.decAndTestIfZero())
+        delete rep;
+}
 
-            case WSMTYPE_OTHER:
-                return _rep.stra->size();
+//==============================================================================
+//
+// WsmValue
+//
+//==============================================================================
 
-            default:
-                PEGASUS_ASSERT(0);
-        }
-    }
+WsmValue::WsmValue() : _rep(&_emptyRep)
+{
+}
 
-    return 0;
+WsmValue::WsmValue(const WsmValue& x)
+{
+    _ref(_rep = x._rep);
 }
 
-void WsmValue::_release()
+WsmValue::WsmValue(const WsmEndpointReference& x)
 {
-    if (_isNull)
-        return;
+    _rep = new WsmValueRep(x);
+}
 
-    if (_isArray)
-    {
-        switch (_type)
-        {
-            case WSMTYPE_REFERENCE:
-                delete _rep.refa;
-                break;
+WsmValue::WsmValue(const Array<WsmEndpointReference>& x)
+{
+    _rep = new WsmValueRep(x);
+}
 
-            case WSMTYPE_INSTANCE:
-                delete _rep.insta;
-                break;
+WsmValue::WsmValue(const WsmInstance& x)
+{
+    _rep = new WsmValueRep(x);
+}
 
-            case WSMTYPE_OTHER:
-                delete _rep.stra;
-                break;
+WsmValue::WsmValue(const Array<WsmInstance>& x)
+{
+    _rep = new WsmValueRep(x);
+}
 
-            default:
-                PEGASUS_ASSERT(0);
-                break;
-        }
+WsmValue::WsmValue(const String& x)
+{
+    _rep = new WsmValueRep(x);
+}
+
+WsmValue::WsmValue(const Array<String>& x)
+{
+    _rep = new WsmValueRep(x);
+}
+
+WsmValue::~WsmValue()
+{
+    _unref(_rep);
+}
+
+WsmValue& WsmValue::operator=(const WsmValue& x)
+{
+    if (this != &x)
+    {
+        _unref(_rep);
+        _ref(_rep = x._rep);
     }
-    else
+
+    return *this;
+}
+
+Uint32 WsmValue::getArraySize()
+{
+    if (_rep->isArray)
     {
-        switch (_type)
+        switch (_rep->type)
         {
             case WSMTYPE_REFERENCE:
-                delete _rep.ref;
-                break;
+                return _rep->refa().size();
 
             case WSMTYPE_INSTANCE:
-                delete _rep.inst;
-                break;
+                return _rep->insta().size();
 
             case WSMTYPE_OTHER:
-                delete _rep.str;
-                break;
+                return _rep->stra().size();
 
             default:
                 PEGASUS_ASSERT(0);
-                break;
         }
     }
+
+    return 0;
 }
 
 void WsmValue::get(WsmEndpointReference& ref) const
 {
-    if (_type != WSMTYPE_REFERENCE || _isArray)
+    if (_rep->type != WSMTYPE_REFERENCE || _rep->isArray)
         throw TypeMismatchException();
 
-    if (!_isNull)
-        ref = *_rep.ref;
+    if (!_rep->isNull)
+        ref = _rep->ref();
 }
 
 void WsmValue::get(Array<WsmEndpointReference>& ref) const
 {
-    if (_type != WSMTYPE_REFERENCE || !_isArray)
+    if (_rep->type != WSMTYPE_REFERENCE || !_rep->isArray)
         throw TypeMismatchException();
 
-    if (!_isNull)
-        ref = *_rep.refa;
+    if (!_rep->isNull)
+        ref = _rep->refa();
 }
 
 void WsmValue::get(WsmInstance& inst) const
 {
-    if (_type != WSMTYPE_INSTANCE || _isArray)
+    if (_rep->type != WSMTYPE_INSTANCE || _rep->isArray)
         throw TypeMismatchException();
 
-    if (!_isNull)
-        inst = *_rep.inst;
+    if (!_rep->isNull)
+        inst = _rep->inst();
 }
 
 void WsmValue::get(Array<WsmInstance>& inst) const
 {
-    if (_type != WSMTYPE_INSTANCE || !_isArray)
+    if (_rep->type != WSMTYPE_INSTANCE || !_rep->isArray)
         throw TypeMismatchException();
 
-    if (!_isNull)
-        inst = *_rep.insta;
+    if (!_rep->isNull)
+        inst = _rep->insta();
 }
 
 void WsmValue::get(String& str) const
 {
-    if (_type != WSMTYPE_OTHER || _isArray)
+    if (_rep->type != WSMTYPE_OTHER || _rep->isArray)
         throw TypeMismatchException();
 
-    if (!_isNull)
-        str = *_rep.str;
+    if (!_rep->isNull)
+        str = _rep->str();
 }
 
 void WsmValue::get(Array<String>& str) const
 {
-    if (_type != WSMTYPE_OTHER || !_isArray)
+    if (_rep->type != WSMTYPE_OTHER || !_rep->isArray)
         throw TypeMismatchException();
 
-    if (!_isNull)
-        str = *_rep.stra;
+    if (!_rep->isNull)
+        str = _rep->stra();
 }
 
-void WsmValue::set(const WsmEndpointReference& ref)
+void WsmValue::set(const WsmEndpointReference& x)
 {
-    _release();
-    _type = WSMTYPE_REFERENCE;
-    _isArray = false;
-    _isNull = false;
-    _rep.ref = new WsmEndpointReference(ref);
+    _unref(_rep);
+    _rep = new WsmValueRep(x);
 }
 
-void WsmValue::set(const Array<WsmEndpointReference>& ref)
+void WsmValue::set(const Array<WsmEndpointReference>& x)
 {
-    _release();
-    _type = WSMTYPE_REFERENCE;
-    _isArray = true;
-    _isNull = false;
-    _rep.refa = new Array<WsmEndpointReference>(ref);
+    _unref(_rep);
+    _rep = new WsmValueRep(x);
 }
 
-void WsmValue::set(const WsmInstance& inst)
+void WsmValue::set(const WsmInstance& x)
 {
-    _release();
-    _type = WSMTYPE_INSTANCE;
-    _isArray = false;
-    _isNull = false;
-    _rep.inst = new WsmInstance(inst);
+    _unref(_rep);
+    _rep = new WsmValueRep(x);
 }
 
-void WsmValue::set(const Array<WsmInstance>& inst)
+void WsmValue::set(const Array<WsmInstance>& x)
 {
-    _release();
-    _type = WSMTYPE_INSTANCE;
-    _isArray = true;
-    _isNull = false;
-    _rep.insta = new Array<WsmInstance>(inst);
+    _unref(_rep);
+    _rep = new WsmValueRep(x);
 }
 
-void WsmValue::set(const String& str)
+void WsmValue::set(const String& x)
 {
-    _release();
-    _type = WSMTYPE_OTHER;
-    _isArray = false;
-    _isNull = false;
-    _rep.str = new String(str);
+    _unref(_rep);
+    _rep = new WsmValueRep(x);
 }
 
-void WsmValue::set(const Array<String>& str)
+void WsmValue::set(const Array<String>& x)
 {
-    _release();
-    _type = WSMTYPE_OTHER;
-    _isArray = true;
-    _isNull = false;
-    _rep.stra = new Array<String>(str);
+    _unref(_rep);
+    _rep = new WsmValueRep(x);
 }
 
 void WsmValue::setNull()
 {
-    _release();
-    _type = WSMTYPE_OTHER;
-    _isArray = false;
-    _isNull = true;
+    if (_rep->refCount.get() == 1)
+    {
+        _rep->clear();
+    }
+    else
+    {
+        WsmValueRep* rep = new WsmValueRep();
+        _unref(_rep);
+        _rep = rep;
+    }
 }
 
-void WsmValue::add(const WsmValue& val)
+void WsmValue::add(const WsmValue& x)
 {
-    PEGASUS_ASSERT(!val._isArray);
+    PEGASUS_ASSERT(!x._rep->isArray);
+
+    if (x._rep->isArray)
+        return;
 
-    if (_type != val._type)
+    if (_rep->type != x._rep->type)
         throw TypeMismatchException();
 
-    if (_isArray)
+    if (_rep->isArray)
     {
-        switch (_type)
+        if (_rep->refCount.get() != 1)
+        {
+            WsmValueRep* rep = _rep->clone();
+            _unref(_rep);
+            _rep = rep;
+        }
+
+        switch (_rep->type)
         {
             case WSMTYPE_REFERENCE:
             {
-                _rep.refa->append(*val._rep.ref);
+                _rep->refa().append(x._rep->ref());
                 break;
             }
             case WSMTYPE_INSTANCE:
             {
-                _rep.insta->append(*val._rep.inst);
+                _rep->insta().append(x._rep->inst());
                 break;
             }
             case WSMTYPE_OTHER:
             {
-                _rep.stra->append(*val._rep.str);
+                _rep->stra().append(x._rep->str());
                 break;
             }
             default:
@@ -387,30 +495,30 @@ void WsmValue::add(const WsmValue& val)
     }
     else
     {
-        switch (_type)
+        switch (_rep->type)
         {
             case WSMTYPE_REFERENCE:
             {
-                Array<WsmEndpointReference> ref;
-                ref.append(*_rep.ref);
-                ref.append(*val._rep.ref);
-                set(ref);
+                Array<WsmEndpointReference> t;
+                t.append(_rep->ref());
+                t.append(x._rep->ref());
+                set(t);
                 break;
             }
             case WSMTYPE_INSTANCE:
             {
-                Array<WsmInstance> inst;
-                inst.append(*_rep.inst);
-                inst.append(*val._rep.inst);
-                set(inst);
+                Array<WsmInstance> t;
+                t.append(_rep->inst());
+                t.append(x._rep->inst());
+                set(t);
                 break;
             }
             case WSMTYPE_OTHER:
             {
-                Array<String> str;
-                str.append(*_rep.str);
-                str.append(*val._rep.str);
-                set(str);
+                Array<String> t;
+                t.append(_rep->str());
+                t.append(x._rep->str());
+                set(t);
                 break;
             }
             default:
@@ -422,33 +530,32 @@ void WsmValue::add(const WsmValue& val)
     }
 }
 
-
 void WsmValue::toArray()
 {
-    if (_isArray)
+    if (_rep->isArray)
         return;
 
-    switch (_type)
+    switch (_rep->type)
     {
         case WSMTYPE_REFERENCE:
         {
-            Array<WsmEndpointReference> ref;
-            ref.append(*_rep.ref);
-            set(ref);
+            Array<WsmEndpointReference> x;
+            x.append(_rep->ref());
+            set(x);
             break;
         }
         case WSMTYPE_INSTANCE:
         {
-            Array<WsmInstance> inst;
-            inst.append(*_rep.inst);
-            set(inst);
+            Array<WsmInstance> x;
+            x.append(_rep->inst());
+            set(x);
             break;
         }
         case WSMTYPE_OTHER:
         {
-            Array<String> str;
-            str.append(*_rep.str);
-            set(str);
+            Array<String> x;
+            x.append(_rep->str());
+            set(x);
             break;
         }
         default:
@@ -459,4 +566,19 @@ void WsmValue::toArray()
     }
 }
 
+Boolean WsmValue::isArray() const
+{
+    return _rep->isArray;
+}
+
+Boolean WsmValue::isNull() const
+{
+    return _rep->isNull;
+}
+
+WsmType WsmValue::getType() const
+{
+    return _rep->type;
+}
+
 PEGASUS_NAMESPACE_END
index d57e2e5f44c0a4a30e3bbab6022f9129d4b30144..1d9cf23af24495d494b37a8d76fc4775a1c111c5 100644 (file)
@@ -49,7 +49,6 @@ enum WsmType
     WSMTYPE_OTHER
 };
 
-
 class PEGASUS_WSMSERVER_LINKAGE WsmValue
 {
 public:
@@ -63,17 +62,14 @@ public:
     WsmValue(const Array<String>& str);
     WsmValue(const WsmValue& val);
 
-    ~WsmValue()
-    {
-        _release();
-    }
+    ~WsmValue();
 
     WsmValue& operator=(const WsmValue& val);
 
-    Boolean isArray() const { return _isArray; }
-    Boolean isNull() const { return _isNull; }
+    Boolean isArray() const;
+    Boolean isNull() const;
     void setNull();
-    WsmType getType() const { return _type; }
+    WsmType getType() const;
     Uint32 getArraySize();
 
     void toArray();
@@ -94,22 +90,7 @@ public:
     void set(const Array<String>& str);
 
 private:
-
-    void _release();
-
-    WsmType _type;
-    Boolean _isArray;
-    Boolean _isNull;
-
-    union WsmValueRep
-    {
-        WsmEndpointReference* ref;
-        Array<WsmEndpointReference>* refa;
-        WsmInstance* inst;
-        Array<WsmInstance>* insta;
-        Array<String>* stra;
-        String* str;
-    } _rep;
+    struct WsmValueRep* _rep;
 };
 
 PEGASUS_NAMESPACE_END
index 3887d5293f45a89c6dcb55ca4b021fb86f20521b..b8e6003a6964e9ceca2c9c90957857310bb100f9 100644 (file)
@@ -48,7 +48,24 @@ PEGASUS_NAMESPACE_BEGIN
 inline void _writeNewlineForReadability(Buffer& out)
 {
     // Uncomment this statement for XML response readability.
-    //out << '\n';
+    // 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(':');
 }
 
 //-----------------------------------------------------------------------------
@@ -172,14 +189,20 @@ void WsmWriter::appendWsmFaultBody(
 
 void WsmWriter::appendInstanceElement(
     Buffer& out,
+    const String& resourceUri,
     WsmInstance& instance,
+    const char* ns,
     Boolean isEmbedded)
 {
+    size_t nsLength = strlen(ns);
+
     // Class opening element:
-    out << STRLIT("<class:") << instance.getClassName();
-    out << STRLIT(" xmlns:class=\"");
-    out << WsmNamespaces::supportedNamespaces[WsmNamespaces::WS_CIM_SCHEMA].
-        extendedName;
+    _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("\"");
 
@@ -203,23 +226,36 @@ void WsmWriter::appendInstanceElement(
 
     // Properties:
     for (Uint32 i = 0, n = instance.getPropertyCount(); i < n; i++)
-        appendPropertyElement(out, instance.getProperty(i));
+        appendPropertyElement(out, resourceUri, instance.getProperty(i), ns);
 
     // Class closing element:
-    out << STRLIT("</class:") << instance.getClassName() << STRLIT(">");
+    _appendEndPrefix(out, ns);
+    out << instance.getClassName() << STRLIT(">");
     _writeNewlineForReadability(out);
 }
 
 void WsmWriter::appendPropertyElement(
     Buffer& out,
-    WsmProperty& property)
+    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 << STRLIT("<class:") << propName;
+        out << start << propName;
         out << " " << WsmNamespaces::supportedNamespaces[
             WsmNamespaces::XML_SCHEMA_INSTANCE].localName;
         out << STRLIT(":nil=\"true\"/>");
@@ -236,10 +272,10 @@ void WsmWriter::appendPropertyElement(
                 val.get(eprs);
                 for (Uint32 i = 0, n = eprs.size(); i < n; i++)
                 {
-                    out << STRLIT("<class:") << propName << STRLIT(">");
+                    out << start << propName << STRLIT(">");
                     _writeNewlineForReadability(out);
                     appendEPRElement(out, eprs[i]);
-                    out << STRLIT("</class:") << propName << STRLIT(">");
+                    out << end << propName << STRLIT(">");
                     _writeNewlineForReadability(out);
                 }
                 break;
@@ -250,10 +286,11 @@ void WsmWriter::appendPropertyElement(
                 val.get(instances);
                 for (Uint32 i = 0, n = instances.size(); i < n; i++)
                 {
-                    out << STRLIT("<class:") << propName << STRLIT(">");
+                    out << start << propName << STRLIT(">");
                     _writeNewlineForReadability(out);
-                    appendInstanceElement(out, instances[i], true);
-                    out << STRLIT("</class:") << propName << STRLIT(">");
+                    appendInstanceElement(out, resourceUri, instances[i],
+                        PEGASUS_INSTANCE_NS, true);
+                    out << end << propName << STRLIT(">");
                     _writeNewlineForReadability(out);
                 }
                 break;
@@ -264,10 +301,10 @@ void WsmWriter::appendPropertyElement(
                 val.get(strs);
                 for (Uint32 i = 0, n = strs.size(); i < n; i++)
                 {
-                    out << STRLIT("<class:") << propName << STRLIT(">");
+                    out << start << propName << STRLIT(">");
                     _writeNewlineForReadability(out);
                     appendStringElement(out, strs[i]);
-                    out << STRLIT("</class:") << propName << STRLIT(">");
+                    out << end << propName << STRLIT(">");
                     _writeNewlineForReadability(out);
                 }
                 break;
@@ -286,10 +323,10 @@ void WsmWriter::appendPropertyElement(
             {
                 WsmEndpointReference epr;
                 val.get(epr);
-                out << STRLIT("<class:") << propName << STRLIT(">");
+                out << start << propName << STRLIT(">");
                 _writeNewlineForReadability(out);
                 appendEPRElement(out, epr);
-                out << STRLIT("</class:") << propName << STRLIT(">");
+                out << end << propName << STRLIT(">");
                 _writeNewlineForReadability(out);
                 break;
             }
@@ -297,10 +334,11 @@ void WsmWriter::appendPropertyElement(
             {
                 WsmInstance instance;
                 val.get(instance);
-                out << STRLIT("<class:") << propName << STRLIT(">");
+                out << start << propName << STRLIT(">");
                 _writeNewlineForReadability(out);
-                appendInstanceElement(out, instance, true);
-                out << STRLIT("</class:") << propName << STRLIT(">");
+                appendInstanceElement(out, resourceUri, instance,
+                    PEGASUS_INSTANCE_NS, true);
+                out << end << propName << STRLIT(">");
                 _writeNewlineForReadability(out);
                 break;
             }
@@ -308,10 +346,10 @@ void WsmWriter::appendPropertyElement(
             {
                 String str;
                 val.get(str);
-                out << STRLIT("<class:") << propName << STRLIT(">");
+                out << start << propName << STRLIT(">");
                 _writeNewlineForReadability(out);
                 appendStringElement(out, str);
-                out << STRLIT("</class:") << propName << STRLIT(">");
+                out << end << propName << STRLIT(">");
                 _writeNewlineForReadability(out);
                 break;
             }
@@ -432,6 +470,7 @@ void WsmWriter::appendHTTPResponseHeader(
     Buffer& out,
     const String& action,
     HttpMethod httpMethod,
+    Boolean omitXMLProcessingInstruction,
     const ContentLanguageList& contentLanguages,
     Boolean isFault,
     Uint32 contentLength)
@@ -470,7 +509,11 @@ void WsmWriter::appendHTTPResponseHeader(
     }
     out << STRLIT("\r\n");
 
-    out << STRLIT("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
+    if (!omitXMLProcessingInstruction)
+    {
+        out << STRLIT("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
+    }
+
     _writeNewlineForReadability(out);
 }
 
@@ -556,9 +599,57 @@ void WsmWriter::appendSoapHeader(
     appendTagValue(
         out, WsmNamespaces::WS_ADDRESSING, STRLIT("MessageID"), messageId);
 
-    // Add <wsa:RelatesTo> entry
-    appendTagValue(
-        out, WsmNamespaces::WS_ADDRESSING, STRLIT("RelatesTo"), relatesTo);
+    // 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
index afca6022f80afe14653e480d29a735acf79d501c..49a9919801f0bc202117db0727dd7fefabfd8d7f 100644 (file)
@@ -75,9 +75,18 @@ public:
         const String& errorDetail = String::EMPTY);
 
     static void appendInstanceElement(
-        Buffer& out, WsmInstance& instance, Boolean isEmbedded = false);
-    static void appendPropertyElement(
-        Buffer& out, WsmProperty& property);
+        Buffer& out,
+        const String& resourceUri,
+        WsmInstance& instance,
+        const char* ns,
+        Boolean isEmbedded);
+
+     static void appendPropertyElement(
+        Buffer& out,
+        const String& resourceUri,
+        WsmProperty& property,
+        const char* ns);
+
     static void appendEPRElement(
         Buffer& out, const WsmEndpointReference& epr);
     static void appendStringElement(
@@ -109,6 +118,7 @@ public:
         Buffer& out,
         const String& action,
         HttpMethod httpMethod,
+        Boolean omitXMLProcessingInstruction,
         const ContentLanguageList& contentLanguages,
         Boolean isFault,
         Uint32 contentLength = 0);
@@ -128,6 +138,14 @@ public:
         const String& messageId,
         const String& relatesTo);
 
+    static void appendInvokeOutputElement(
+        Buffer& out,
+        const String& resourceUri,
+        const String& className,
+        const String& methodName,
+        WsmInstance& instance,
+        const char* ns);
+
 private:
 
     WsmWriter();
index d1e4cc1c63e98d5702ee52b649a51dd48ab827ec..7cee1815332c6cca2a5b816fb8312a0845b974a4 100644 (file)
@@ -43,6 +43,8 @@ PEGASUS_USING_STD;
 
 static Boolean verbose;
 
+static const String& ruri = WSM_RESOURCEURI_CIMSCHEMAV2;
+
 /* This template provides a set of tests of simple CIMValues (excluding
    reference and embedded instance types). */
 template<class T>
@@ -58,7 +60,7 @@ void testSimpleType(const T& x)
     {
         cimStr.toLower();
     }
-    mapper.convertCimToWsmValue(cimValue, wsmValue, String::EMPTY);
+    mapper.convertCimToWsmValue(ruri, cimValue, wsmValue, String::EMPTY);
     wsmValue.get(wsmStr);
     if (wsmValue.getType() != WSMTYPE_OTHER || wsmValue.isArray() ||
         wsmValue.isNull() || wsmStr != cimStr)
@@ -96,42 +98,42 @@ static void _testValues(void)
     Real32 f1 = strtod("nan", 0);
     CIMValue cimf1(f1);
     WsmValue wsmf1;
-    mapper.convertCimToWsmValue(cimf1, wsmf1, String::EMPTY);
+    mapper.convertCimToWsmValue(ruri, cimf1, wsmf1, String::EMPTY);
     wsmf1.get(str);
     PEGASUS_TEST_ASSERT(str == "NaN");
 
     Real32 f2 = strtod("inf", 0);
     CIMValue cimf2(f2);
     WsmValue wsmf2;
-    mapper.convertCimToWsmValue(cimf2, wsmf2, String::EMPTY);
+    mapper.convertCimToWsmValue(ruri, cimf2, wsmf2, String::EMPTY);
     wsmf2.get(str);
     PEGASUS_TEST_ASSERT(str == "INF");
 
     Real32 f3 = strtod("-inf", 0);
     CIMValue cimf3(f3);
     WsmValue wsmf3;
-    mapper.convertCimToWsmValue(cimf3, wsmf3, String::EMPTY);
+    mapper.convertCimToWsmValue(ruri, cimf3, wsmf3, String::EMPTY);
     wsmf3.get(str);
     PEGASUS_TEST_ASSERT(str == "-INF");
 
     Real64 d1 = strtod("nan", 0);
     CIMValue cimd1(d1);
     WsmValue wsmd1;
-    mapper.convertCimToWsmValue(cimd1, wsmd1, String::EMPTY);
+    mapper.convertCimToWsmValue(ruri, cimd1, wsmd1, String::EMPTY);
     wsmd1.get(str);
     PEGASUS_TEST_ASSERT(str == "NaN");
 
     Real64 d2 = strtod("inf", 0);
     CIMValue cimd2(d2);
     WsmValue wsmd2;
-    mapper.convertCimToWsmValue(cimd2, wsmd2, String::EMPTY);
+    mapper.convertCimToWsmValue(ruri, cimd2, wsmd2, String::EMPTY);
     wsmd2.get(str);
     PEGASUS_TEST_ASSERT(str == "INF");
 
     Real64 d3 = strtod("-inf", 0);
     CIMValue cimd3(d3);
     WsmValue wsmd3;
-    mapper.convertCimToWsmValue(cimd3, wsmd3, String::EMPTY);
+    mapper.convertCimToWsmValue(ruri, cimd3, wsmd3, String::EMPTY);
     wsmd3.get(str);
     PEGASUS_TEST_ASSERT(str == "-INF");
 
@@ -190,7 +192,7 @@ static void _testValues(void)
         cimInst.addProperty(CIMProperty(CIMName("count"), Uint32(55)));
         cimInst.addProperty(CIMProperty(CIMName("flag"), Boolean(true)));
         CIMValue cimValue(cimInst);
-        mapper.convertCimToWsmValue(cimValue, wsmValue, String::EMPTY);
+        mapper.convertCimToWsmValue(ruri, cimValue, wsmValue, String::EMPTY);
         wsmValue.get(wsmInst);
         if (wsmInst.getClassName() != "MyClass" ||
             wsmInst.getPropertyCount() != 3)
@@ -218,7 +220,7 @@ static void _testValues(void)
         cimInst.addProperty(CIMProperty(CIMName("flag"), Boolean(true)));
         CIMObject cimObj(cimInst);
         CIMValue cimValue(cimObj);
-        mapper.convertCimToWsmValue(cimValue, wsmValue, String::EMPTY);
+        mapper.convertCimToWsmValue(ruri, cimValue, wsmValue, String::EMPTY);
         wsmValue.get(wsmInst);
         if (wsmInst.getClassName() != "MyClass" ||
             wsmInst.getPropertyCount() != 3)
@@ -241,7 +243,7 @@ static void _testValues(void)
         WsmValue wsmValue;
         CIMObjectPath op("//atp:77/root/cimv25:TennisPlayer.last=\"Rafter\"");
         CIMValue cimValue(op);
-        mapper.convertCimToWsmValue(cimValue, wsmValue, String::EMPTY);
+        mapper.convertCimToWsmValue(ruri, cimValue, wsmValue, String::EMPTY);
         wsmValue.get(epr);
         if (epr.address != "http://atp:77/wsman" ||
             epr.resourceUri !=
@@ -265,7 +267,7 @@ void testArrayType(const Array<T>& x)
     WsmValue wsmValue;
     Array<String> arr;
     CIMValue cimValue(x);
-    mapper.convertCimToWsmValue(cimValue, wsmValue, String::EMPTY);
+    mapper.convertCimToWsmValue(ruri, cimValue, wsmValue, String::EMPTY);
     wsmValue.get(arr);
 
     if (wsmValue.getType() != WSMTYPE_OTHER || !wsmValue.isArray() ||
@@ -368,7 +370,7 @@ static void _testArrayValues(void)
         cimDTs.append(CIMDateTime("20001224120000.000000+360"));
         CIMValue cimValue(cimDTs);
         WsmValue wsmValue;
-        mapper.convertCimToWsmValue(cimValue, wsmValue, String::EMPTY);
+        mapper.convertCimToWsmValue(ruri, cimValue, wsmValue, String::EMPTY);
         wsmValue.get(wsmDTs);
         PEGASUS_TEST_ASSERT(wsmDTs.size() == 2 &&
             wsmDTs[0] == "1999-12-24T12:00:00+06:00" &&
@@ -390,7 +392,7 @@ static void _testArrayValues(void)
         cimInst2.addProperty(CIMProperty(CIMName("prop4"), String("value4")));
         cimInstArray.append(cimInst2);
         CIMValue cimValue(cimInstArray);
-        mapper.convertCimToWsmValue(cimValue, wsmValue, String::EMPTY);
+        mapper.convertCimToWsmValue(ruri, cimValue, wsmValue, String::EMPTY);
         wsmValue.get(wsmInstArray);
 
         if (wsmInstArray.size() != 2 ||
@@ -430,7 +432,7 @@ static void _testArrayValues(void)
         cimInst2.addProperty(CIMProperty(CIMName("prop4"), String("value4")));
         cimObjArray.append(CIMObject(cimInst2));
         CIMValue cimValue(cimObjArray);
-        mapper.convertCimToWsmValue(cimValue, wsmValue, String::EMPTY);
+        mapper.convertCimToWsmValue(ruri, cimValue, wsmValue, String::EMPTY);
         wsmValue.get(wsmInstArray);
 
         if (wsmInstArray.size() != 2 ||
@@ -466,7 +468,7 @@ static void _testArrayValues(void)
         opArray.append(op1);
         opArray.append(op2);
         CIMValue cimValue(opArray);
-        mapper.convertCimToWsmValue(cimValue, wsmValue, String::EMPTY);
+        mapper.convertCimToWsmValue(ruri, cimValue, wsmValue, String::EMPTY);
         wsmValue.get(eprArray);
 
         if (eprArray[0].address != "http://atp:11/wsman" ||
index 5c7b95b7aa3579ce1a8eaafcd877c3f48a5415c6..eab2001615937c356210e8ac7fc22c70429a6c02 100644 (file)
@@ -895,9 +895,12 @@ static void _testEnumerateBody(WsmReader& reader)
     WsenEnumerationMode enumerationMode = WSEN_EM_UNKNOWN;
     Boolean optimized = false;
     Uint32 maxElements = 0;
+    String lang;
+    String query;
+    SharedPtr<WQLSelectStatement> selectStatement;
 
     reader.decodeEnumerateBody(expiration, polymorphismMode, enumerationMode,
-        optimized, maxElements);
+        optimized, maxElements, lang, query, selectStatement);
     if (expiration != "PT123S" ||
         polymorphismMode != WSMB_PM_EXCLUDE_SUBCLASS_PROPERTIES ||
         enumerationMode != WSEN_EM_EPR ||
@@ -916,9 +919,13 @@ static void _testEnumerateBodyErrors(WsmReader& reader)
         WsenEnumerationMode enumerationMode = WSEN_EM_UNKNOWN;
         Boolean optimized = false;
         Uint32 maxElements = 0;
+        String lang;
+        String query;
+        SharedPtr<WQLSelectStatement> selectStatement;
 
         reader.decodeEnumerateBody(expiration, polymorphismMode,
-            enumerationMode, optimized, maxElements);
+            enumerationMode, optimized, maxElements, lang, query,
+            selectStatement);
 
         throw Exception("Expected duplicate headers fault");
     }
@@ -938,9 +945,13 @@ static void _testEnumerateBodyErrors(WsmReader& reader)
         WsenEnumerationMode enumerationMode = WSEN_EM_UNKNOWN;
         Boolean optimized = false;
         Uint32 maxElements = 0;
+        String lang;
+        String query;
+        SharedPtr<WQLSelectStatement> selectStatement;
 
         reader.decodeEnumerateBody(expiration, polymorphismMode,
-            enumerationMode, optimized, maxElements);
+            enumerationMode, optimized, maxElements, lang, query,
+            selectStatement);
 
         throw Exception("Expected unsupported feature fault");
     }
@@ -960,11 +971,13 @@ static void _testEnumerateBodyErrors(WsmReader& reader)
         WsenEnumerationMode enumerationMode = WSEN_EM_UNKNOWN;
         Boolean optimized = false;
         Uint32 maxElements = 0;
+        String lang;
+        String query;
+        SharedPtr<WQLSelectStatement> selectStatement;
 
         reader.decodeEnumerateBody(expiration, polymorphismMode,
-            enumerationMode, optimized, maxElements);
-
-        throw Exception("Expected filtering not supported fault");
+            enumerationMode, optimized, maxElements, lang, query,
+            selectStatement);
     }
     catch (WsmFault& fault)
     {
@@ -982,9 +995,13 @@ static void _testEnumerateBodyErrors(WsmReader& reader)
         WsenEnumerationMode enumerationMode = WSEN_EM_UNKNOWN;
         Boolean optimized = false;
         Uint32 maxElements = 0;
+        String lang;
+        String query;
+        SharedPtr<WQLSelectStatement> selectStatement;
 
         reader.decodeEnumerateBody(expiration, polymorphismMode,
-            enumerationMode, optimized, maxElements);
+            enumerationMode, optimized, maxElements, lang, query,
+            selectStatement);
 
         throw Exception("Expected unsupported feature fault");
     }
@@ -1004,9 +1021,13 @@ static void _testEnumerateBodyErrors(WsmReader& reader)
         WsenEnumerationMode enumerationMode = WSEN_EM_UNKNOWN;
         Boolean optimized = false;
         Uint32 maxElements = 0;
+        String lang;
+        String query;
+        SharedPtr<WQLSelectStatement> selectStatement;
 
         reader.decodeEnumerateBody(expiration, polymorphismMode,
-            enumerationMode, optimized, maxElements);
+            enumerationMode, optimized, maxElements, lang, query,
+            selectStatement);
 
         throw Exception("Expected unsupported polymorphism mode fault");
     }
@@ -1106,6 +1127,114 @@ static void _testPullBodyErrors(WsmReader& reader)
     }
 }
 
+static void _testEnumerateWithFilterBody(WsmReader& reader)
+{
+    XmlEntry entry;
+    reader.expectStartTag(entry, WsmNamespaces::SOAP_ENVELOPE, "Envelope");
+
+    String expiration;
+    WsmbPolymorphismMode polymorphismMode = WSMB_PM_UNKNOWN;
+    WsenEnumerationMode enumerationMode = WSEN_EM_UNKNOWN;
+    Boolean optimized = false;
+    Uint32 maxElements = 0;
+    String lang;
+    String query;
+    SharedPtr<WQLSelectStatement> selectStatement;
+
+    reader.decodeEnumerateBody(expiration, polymorphismMode, enumerationMode,
+        optimized, maxElements, lang, query, selectStatement);
+
+    if (lang != "WQL")
+    {
+        throw Exception("expected WQL dialect");
+    }
+
+    if (query != "select Status from CIM_ComputerSystem")
+    {
+        throw Exception("failed to get query from Filter");
+    }
+}
+
+static void _testInvokeBody(WsmReader& reader)
+{
+    WsmInstance inst;
+    reader.decodeInvokeInputBody("MyClass", "MyMethod", inst);
+
+    for (Uint32 i = 0; i < inst.getPropertyCount(); i++)
+    {
+        WsmProperty prop = inst.getProperty(i);
+        const String& name = prop.getName();
+        WsmValue& value = prop.getValue();
+        String str;
+        value.get(str);
+
+        if (name == "BooleanScalar")
+        {
+            if (str != "true")
+                throw Exception("bad parameter value for " + name);
+        }
+        else if (name == "Uint8Scalar")
+        {
+            if (str != "8")
+                throw Exception("bad parameter value for " + name);
+        }
+        else if (name == "Sint8Scalar")
+        {
+            if (str != "-8")
+                throw Exception("bad parameter value for " + name);
+        }
+        else if (name == "Uint16Scalar")
+        {
+            if (str != "16")
+                throw Exception("bad parameter value for " + name);
+        }
+        else if (name == "Sint16Scalar")
+        {
+            if (str != "-16")
+                throw Exception("bad parameter value for " + name);
+        }
+        else if (name == "Uint32Scalar")
+        {
+            if (str != "32")
+                throw Exception("bad parameter value for " + name);
+        }
+        else if (name == "Sint32Scalar")
+        {
+            if (str != "-32")
+                throw Exception("bad parameter value for " + name);
+        }
+        else if (name == "Real32Scalar")
+        {
+            if (str != "32.32")
+                throw Exception("bad parameter value for " + name);
+        }
+        else if (name == "Real64Scalar")
+        {
+            if (str != "64.64")
+                throw Exception("bad parameter value for " + name);
+        }
+        else if (name == "StringScalar")
+        {
+            if (str != "My String")
+                throw Exception("bad parameter value for " + name);
+        }
+        else
+        {
+            throw Exception("unexpected parameter:" + name);
+        }
+    }
+}
+
+static void _testIdentifyBody(WsmReader& reader)
+{
+    XmlEntry entry;
+    reader.expectStartTag(entry, WsmNamespaces::SOAP_ENVELOPE, "Envelope");
+
+    reader.setHideEmptyTags(true);
+    int nsType = reader.expectStartTag(entry, "Identify");
+    reader.expectEndTag(nsType, "Identify");
+}
+
 int main(int argc, char** argv)
 {
     verbose = getenv("PEGASUS_TEST_VERBOSE") ? true : false;
@@ -1177,6 +1306,42 @@ int main(int argc, char** argv)
             _testPullBody(reader);
             _testPullBodyErrors(reader);
         }
+
+        /* Enumerate with Filter test */
+        {
+            Buffer text;
+            FileSystem::loadFileToMemory(text, "./wsfilter.xml");
+            WsmReader reader((char*)text.getData());
+
+            if (verbose)
+                cout << "Testing instances." << endl;
+
+            _testEnumerateWithFilterBody(reader);
+        }
+
+        /* WS-Management Invoke test */
+        {
+            Buffer text;
+            FileSystem::loadFileToMemory(text, "./wsinvoke.xml");
+            WsmReader reader((char*)text.getData());
+
+            if (verbose)
+                cout << "Testing instances." << endl;
+
+            _testInvokeBody(reader);
+        }
+
+        /* WS-Management Identify test */
+        {
+            Buffer text;
+            FileSystem::loadFileToMemory(text, "./wsidentify.xml");
+            WsmReader reader((char*)text.getData());
+
+            if (verbose)
+                cout << "Testing instances." << endl;
+
+            _testIdentifyBody(reader);
+        }
     }
     catch(Exception& e)
     {
diff --git a/src/Pegasus/WsmServer/tests/WsmReader/wsfilter.xml b/src/Pegasus/WsmServer/tests/WsmReader/wsfilter.xml
new file mode 100644 (file)
index 0000000..57e34ff
--- /dev/null
@@ -0,0 +1,9 @@
+<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">\r
+<n:Enumerate>\r
+<w:OptimizeEnumeration/>\r
+<w:MaxElements>5000\r
+</w:MaxElements>\r
+<w:Filter Dialect="http://schemas.microsoft.com/wbem/wsman/1/WQL">select Status from CIM_ComputerSystem\r
+</w:Filter>\r
+</n:Enumerate>\r
+</s:Envelope>\r
diff --git a/src/Pegasus/WsmServer/tests/WsmReader/wsidentify.xml b/src/Pegasus/WsmServer/tests/WsmReader/wsidentify.xml
new file mode 100644 (file)
index 0000000..64f14c6
--- /dev/null
@@ -0,0 +1,3 @@
+<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsmid="http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd">\r
+<wsmid:Identify/>\r
+</s:Envelope>\r
diff --git a/src/Pegasus/WsmServer/tests/WsmReader/wsinvoke.xml b/src/Pegasus/WsmServer/tests/WsmReader/wsinvoke.xml
new file mode 100644 (file)
index 0000000..192f83b
--- /dev/null
@@ -0,0 +1,26 @@
+<p:MyMethod_INPUT xmlns:p="http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/MyClass.xsd">\r
+<p:BooleanScalar>true\r
+</p:BooleanScalar>\r
+<p:Uint8Scalar>8\r
+</p:Uint8Scalar>\r
+<p:Sint8Scalar>-8\r
+</p:Sint8Scalar>\r
+<p:Uint16Scalar>16\r
+</p:Uint16Scalar>\r
+<p:Sint16Scalar>-16\r
+</p:Sint16Scalar>\r
+<p:Uint32Scalar>32\r
+</p:Uint32Scalar>\r
+<p:Sint32Scalar>-32\r
+</p:Sint32Scalar>\r
+<p:Uint32Scalar>32\r
+</p:Uint32Scalar>\r
+<p:Sint32Scalar>-32\r
+</p:Sint32Scalar>\r
+<p:Real32Scalar>32.32\r
+</p:Real32Scalar>\r
+<p:Real64Scalar>64.64\r
+</p:Real64Scalar>\r
+<p:StringScalar>My String\r
+</p:StringScalar>\r
+</p:MyMethod_INPUT>\r
index fe66172925ff621ce1e2bd30387006b1b481a73f..0713b819a12f688dde905db207ac1a85d7504409 100644 (file)
@@ -185,7 +185,8 @@ static void _checkInstance(WsmInstance& inst, const char* text)
 {
     Buffer out;
     _appendSoapEnvelopeStart(out);
-    WsmWriter::appendInstanceElement(out, inst);
+    WsmWriter::appendInstanceElement(out, WSM_RESOURCEURI_CIMSCHEMAV2, inst,
+        PEGASUS_INSTANCE_NS, false);
     WsmWriter::appendEndTag(
         out, WsmNamespaces::SOAP_ENVELOPE, STRLIT("Envelope"));
 
@@ -400,7 +401,8 @@ static void  _testResponseFormatting(void)
     WsmInstance inst("testClass");
     WsmValue val("value");
     inst.addProperty(WsmProperty("property", val));
-    WsmWriter::appendInstanceElement(body, inst);
+    WsmWriter::appendInstanceElement(body, WSM_RESOURCEURI_CIMSCHEMAV2, inst,
+        PEGASUS_INSTANCE_NS, false);
 
     String messageId = WsmUtils::getMessageId();
     WxfGetRequest request(messageId, WsmEndpointReference());
@@ -477,7 +479,7 @@ static void  _testFaultFormatting(void)
         SoapNotUnderstoodFault soapFault(WsmNamespaces::supportedNamespaces[
             WsmNamespaces::WS_MAN].extendedName, "RequestedEPR");
         SoapFaultResponse response(relatesTo, 0, HTTP_METHOD__POST,
-            false, soapFault);
+            false, false, soapFault);
         SoapResponse soapResponse(&response);
 
         Buffer out = soapResponse.getResponseContent();
@@ -550,7 +552,7 @@ static void  _testFaultFormatting(void)
         WsmFault wsmFault(WsmFault::wsman_AccessDenied, "Whatever reason",
             ContentLanguageList(), "Whatever fault detail");
         WsmFaultResponse response(relatesTo, 0, HTTP_METHOD__POST,
-            false, wsmFault);
+            false, false, wsmFault);
         SoapResponse soapResponse(&response);
 
         Buffer out = soapResponse.getResponseContent();