};
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
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 << ", ";
{
T x;
cv.get(x);
- _print<T>(os, x);
+ Print<T>::func(os, x);
os << endl;
}
};
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
#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>
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 */
//
////////////////////////////////////////////////////////////////////////////////
-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)
{
}
}
}
-Boolean XmlParser::next(
+Boolean XmlParser::_next(
XmlEntry& entry,
Boolean includeComment)
{
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)
{
// 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.
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(
XmlNamespace* _supportedNamespaces;
Stack<XmlNamespace> _nameSpaces;
int _currentUnsupportedNSType;
+ Boolean _hideEmptyTags;
};
PEGASUS_COMMON_LINKAGE void XmlAppendCString(
{
MessageLoaderParms mlParms(
"Common.XmlReader.EXPECTED_CDATA",
- "Expected content of CDATA");
+ "Expected content or CDATA");
throw XmlValidationError(parser.getLine(), mlParms);
}
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;
PEGASUS_ASSERT(caughtException); \
} while(0)
-void testNamespaceSupport()
+void testNamespaceSupport(Boolean hideEmptyTags)
{
XmlNamespace testNamespaces[] =
{
" <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));
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);
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"));
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);
// 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));
}
}
{
try
{
- _parseFile(argv[i]);
+ _parseFile(argv[i], true);
+ _parseFile(argv[i], false);
}
catch (Exception& e)
{
testWhitespaceHandling();
- testNamespaceSupport();
+ testNamespaceSupport(true);
+ testNamespaceSupport(false);
cout << argv[0] << " +++++ passed all tests" << endl;
#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
}
break;
+ case WS_INVOKE:
+ {
+ wsmResponse.reset(_mapToWsInvokeResponse(
+ (WsInvokeRequest*)wsmRequest,
+ (CIMInvokeMethodResponseMessage*)message));
+ break;
+ }
+
default:
PEGASUS_ASSERT(0);
break;
break;
default:
+ // Initialize to prevent uninitialized subcode error.
+ subcode = WsmFault::wsman_InternalError;
PEGASUS_ASSERT(0);
}
WsmInstance wsmInstance;
convertCimToWsmInstance(
+ wsmRequest->epr.resourceUri,
response->getResponseData().getCimInstance(),
wsmInstance,
wsmRequest->epr.getNamespace());
{
WsmEndpointReference epr;
- convertObjPathToEPR(response->instanceName, epr,
+ convertObjPathToEPR(
+ wsmRequest->epr.resourceUri,
+ response->instanceName,
+ epr,
wsmRequest->epr.getNamespace());
WxfCreateResponse* wsmResponse =
{
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*
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);
}
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);
}
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)
const CIMValue& cimValue = cimProperty.getValue();
WsmValue wsmValue;
- convertCimToWsmValue(cimValue, wsmValue, nameSpace);
+ convertCimToWsmValue(resourceUri, cimValue, wsmValue, nameSpace);
WsmProperty wsmProperty(propertyName, wsmValue);
wsmInstance.addProperty(wsmProperty);
}
void CimToWsmResponseMapper::convertCimToWsmValue(
+ const String& resourceUri,
const CIMValue& cimValue,
WsmValue& wsmValue,
const String& nameSpace)
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);
{
WsmInstance wsmInstance;
convertCimToWsmInstance(
+ resourceUri,
CIMInstance(cimObjects[i]),
wsmInstance,
nameSpace);
{
WsmInstance wsmInstance;
convertCimToWsmInstance(
- cimInstances[i], wsmInstance, nameSpace);
+ resourceUri,
+ cimInstances[i],
+ wsmInstance,
+ nameSpace);
wsmInstances.append(wsmInstance);
}
wsmValue.set(wsmInstances);
WsmEndpointReference epr;
CIMObjectPath objPath;
cimValue.get(objPath);
- convertObjPathToEPR(objPath, epr, nameSpace);
+ convertObjPathToEPR(resourceUri, objPath, epr, nameSpace);
wsmValue.set(epr);
break;
}
{
WsmInstance wsmInstance;
convertCimToWsmInstance(
+ resourceUri,
CIMInstance(cimObject), wsmInstance, nameSpace);
wsmValue.set(wsmInstance);
}
WsmInstance wsmInstance;
CIMInstance cimInstance;
cimValue.get(cimInstance);
- convertCimToWsmInstance(cimInstance, wsmInstance, nameSpace);
+ convertCimToWsmInstance(
+ resourceUri, cimInstance, wsmInstance, nameSpace);
wsmValue.set(wsmInstance);
break;
}
}
void CimToWsmResponseMapper::convertObjPathToEPR(
+ const String& resourceUri,
const CIMObjectPath& objPath,
WsmEndpointReference& epr,
const String& nameSpace)
else
epr.address = WSM_ADDRESS_ANONYMOUS;
- epr.resourceUri = String(WSM_RESOURCEURI_CIMSCHEMAV2) + "/" +
+ epr.resourceUri = WsmUtils::getRootResourceUri(resourceUri) + "/" +
objPath.getClassName().getString();
CIMNamespaceName cimNS = objPath.getNameSpace();
{
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);
}
}
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)
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
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);
const WsmRequest* wsmRequest,
const CIMResponseMessage* message);
+ WsInvokeResponse* _mapToWsInvokeResponse(
+ const WsInvokeRequest* wsmRequest,
+ const CIMInvokeMethodResponseMessage* response);
+
ContentLanguageList _getContentLanguages(const OperationContext& context)
{
if (context.contains(ContentLanguageListContainer::NAME))
LIBRARIES = \
pegrepository \
+ pegwql \
pegconfig \
pegcommon
((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);
#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,
#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"
{
}
+void WsmReader::setHideEmptyTags(Boolean flag)
+{
+ _parser.setHideEmptyTags(flag);
+}
+
//-----------------------------------------------------------------------------
//
// getXmlDeclaration()
}
}
+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,
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) ||
// 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
WsmbPolymorphismMode& polymorphismMode,
WsenEnumerationMode& enumerationMode,
Boolean& optimized,
- Uint32& maxElements)
+ Uint32& maxElements,
+ String& queryLanguage,
+ String& query,
+ SharedPtr<WQLSelectStatement>& selectStatement)
{
XmlEntry entry;
expectStartOrEmptyTag(
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))
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
#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
WsmReader(char* text);
~WsmReader();
+ void setHideEmptyTags(Boolean flag);
+
Boolean getXmlDeclaration(
const char*& xmlVersion, const char*& xmlEncoding);
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);
WsmbPolymorphismMode& polymorphismMode,
WsenEnumerationMode& enumerationMode,
Boolean& optimized,
- Uint32& maxElements);
+ Uint32& maxElements,
+ String& queryLanguage,
+ String& query,
+ SharedPtr<WQLSelectStatement>& selectStatement);
void decodePullBody(
Uint64& enumerationContext,
void decodeReleaseBody(Uint64& enumerationContext);
+ void decodeInvokeInputBody(
+ const String& className,
+ const String& methodName,
+ WsmInstance& instance);
+
void getInstanceElement(WsmInstance& instance);
Boolean getPropertyElement(
int nsType,
WsmValue& propValue);
void getValueElement(WsmValue& value, int nsType, const char* propNameTag);
+ void decodeFilter(
+ String& queryLanguage,
+ String& query,
+ SharedPtr<WQLSelectStatement>& selectStatement);
+
private:
XmlParser _parser;
#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
WS_ENUMERATION_ENUMERATE,
WS_ENUMERATION_PULL,
- WS_ENUMERATION_RELEASE
+ WS_ENUMERATION_RELEASE,
+
+ /* WS-Management invoke */
+ WS_INVOKE
// etc.
};
: messageId(messageId_),
httpMethod(HTTP_METHOD__POST),
httpCloseConnect(false),
+ omitXMLProcessingInstruction(false),
queueId(0),
requestEpr(false),
maxEnvelopeSize(0),
AcceptLanguageList acceptLanguages;
ContentLanguageList contentLanguages;
Boolean httpCloseConnect;
+ Boolean omitXMLProcessingInstruction;
Uint32 queueId;
Boolean requestEpr;
Uint32 maxEnvelopeSize;
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_),
optimized(optimized_),
maxElements(maxElements_),
enumerationMode(enumerationMode_),
- polymorphismMode(polymorphismMode_)
+ polymorphismMode(polymorphismMode_),
+ queryLanguage(queryLanguage_),
+ query(query_),
+ selectStatement(selectStatement_)
+ {
+ }
+
+ ~WsenEnumerateRequest()
{
}
Uint32 maxElements;
WsenEnumerationMode enumerationMode;
WsmbPolymorphismMode polymorphismMode;
+ const String queryLanguage;
+ const String query;
+ SharedPtr<WQLSelectStatement> selectStatement;
};
class WsenPullRequest : public WsmRequest
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 */
#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),
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(
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
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;
}
httpMessage->ipAddress,
httpMessage->acceptLanguages,
httpMessage->contentLanguages,
- httpCloseConnect);
+ httpCloseConnect,
+ omitXMLProcessingInstruction);
PEG_METHOD_EXIT();
}
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)
{
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);
// Parse the SOAP Body while decoding each action
//
+ String className;
+ String methodName;
+
if (wsaAction == WSM_ACTION_GET)
{
request.reset(_decodeWSTransferGet(
wsaMessageId,
epr));
}
+ else if (_parseInvokeAction(wsaAction, className, methodName))
+ {
+ request.reset(_decodeWSInvoke(
+ wsmReader,
+ wsaMessageId,
+ epr,
+ className,
+ methodName));
+ }
else
{
throw WsmFault(
request->acceptLanguages = wsmLocale;
request->contentLanguages = httpContentLanguages;
request->httpCloseConnect = httpCloseConnect;
+ request->omitXMLProcessingInstruction = omitXMLProcessingInstruction;
request->queueId = queueId;
request->requestEpr = wsmRequestEpr;
request->maxEnvelopeSize = wsmMaxEnvelopeSize;
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;
}
e.getMessage(),
e.getContentLanguages());
_wsmProcessor->sendResponse(new WsmFaultResponse(
- wsaMessageId, queueId, httpMethod, httpCloseConnect, fault));
+ wsaMessageId, queueId, httpMethod, httpCloseConnect,
+ omitXMLProcessingInstruction, fault));
PEG_METHOD_EXIT();
return;
}
e.getMessage(),
e.getContentLanguages());
_wsmProcessor->sendResponse(new WsmFaultResponse(
- wsaMessageId, queueId, httpMethod, httpCloseConnect, fault));
+ wsaMessageId, queueId, httpMethod, httpCloseConnect,
+ omitXMLProcessingInstruction, fault));
PEG_METHOD_EXIT();
return;
}
{
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;
}
{
WsmFault fault(WsmFault::wsman_InternalError);
_wsmProcessor->sendResponse(new WsmFaultResponse(
- wsaMessageId, queueId, httpMethod, httpCloseConnect, fault));
+ wsaMessageId, queueId, httpMethod, httpCloseConnect,
+ omitXMLProcessingInstruction, fault));
PEG_METHOD_EXIT();
return;
}
WsenEnumerationMode enumerationMode = WSEN_EM_UNKNOWN;
Boolean optimized = false;
Uint32 maxElements = 0;
+ String queryLanguage;
+ String query;
+ SharedPtr<WQLSelectStatement> selectStatement;
XmlEntry entry;
wsmReader.expectStartOrEmptyTag(
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");
}
// 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(
optimized,
maxElements,
enumerationMode,
- polymorphismMode);
+ polymorphismMode,
+ queryLanguage,
+ query,
+ selectStatement);
}
WsenPullRequest* WsmRequestDecoder::_decodeWSEnumerationPull(
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
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(
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;
_queueId(request->queueId),
_httpMethod(request->httpMethod),
_httpCloseConnect(request->httpCloseConnect),
+ _omitXMLProcessingInstruction(request->omitXMLProcessingInstruction),
_maxEnvelopeSize(request->maxEnvelopeSize),
_contentLanguages(contentLanguages)
{
Uint32 queueId,
HttpMethod httpMethod,
Boolean httpCloseConnect,
+ Boolean omitXMLProcessingInstruction,
const ContentLanguageList& contentLanguages)
: _type(type),
_messageId(WsmUtils::getMessageId()),
_queueId(queueId),
_httpMethod(httpMethod),
_httpCloseConnect(httpCloseConnect),
+ _omitXMLProcessingInstruction(omitXMLProcessingInstruction),
_maxEnvelopeSize(0),
_contentLanguages(contentLanguages)
{
return _contentLanguages;
}
+ Boolean getOmitXMLProcessingInstruction() const
+ {
+ return _omitXMLProcessingInstruction;
+ }
+
private:
WsmResponse(const WsmResponse&);
Uint32 _queueId;
HttpMethod _httpMethod;
Boolean _httpCloseConnect;
+ Boolean _omitXMLProcessingInstruction;
Uint32 _maxEnvelopeSize;
ContentLanguageList _contentLanguages;
};
Uint32 queueId,
HttpMethod httpMethod,
Boolean httpCloseConnect,
+ Boolean omitXMLProcessingInstruction,
const WsmFault& fault)
: WsmResponse(
WSM_FAULT,
queueId,
httpMethod,
httpCloseConnect,
+ omitXMLProcessingInstruction,
fault.getReasonLanguage()),
_fault(fault)
{
Uint32 queueId,
HttpMethod httpMethod,
Boolean httpCloseConnect,
+ Boolean omitXMLProcessingInstruction,
const SoapNotUnderstoodFault& fault)
: WsmResponse(
SOAP_FAULT,
queueId,
httpMethod,
httpCloseConnect,
+ omitXMLProcessingInstruction,
fault.getMessageLanguage()),
_fault(fault)
{
WS_TRANSFER_GET,
request,
contentLanguages),
- _instance(inst)
+ _instance(inst),
+ _resourceUri(request->epr.resourceUri)
{
}
return _instance;
}
+ const String& getResourceUri() const
+ {
+ return _resourceUri;
+ }
+
private:
WsmInstance _instance;
+ String _resourceUri;
};
class WxfPutResponse : public WsmResponse
// EPR in the request.
WsmEndpointReference _reference;
Boolean _requestedEPR;
+ String _resourceUri;
};
class WxfCreateResponse : public WsmResponse
contentLanguages),
_enumerationContext((Uint64) -1),
_isComplete(false),
- _enumerationData(data)
+ _enumerationData(data),
+ _resourceUri(request->epr.resourceUri)
{
}
~WsenPullResponse()
_enumerationContext = context;
}
+ const String& getResourceUri() const
+ {
+ return _resourceUri;
+ }
+
private:
Uint64 _enumerationContext;
Boolean _isComplete;
WsenEnumerationData _enumerationData;
+ String _resourceUri;
};
class WsenEnumerateResponse : public WsmResponse
_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);
_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);
}
_isComplete(false),
_requestItemCount(request->requestItemCount),
_itemCount(itemCount),
- _enumerationData(epr)
+ _enumerationData(epr),
+ _resourceUri(request->epr.resourceUri)
{
PEGASUS_ASSERT(request->enumerationMode == WSEN_EM_EPR);
}
_isComplete(false),
_requestItemCount(request->requestItemCount),
_itemCount(itemCount),
- _enumerationData(data)
+ _enumerationData(data),
+ _resourceUri(request->epr.resourceUri)
{
PEGASUS_ASSERT(request->enumerationMode == data.enumerationMode);
}
_enumerationContext = context;
}
+ const String& getResourceUri() const
+ {
+ return _resourceUri;
+ }
+
private:
Uint64 _enumerationContext;
Boolean _requestItemCount;
Uint32 _itemCount;
WsenEnumerationData _enumerationData;
+ String _resourceUri;
};
class WsenReleaseResponse : public WsmResponse
}
};
+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 */
response->getQueueId(),
response->getHttpMethod(),
response->getHttpCloseConnect(),
+ response->getOmitXMLProcessingInstruction(),
fault);
SoapResponse soapResponse(&faultResponse);
response->getQueueId(),
response->getHttpMethod(),
response->getHttpCloseConnect(),
+ response->getOmitXMLProcessingInstruction(),
fault);
return new SoapResponse(&faultResponse);
_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
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);
{
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);
response->getEnumerationContext(),
response->isComplete(),
response->getEnumerationData(),
- numDataItemsEncoded))
+ numDataItemsEncoded,
+ response->getResourceUri()))
{
soapResponse.reset(_buildEncodingLimitFault(response));
}
response->getEnumerationContext(),
response->isComplete(),
response->getEnumerationData(),
- numDataItemsEncoded))
+ numDataItemsEncoded,
+ response->getResourceUri()))
{
soapResponse.reset(_buildEncodingLimitFault(response));
}
Uint64 contextId,
Boolean isComplete,
WsenEnumerationData& data,
- Uint32& numDataItemsEncoded)
+ Uint32& numDataItemsEncoded,
+ const String& resourceUri)
{
Buffer bodyHeader, bodyTrailer;
}
// Now add the list of items
- Uint32 i;
+ Uint32 i = 0;
if (data.enumerationMode == WSEN_EM_OBJECT)
{
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;
data.classUri).getString());
}
- WsmWriter::appendInstanceElement(body, data.instances[i]);
+ WsmWriter::appendInstanceElement(body, resourceUri,
+ data.instances[i], PEGASUS_INSTANCE_NS, false);
WsmWriter::appendStartTag(
body,
_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
void _encodeWsenReleaseResponse(WsenReleaseResponse* response);
void _encodeWsmFaultResponse(WsmFaultResponse* response);
void _encodeSoapFaultResponse(SoapFaultResponse* response);
+ void _encodeWsInvokeResponse(WsInvokeResponse* response);
Boolean _encodeEnumerationData(
SoapResponse& soapResponse,
Uint64 contextId,
Boolean isComplete,
WsenEnumerationData& data,
- Uint32& numDataItemsEncoded);
+ Uint32& numDataItemsEncoded,
+ const String& resourceUri);
};
PEGASUS_NAMESPACE_END
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)
{
case WS_ENUMERATION_RELEASE:
break;
+ case WS_INVOKE:
+ {
+ cimRequest.reset(mapToCimInvokeMethodRequest(
+ (WsInvokeRequest*)request));
+ break;
+ }
+
default:
PEGASUS_ASSERT(0);
}
CIMGetInstanceRequestMessage*
WsmToCimRequestMapper::mapToCimGetInstanceRequest(
- WxfGetRequest* request)
+ WxfGetRequest* request)
{
CIMNamespaceName nameSpace;
CIMObjectPath instanceName;
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)
{
// 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,
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(
}
}
+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.
WsenEnumerateRequest* request);
CIMEnumerateInstanceNamesRequestMessage*
mapToCimEnumerateInstanceNamesRequest(WsenEnumerateRequest* request);
+ CIMInvokeMethodRequestMessage* mapToCimInvokeMethodRequest(
+ WsInvokeRequest* request);
static CIMName convertResourceUriToClassName(const String& resourceUri);
String convertEPRAddressToHostname(const String& addr);
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;
#include <Pegasus/Common/String.h>
#include <Pegasus/Common/PegasusAssert.h>
#include "WsmUtils.h"
+#include "WsmConstants.h"
PEGASUS_NAMESPACE_BEGIN
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
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();
//
//%/////////////////////////////////////////////////////////////////////////////
+#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:
}
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:
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:
}
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:
}
}
-
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:
}
}
+Boolean WsmValue::isArray() const
+{
+ return _rep->isArray;
+}
+
+Boolean WsmValue::isNull() const
+{
+ return _rep->isNull;
+}
+
+WsmType WsmValue::getType() const
+{
+ return _rep->type;
+}
+
PEGASUS_NAMESPACE_END
WSMTYPE_OTHER
};
-
class PEGASUS_WSMSERVER_LINKAGE WsmValue
{
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();
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
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(':');
}
//-----------------------------------------------------------------------------
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("\"");
// 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\"/>");
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;
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;
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;
{
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;
}
{
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;
}
{
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;
}
Buffer& out,
const String& action,
HttpMethod httpMethod,
+ Boolean omitXMLProcessingInstruction,
const ContentLanguageList& contentLanguages,
Boolean isFault,
Uint32 contentLength)
}
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);
}
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
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(
Buffer& out,
const String& action,
HttpMethod httpMethod,
+ Boolean omitXMLProcessingInstruction,
const ContentLanguageList& contentLanguages,
Boolean isFault,
Uint32 contentLength = 0);
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();
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>
{
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)
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");
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)
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)
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 !=
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() ||
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" &&
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 ||
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 ||
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" ||
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 ||
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");
}
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");
}
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)
{
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");
}
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");
}
}
}
+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;
_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)
{
--- /dev/null
+<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
--- /dev/null
+<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
--- /dev/null
+<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
{
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"));
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());
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();
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();