version 1.47, 2006/09/01 18:45:06
|
version 1.48, 2006/10/06 17:38:54
|
|
|
| |
void CIMExportResponseDecoder::_handleHTTPMessage(HTTPMessage* httpMessage) | void CIMExportResponseDecoder::_handleHTTPMessage(HTTPMessage* httpMessage) |
{ | { |
PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportResponseDecoder::handleHTTPMessage()"); |
PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, |
|
"CIMExportResponseDecoder::_handleHTTPMessage()"); |
|
|
// | // |
// Parse the HTTP message: |
// Parse the HTTP CIM Export response message |
// | // |
|
ClientExceptionMessage* exceptionMessage; |
String startLine; |
|
Array<HTTPHeader> headers; |
|
char* content; | char* content; |
|
Array<HTTPHeader> headers; |
Uint32 contentLength; | Uint32 contentLength; |
String connectClose; |
|
Boolean cimReconnect=false; |
|
|
|
if (httpMessage->message.size() == 0) |
|
{ |
|
|
|
// l10n |
|
|
|
// CIMClientMalformedHTTPException* malformedHTTPException = |
|
// new CIMClientMalformedHTTPException("Empty HTTP response message."); |
|
|
|
MessageLoaderParms mlParms("ExportClient.CIMExportResponseDecoder.EMPTY_RESPONSE", "Empty HTTP response message."); |
|
String mlString(MessageLoader::getMessage(mlParms)); |
|
|
|
AutoPtr<CIMClientMalformedHTTPException> malformedHTTPException( |
|
new CIMClientMalformedHTTPException(mlString)); |
|
|
|
AutoPtr<ClientExceptionMessage> response( |
|
new ClientExceptionMessage(malformedHTTPException.get())); |
|
|
|
malformedHTTPException.release(); |
|
|
|
_outputQueue->enqueue(response.release()); |
|
PEG_METHOD_EXIT(); |
|
return; |
|
} |
|
|
|
httpMessage->parse(startLine, headers, contentLength); |
|
// |
|
// Check for Connection: Close |
|
// |
|
if (HTTPMessage::lookupHeader(headers, "Connection", connectClose, false)) |
|
{ |
|
if (String::equalNoCase(connectClose, "Close")) |
|
{ |
|
//reconnect and then resend next request. |
|
cimReconnect=true; |
|
} |
|
Tracer::trace(TRC_XML_IO, Tracer::LEVEL2, "%s", |
|
httpMessage->message.getData()); |
|
} |
|
|
|
|
|
// |
|
// Get the status line info |
|
// |
|
|
|
String httpVersion; |
|
Uint32 statusCode; | Uint32 statusCode; |
String reasonPhrase; | String reasonPhrase; |
|
Boolean cimReconnect; |
|
Boolean valid; |
|
HTTPExportResponseDecoder::parseHTTPHeaders(httpMessage, exceptionMessage, |
|
headers, contentLength, statusCode, reasonPhrase, cimReconnect, valid); |
| |
Boolean parsableMessage = HTTPMessage::parseStatusLine( |
// |
startLine, httpVersion, statusCode, reasonPhrase); |
// Return exception on any parse errors from the HTTP export response |
if (!parsableMessage) |
// message |
|
// |
|
if (!valid) |
{ | { |
|
_outputQueue->enqueue(exceptionMessage); |
// l10n |
|
|
|
// CIMClientMalformedHTTPException* malformedHTTPException = new |
|
// CIMClientMalformedHTTPException("Malformed HTTP response message."); |
|
|
|
MessageLoaderParms mlParms("ExportClient.CIMExportResponseDecoder.MALFORMED_RESPONSE", "Malformed HTTP response message."); |
|
String mlString(MessageLoader::getMessage(mlParms)); |
|
|
|
AutoPtr<CIMClientMalformedHTTPException> malformedHTTPException(new |
|
CIMClientMalformedHTTPException(mlString)); |
|
|
|
AutoPtr<ClientExceptionMessage> response( |
|
new ClientExceptionMessage(malformedHTTPException.get())); |
|
|
|
malformedHTTPException.release(); |
|
|
|
response->setCloseConnect(cimReconnect); |
|
_outputQueue->enqueue(response.release()); |
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return; | return; |
} | } |
|
|
return; | return; |
} | } |
| |
// We have the response. If authentication failed, we will generate a |
|
// CIMClientHTTPErrorException below with the "401 Unauthorized" status |
|
// in the (re-challenge) response. |
|
|
|
// |
|
// Check for a success (200 OK) response |
|
// |
|
|
|
if (statusCode != HTTP_STATUSCODE_OK) |
|
{ |
|
String cimError; |
|
String pegasusError; |
|
|
|
HTTPMessage::lookupHeader(headers, "CIMError", cimError); |
|
HTTPMessage::lookupHeader(headers, PEGASUS_HTTPHEADERTAG_ERRORDETAIL, pegasusError); |
|
try |
|
{ |
|
pegasusError = XmlReader::decodeURICharacters(pegasusError); |
|
} |
|
catch (const ParseError&) |
|
{ |
|
// Ignore this exception. We're more interested in having the |
|
// message in encoded form than knowing that the format is invalid. |
|
} |
|
|
|
AutoPtr<CIMClientHTTPErrorException> httpError( |
|
new CIMClientHTTPErrorException(statusCode, reasonPhrase, |
|
cimError, pegasusError)); |
|
AutoPtr<ClientExceptionMessage> response( |
|
new ClientExceptionMessage(httpError.get())); |
|
|
|
httpError.release(); |
|
|
|
response->setCloseConnect(cimReconnect); |
|
_outputQueue->enqueue(response.release()); |
|
PEG_METHOD_EXIT(); |
|
return; |
|
} |
|
|
|
// |
|
// Search for "CIMOperation" header: |
|
// |
|
|
|
String cimExport; |
|
|
|
if (!HTTPMessage::lookupHeader(headers, "CIMExport", cimExport, true)) |
|
{ |
|
// |
|
// Missing CIMExport HTTP header |
|
// |
|
MessageLoaderParms mlParms( |
|
"ExportClient.CIMExportResponseDecoder.MISSING_CIMEXP_HEADER", |
|
"Missing CIMExport HTTP header"); |
|
String mlString(MessageLoader::getMessage(mlParms)); |
|
|
|
AutoPtr<CIMClientMalformedHTTPException> malformedHTTPException(new |
|
CIMClientMalformedHTTPException(mlString)); |
|
|
|
AutoPtr<ClientExceptionMessage> response( |
|
new ClientExceptionMessage(malformedHTTPException.get())); |
|
|
|
malformedHTTPException.release(); |
|
|
|
response->setCloseConnect(cimReconnect); |
|
_outputQueue->enqueue(response.release()); |
|
PEG_METHOD_EXIT(); |
|
return; |
|
} |
|
|
|
// |
|
// Search for "Content-Type" header: |
|
// |
|
|
|
String cimContentType; |
|
|
|
if (!HTTPMessage::lookupHeader( |
|
headers, "Content-Type", cimContentType, true)) |
|
{ |
|
AutoPtr<CIMClientMalformedHTTPException> malformedHTTPException(new |
|
CIMClientMalformedHTTPException("Missing CIMContentType HTTP header")); |
|
AutoPtr<ClientExceptionMessage> response( |
|
new ClientExceptionMessage(malformedHTTPException.get())); |
|
|
|
malformedHTTPException.release(); |
|
|
|
response->setCloseConnect(cimReconnect); |
|
_outputQueue->enqueue(response.release()); |
|
PEG_METHOD_EXIT(); |
|
return; |
|
} |
|
|
|
|
|
// |
|
// Zero-terminate the message: |
|
// |
|
|
|
httpMessage->message.append('\0'); |
|
|
|
// Calculate the beginning of the content from the message size and |
|
// the content length. Subtract 1 to take into account the null |
|
// character we just added to the end of the message. |
|
|
|
content = (char *) httpMessage->message.getData() + |
|
httpMessage->message.size() - contentLength - 1; |
|
|
|
// |
|
// If it is a method response, then dispatch it to the handler: |
|
// |
|
|
|
if (!String::equalNoCase(cimExport, "MethodResponse")) |
|
{ |
|
// |
|
// Expected CIMExport HTTP header value MethodResponse |
|
// |
|
MessageLoaderParms mlParms( |
|
"ExportClient.CIMExportResponseDecoder.EXPECTED_METHODRESPONSE", |
|
"Received CIMExport HTTP header value \"$0\", " |
|
"expected \"MethodResponse\"", cimExport); |
|
String mlString(MessageLoader::getMessage(mlParms)); |
|
|
|
AutoPtr<CIMClientMalformedHTTPException> malformedHTTPException( |
|
new CIMClientMalformedHTTPException(mlString)); |
|
|
|
AutoPtr<ClientExceptionMessage> response( |
|
new ClientExceptionMessage(malformedHTTPException.get())); |
|
|
|
malformedHTTPException.release(); |
|
|
|
response->setCloseConnect(cimReconnect); |
|
_outputQueue->enqueue(response.release()); |
|
PEG_METHOD_EXIT(); |
|
return; |
|
} |
|
|
|
_handleMethodResponse(content,cimReconnect); |
|
PEG_METHOD_EXIT(); |
|
} |
|
|
|
void CIMExportResponseDecoder::_handleMethodResponse(char* content,Boolean cimReconnect) |
|
{ |
|
PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportResponseDecoder::_handleMethodResponse()"); |
|
AutoPtr<Message> response; |
|
|
|
// | // |
// Create and initialize XML parser: |
// Validate the HTTP headers in the export response message |
// | // |
|
HTTPExportResponseDecoder::validateHTTPHeaders(httpMessage, headers, |
|
contentLength, statusCode, cimReconnect, reasonPhrase, content, |
|
exceptionMessage, valid); |
| |
XmlParser parser((char*)content); |
|
XmlEntry entry; |
|
|
|
try |
|
{ |
|
// | // |
// Process <?xml ... > |
// Return exception on any errors in the HTTP headers in the export |
|
// response message |
// | // |
|
if (!valid) |
const char* xmlVersion = 0; |
|
const char* xmlEncoding = 0; |
|
|
|
XmlReader::getXmlDeclaration(parser, xmlVersion, xmlEncoding); |
|
|
|
// |
|
// Process <CIM ... > |
|
// |
|
|
|
const char* cimVersion = 0; |
|
const char* dtdVersion = 0; |
|
|
|
XmlReader::getCimStartTag(parser, cimVersion, dtdVersion); |
|
|
|
// |
|
// Expect <MESSAGE ... > |
|
// |
|
|
|
String messageId; |
|
String protocolVersion; |
|
|
|
if (!XmlReader::getMessageStartTag(parser, messageId, protocolVersion)) { |
|
|
|
// l10n |
|
|
|
// throw XmlValidationError( |
|
// parser.getLine(), "expected MESSAGE element"); |
|
|
|
MessageLoaderParms mlParms("ExportClient.CIMExportResponseDecoder.EXPECTED_MESSAGE_ELEMENT", "expected MESSAGE element"); |
|
String mlString(MessageLoader::getMessage(mlParms)); |
|
|
|
PEG_METHOD_EXIT(); |
|
throw XmlValidationError(parser.getLine(), mlString); |
|
|
|
} |
|
|
|
if (!String::equalNoCase(protocolVersion, "1.0")) |
|
{ | { |
|
_outputQueue->enqueue(exceptionMessage); |
// l10n |
|
|
|
// CIMClientResponseException* responseException = |
|
// new CIMClientResponseException( |
|
// String("Received unsupported protocol version \"") + |
|
// protocolVersion + "\", expected \"1.0\""); |
|
|
|
MessageLoaderParms mlParms("ExportClient.CIMExportResponseDecoder.UNSUPPORTED_PROTOCOL", "Received unsupported protocol version \"$0\", expected \"$1\"", protocolVersion, "1.0"); |
|
String mlString(MessageLoader::getMessage(mlParms)); |
|
|
|
AutoPtr<CIMClientResponseException> responseException( |
|
new CIMClientResponseException(mlString)); |
|
|
|
AutoPtr<ClientExceptionMessage> response( |
|
new ClientExceptionMessage(responseException.get())); |
|
|
|
responseException.release(); |
|
|
|
response->setCloseConnect(cimReconnect); |
|
_outputQueue->enqueue(response.release()); |
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return; | return; |
} | } |
| |
// | // |
// Expect <SIMPLEEXPRSP ... > |
// Decode the export response message |
// | // |
|
Message* responseMessage; |
XmlReader::expectStartTag(parser, entry, "SIMPLEEXPRSP"); |
HTTPExportResponseDecoder::decodeExportResponse(content, cimReconnect, |
|
responseMessage); |
// |
_outputQueue->enqueue(responseMessage); |
// Expect <EXPMETHODRESPONSE ... > |
|
// |
|
|
|
const char* expMethodResponseName = 0; |
|
Boolean isEmptyTag = false; |
|
|
|
if (XmlReader::getEMethodResponseStartTag( |
|
parser, expMethodResponseName, isEmptyTag)) |
|
{ |
|
if (System::strcasecmp(expMethodResponseName, "ExportIndication") == |
|
0) |
|
{ |
|
response.reset(_decodeExportIndicationResponse( |
|
parser, messageId, isEmptyTag)); |
|
} |
|
else |
|
{ |
|
// |
|
// Unrecognized ExpMethodResponse name attribute |
|
// |
|
MessageLoaderParms mlParms( |
|
"ExportClient.CIMExportResponseDecoder.UNRECOGNIZED_EXPMETHRSP", |
|
"Unrecognized ExpMethodResponse name \"$0\"", |
|
expMethodResponseName); |
|
String mlString(MessageLoader::getMessage(mlParms)); |
|
|
|
PEG_METHOD_EXIT(); |
|
throw XmlValidationError(parser.getLine(), mlString); |
|
} |
|
|
|
// |
|
// Handle end tag: |
|
// |
|
|
|
if (!isEmptyTag) |
|
{ |
|
XmlReader::expectEndTag(parser, "EXPMETHODRESPONSE"); |
|
} |
|
} |
|
else |
|
{ |
|
// |
|
// Expected ExpMethodResponse element |
|
// |
|
MessageLoaderParms mlParms( |
|
"ExportClient.CIMExportResponseDecoder." |
|
"EXPECTED_EXPMETHODRESPONSE_ELEMENT", |
|
"expected EXPMETHODRESPONSE element"); |
|
String mlString(MessageLoader::getMessage(mlParms)); |
|
|
|
PEG_METHOD_EXIT(); |
|
throw XmlValidationError(parser.getLine(), mlString); |
|
} |
|
|
|
// |
|
// Handle end tags: |
|
// |
|
XmlReader::expectEndTag(parser, "SIMPLEEXPRSP"); |
|
XmlReader::expectEndTag(parser, "MESSAGE"); |
|
XmlReader::expectEndTag(parser, "CIM"); |
|
} |
|
catch (XmlException& x) |
|
{ |
|
response.reset(new ClientExceptionMessage( |
|
new CIMClientXmlException(x.getMessage()))); |
|
} |
|
catch (Exception& x) |
|
{ |
|
// Might get MalformedObjectNameException, InvalidNameException, etc. |
|
|
|
response.reset(new ClientExceptionMessage( |
|
new CIMClientResponseException(x.getMessage()))); |
|
} |
|
|
|
// l10n |
|
// Note: Ignore any ContentLanguage set in the export response |
|
|
|
response->setCloseConnect(cimReconnect); |
|
_outputQueue->enqueue(response.release()); |
|
PEG_METHOD_EXIT(); |
|
} |
|
|
|
CIMExportIndicationResponseMessage* CIMExportResponseDecoder::_decodeExportIndicationResponse( |
|
XmlParser& parser, |
|
const String& messageId, |
|
Boolean isEmptyImethodresponseTag) |
|
{ |
|
PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportResponseDecoder::_decodeExportIndicationResponse()"); |
|
XmlEntry entry; |
|
CIMException cimException; |
|
|
|
if (!isEmptyImethodresponseTag) |
|
{ |
|
if (XmlReader::getErrorElement(parser, cimException)) |
|
{ |
|
PEG_METHOD_EXIT(); |
|
return(new CIMExportIndicationResponseMessage( |
|
messageId, |
|
cimException, |
|
QueueIdStack())); |
|
} |
|
|
|
if (XmlReader::testStartTagOrEmptyTag(parser, entry, "IRETURNVALUE")) |
|
{ |
|
if (entry.type != XmlEntry::EMPTY_TAG) |
|
{ |
|
XmlReader::expectEndTag(parser, "IRETURNVALUE"); |
|
} |
|
} |
|
} |
|
| |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return(new CIMExportIndicationResponseMessage( |
|
messageId, |
|
cimException, |
|
QueueIdStack())); |
|
} | } |
| |
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |