(file) Return to WsmResponseEncoder.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / WsmServer

  1 kumpf 1.2 //%2006////////////////////////////////////////////////////////////////////////
  2           //
  3           // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4           // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6           // IBM Corp.; EMC Corporation, The Open Group.
  7           // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8           // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9           // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10           // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11           // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12           // EMC Corporation; Symantec Corporation; The Open Group.
 13           //
 14           // Permission is hereby granted, free of charge, to any person obtaining a copy
 15           // of this software and associated documentation files (the "Software"), to
 16           // deal in the Software without restriction, including without limitation the
 17           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18           // sell copies of the Software, and to permit persons to whom the Software is
 19           // furnished to do so, subject to the following conditions:
 20           // 
 21           // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22 kumpf 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29           //
 30           //==============================================================================
 31           //
 32           //%/////////////////////////////////////////////////////////////////////////////
 33           
 34           #include <cctype>
 35           #include <cstdio>
 36           #include <Pegasus/Common/Config.h>
 37           #include <Pegasus/Common/HTTPConnection.h>
 38           #include <Pegasus/Common/HTTPMessage.h>
 39           #include <Pegasus/Common/Tracer.h>
 40           #include <Pegasus/Common/AutoPtr.h>
 41           #include <Pegasus/Common/MessageLoader.h>
 42           
 43 kumpf 1.2 #include "WsmConstants.h"
 44           #include "WsmReader.h"
 45           #include "WsmWriter.h"
 46           #include "WsmResponseEncoder.h"
 47 kumpf 1.4 #include "WsmToCimRequestMapper.h"
 48           #include "SoapResponse.h"
 49 kumpf 1.2 
 50           PEGASUS_USING_STD;
 51           
 52           PEGASUS_NAMESPACE_BEGIN
 53           
 54           WsmResponseEncoder::WsmResponseEncoder()
 55           {
 56           }
 57           
 58           WsmResponseEncoder::~WsmResponseEncoder()
 59           {
 60           }
 61           
 62 kumpf 1.4 void WsmResponseEncoder::_sendResponse(SoapResponse* response)
 63 kumpf 1.2 {
 64               PEG_METHOD_ENTER(TRC_WSMSERVER, "WsmResponseEncoder::sendResponse");
 65               PEG_TRACE((TRC_WSMSERVER, Tracer::LEVEL3,
 66 kumpf 1.4         "WsmResponseEncoder::sendResponse()"));
 67 kumpf 1.2 
 68               if (!response)
 69               {
 70                   PEG_METHOD_EXIT();
 71                   return;
 72               }
 73           
 74               Uint32 queueId = response->getQueueId();
 75               Boolean httpCloseConnect = response->getHttpCloseConnect();
 76           
 77 marek 1.3     PEG_TRACE((TRC_WSMSERVER, Tracer::LEVEL4,
 78 kumpf 1.2         "WsmResponseEncoder::sendResponse()- "
 79                       "response->getHttpCloseConnect() returned %d",
 80                   httpCloseConnect));
 81           
 82               MessageQueue* queue = MessageQueue::lookup(queueId);
 83               if (!queue)
 84               {
 85 marek 1.3         PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL1,
 86 kumpf 1.2             "ERROR: non-existent queueId = %u, response not sent.", queueId));
 87                   PEG_METHOD_EXIT();
 88                   return;
 89               }
 90               PEGASUS_ASSERT(dynamic_cast<HTTPConnection*>(queue) != 0);
 91           
 92 kumpf 1.4     Buffer message = response->getResponseContent();
 93 kumpf 1.2 
 94               // Note: WS-Management responses are never sent in chunks, so there is no
 95               // need to check dynamic_cast<HTTPConnection*>(queue)->isChunkRequested().
 96               // HTTPMessage::isComplete() defaults to true, and we leave it that way.
 97           
 98               AutoPtr<HTTPMessage> httpMessage(new HTTPMessage(message));
 99           
100               httpMessage->setCloseConnect(httpCloseConnect);
101               queue->enqueue(httpMessage.release());
102           
103               PEG_METHOD_EXIT();
104           }
105           
106 kumpf 1.4 void WsmResponseEncoder::_sendUnreportableSuccess(WsmResponse* response)
107           {
108               // DSP0226 R6.2-2:  If the mustUnderstand attribute is set to
109               // "true", the service shall comply with the request.  If the
110               // response would exceed the maximum size, the service should
111               // return a wsman:EncodingLimit fault.  Because a service might
112               // execute the operation prior to knowing the response size, the
113               // service should undo any effects of the operation before
114               // issuing the fault.  If the operation cannot be reversed (such
115               // as a destructive wxf:Put or wxf:Delete, or a wxf:Create), the
116               // service shall indicate that the operation succeeded in the
117               // wsman:EncodingLimit fault with the following detail code:
118               //     http://schemas.dmtf.org/wbem/wsman/1/wsman/faultDetail/
119               //         UnreportableSuccess
120           
121               WsmFault fault(WsmFault::wsman_EncodingLimit,
122                   MessageLoaderParms(
123                       "WsmServer.WsmResponseEncoder.UNREPORTABLE_SUCCESS",
124                       "Success response could not be encoded within "
125                       "requested envelope size limits."),
126                   WSMAN_FAULTDETAIL_UNREPORTABLESUCCESS);
127 kumpf 1.4     WsmFaultResponse faultResponse(
128                   response->getRelatesTo(), 
129                   response->getQueueId(), 
130                   response->getHttpMethod(),
131                   response->getHttpCloseConnect(), 
132                   fault);
133           
134               SoapResponse soapResponse(&faultResponse);
135               _sendResponse(&soapResponse);
136           }
137           
138           void WsmResponseEncoder::_sendEncodingLimitFault(WsmResponse* response)
139           {
140               WsmFault fault(WsmFault::wsman_EncodingLimit,
141                   MessageLoaderParms(
142                       "WsmServer.WsmResponseEncoder.MAX_ENV_SIZE_EXCEEDED",
143                       "Response could not be encoded within requested "
144                       "envelope size limits."),
145                   WSMAN_FAULTDETAIL_MAXENVELOPESIZE);
146               WsmFaultResponse faultResponse(
147                   response->getRelatesTo(), 
148 kumpf 1.4         response->getQueueId(), 
149                   response->getHttpMethod(),
150                   response->getHttpCloseConnect(), 
151                   fault);
152           
153               SoapResponse soapResponse(&faultResponse);
154               _sendResponse(&soapResponse);
155           }
156           
157 kumpf 1.2 void WsmResponseEncoder::enqueue(WsmResponse* response)
158           {
159               PEG_METHOD_ENTER(TRC_WSMSERVER, "WsmResponseEncoder::enqueue()");
160               PEGASUS_ASSERT(response);
161           
162 marek 1.3     PEG_TRACE((TRC_WSMSERVER, Tracer::LEVEL4,
163 kumpf 1.2         "WsmResponseEncoder::enqueue()- "
164                       "response->getHttpCloseConnect() returned %d",
165                   response->getHttpCloseConnect()));
166           
167 kumpf 1.4     try 
168 kumpf 1.2     {
169 kumpf 1.4         switch (response->getType())
170                   {
171                       case WS_TRANSFER_GET:
172                           _encodeWxfGetResponse((WxfGetResponse*) response);
173                           break;
174           
175                       case WS_TRANSFER_PUT:
176                           _encodeWxfPutResponse((WxfPutResponse*) response);
177                           break;
178           
179                       case WS_TRANSFER_CREATE:
180                           _encodeWxfCreateResponse((WxfCreateResponse*) response);
181                           break;
182           
183                       case WS_TRANSFER_DELETE:
184                           _encodeWxfDeleteResponse((WxfDeleteResponse*) response);
185                           break;
186           
187                       case WS_ENUMERATION_ENUMERATE:
188                           _encodeWsenEnumerateResponse((WsenEnumerateResponse*) response);
189                           break;
190 kumpf 1.4 
191                       case WS_ENUMERATION_PULL:
192                           _encodeWsenPullResponse((WsenPullResponse*) response);
193                           break;
194           
195                       case WS_ENUMERATION_RELEASE:
196                           _encodeWsenReleaseResponse((WsenReleaseResponse*) response);
197                           break;
198           
199                       case WSM_FAULT:
200                           _encodeWsmFaultResponse((WsmFaultResponse*) response);
201                           break;
202           
203                       case SOAP_FAULT:
204                           _encodeSoapFaultResponse((SoapFaultResponse*) response);
205                           break;
206           
207                       default:
208                           // Unexpected message type
209                           PEGASUS_ASSERT(0);
210                           break;
211 kumpf 1.4         }
212               }
213               catch (PEGASUS_STD(bad_alloc)&)
214               {
215                   WsmFault fault(WsmFault::wsman_InternalError,
216                       MessageLoaderParms(
217                           "WsmServer.WsmResponseEncoder.OUT_OF_MEMORY",
218                           "A System error has occurred. Please retry the "
219                               "WS-Management operation at a later time."));
220                   WsmFaultResponse outofmem(
221                       response->getRelatesTo(), 
222                       response->getQueueId(), 
223                       response->getHttpMethod(),
224                       response->getHttpCloseConnect(), 
225                       fault);
226                   _encodeWsmFaultResponse(&outofmem);
227 kumpf 1.2     }
228           
229               PEG_METHOD_EXIT();
230           }
231           
232 kumpf 1.4 void WsmResponseEncoder::_encodeWxfGetResponse(WxfGetResponse* response)
233 kumpf 1.2 {
234 kumpf 1.4     SoapResponse soapResponse(response);
235 kumpf 1.2     Buffer body;
236               WsmWriter::appendInstanceElement(body, response->getInstance());
237 kumpf 1.4     if (soapResponse.appendBodyContent(body))
238               {
239                   _sendResponse(&soapResponse);
240               }
241               else
242               {
243                   _sendUnreportableSuccess(response);
244               }
245 kumpf 1.2 }
246           
247 kumpf 1.4 void WsmResponseEncoder::_encodeWxfPutResponse(WxfPutResponse* response)
248 kumpf 1.2 {
249 kumpf 1.4     SoapResponse soapResponse(response);
250 kumpf 1.2     Buffer headers;
251           
252               // DSP0226 R6.5-1:  A service receiving a message that contains the
253               // wsman:RequestEPR header block should return a response that contains
254               // a wsman:RequestedEPR header block.  This block contains the most recent
255               // EPR of the resource being accessed or a status code if the service
256               // cannot determine or return the EPR.  This EPR reflects any identity
257               // changes that may have occurred as a result of the current operation, as
258               // set forth in the following behavior.  The header block in the
259               // corresponding response message has the following format:
260               //     <wsman:RequestedEPR...>
261               //       [ <wsa:EndpointReference>
262               //          wsa:EndpointReferenceType
263               //       </wsa:EndpointReference> |
264               //       <wsman:EPRInvalid/> |
265               //       <wsman:EPRUnknown/> ]
266               //     </wsman:RequestedEPR>
267               if (response->getRequestedEPR())
268               {
269                   WsmWriter::appendStartTag(
270                       headers, WsmNamespaces::WS_MAN, STRLIT("RequestedEPR"));
271 kumpf 1.2         WsmWriter::appendStartTag(
272 kumpf 1.4             headers, 
273                       WsmNamespaces::WS_ADDRESSING, STRLIT("EndpointReference"));
274 kumpf 1.2         WsmWriter::appendEPRElement(headers, response->getEPR());
275                   WsmWriter::appendEndTag(
276 kumpf 1.4             headers, 
277                       WsmNamespaces::WS_ADDRESSING, STRLIT("EndpointReference"));
278 kumpf 1.2         WsmWriter::appendEndTag(
279                       headers, WsmNamespaces::WS_MAN, STRLIT("RequestedEPR"));
280               }
281 kumpf 1.4 
282               if (soapResponse.appendHeader(headers))
283               {
284                   _sendResponse(&soapResponse);
285               }
286               else
287               {
288                   _sendUnreportableSuccess(response);
289               }
290 kumpf 1.2 }
291           
292 kumpf 1.4 void WsmResponseEncoder::_encodeWxfCreateResponse(WxfCreateResponse* response)
293 kumpf 1.2 {
294 kumpf 1.4     SoapResponse soapResponse(response);
295 kumpf 1.2     Buffer body;
296 kumpf 1.4 
297 kumpf 1.2     WsmWriter::appendStartTag(
298                   body, WsmNamespaces::WS_TRANSFER, STRLIT("ResourceCreated"));
299               WsmWriter::appendEPRElement(body, response->getEPR());
300               WsmWriter::appendEndTag(
301                   body, WsmNamespaces::WS_TRANSFER, STRLIT("ResourceCreated"));
302 kumpf 1.4 
303               if (soapResponse.appendBodyContent(body))
304               {
305                   _sendResponse(&soapResponse);
306               }
307               else
308               {
309                   _sendUnreportableSuccess(response);
310               }
311           }
312           
313           void WsmResponseEncoder::_encodeWxfDeleteResponse(WxfDeleteResponse* response)
314           {
315               SoapResponse soapResponse(response);
316               _sendResponse(&soapResponse);
317           }
318           
319           void WsmResponseEncoder::_encodeWsenEnumerateResponse(
320               WsenEnumerateResponse* response)
321           {
322               SoapResponse soapResponse(response);
323 kumpf 1.4     Buffer headers;
324           
325               if (response->requestedItemCount())
326               {
327                   WsmWriter::appendStartTag(
328                       headers, WsmNamespaces::WS_MAN, STRLIT("TotalItemsCountEstimate"));
329                   WsmWriter::append(headers, response->getItemCount());
330                   WsmWriter::appendEndTag(
331                       headers, WsmNamespaces::WS_MAN, STRLIT("TotalItemsCountEstimate"));
332               }
333           
334               if (!_encodeEnumerationData(
335                       soapResponse, 
336                       headers, 
337                       WS_ENUMERATION_ENUMERATE,
338                       response->getEnumerationContext(),
339                       response->isComplete(),
340                       response->getEnumerationData()))
341               {
342                   _sendEncodingLimitFault(response);
343                   return;
344 kumpf 1.4     }
345           
346               _sendResponse(&soapResponse);
347           }
348           
349           void WsmResponseEncoder::_encodeWsenPullResponse(WsenPullResponse* response)
350           {
351               SoapResponse soapResponse(response);
352               Buffer headers;
353           
354               if (!_encodeEnumerationData(
355                       soapResponse, 
356                       headers, 
357                       WS_ENUMERATION_PULL,
358                       response->getEnumerationContext(),
359                       response->isComplete(),
360                       response->getEnumerationData()))
361               {
362                   _sendEncodingLimitFault(response);
363                   return;
364               }
365 kumpf 1.4 
366               _sendResponse(&soapResponse);
367           }
368           
369           Boolean WsmResponseEncoder::_encodeEnumerationData(
370               SoapResponse& soapResponse,
371               Buffer& headers,
372               WsmOperationType operation,
373               Uint64 contextId,
374               Boolean isComplete,
375               WsenEnumerationData& data)
376           {
377               Buffer bodyHeader, bodyTrailer;
378           
379               PEGASUS_ASSERT(operation == WS_ENUMERATION_ENUMERATE ||
380                   operation == WS_ENUMERATION_PULL);
381           
382               WsmWriter::appendStartTag(
383                   bodyHeader, WsmNamespaces::WS_ENUMERATION, 
384                   operation == WS_ENUMERATION_ENUMERATE ? 
385                       STRLIT("EnumerateResponse") : STRLIT("PullResponse"));
386 kumpf 1.4 
387               if (!isComplete)
388               {
389                   WsmWriter::appendStartTag(
390                       bodyHeader, WsmNamespaces::WS_ENUMERATION, 
391                       STRLIT("EnumerationContext"));
392                   WsmWriter::append(bodyHeader, contextId);
393                   WsmWriter::appendEndTag(
394                       bodyHeader, WsmNamespaces::WS_ENUMERATION, 
395                       STRLIT("EnumerationContext"));
396               }
397               else
398               {
399                   WsmWriter::appendEmptyTag(
400                       bodyHeader, WsmNamespaces::WS_ENUMERATION, 
401                       STRLIT("EnumerationContext"));
402               }
403           
404               if (data.getSize() > 0)
405               {
406                   WsmWriter::appendStartTag(
407 kumpf 1.4             bodyHeader, 
408                       operation == WS_ENUMERATION_ENUMERATE ? 
409                           WsmNamespaces::WS_MAN : WsmNamespaces::WS_ENUMERATION, 
410                       STRLIT("Items"));
411                   WsmWriter::appendEndTag(
412                       bodyTrailer, 
413                       operation == WS_ENUMERATION_ENUMERATE ? 
414                           WsmNamespaces::WS_MAN : WsmNamespaces::WS_ENUMERATION, 
415                       STRLIT("Items"));
416               }
417           
418               Uint32 eosPos = bodyTrailer.size();
419               Uint32 eosSize = 0;
420               if (isComplete)
421               {
422                   WsmWriter::appendEmptyTag(
423                       bodyTrailer, 
424                       operation == WS_ENUMERATION_ENUMERATE ? 
425                           WsmNamespaces::WS_MAN : WsmNamespaces::WS_ENUMERATION, 
426                       STRLIT("EndOfSequence"));
427                   eosSize = bodyTrailer.size() - eosPos;
428 kumpf 1.4     }
429           
430               WsmWriter::appendEndTag(
431                   bodyTrailer, WsmNamespaces::WS_ENUMERATION, 
432                   operation == WS_ENUMERATION_ENUMERATE ? 
433                       STRLIT("EnumerateResponse") : STRLIT("PullResponse"));
434           
435               // Fault the request if it can't be encoded within the limits
436               if (!soapResponse.appendHeader(headers) ||
437                   !soapResponse.appendBodyHeader(bodyHeader) ||
438                   !soapResponse.appendBodyTrailer(bodyTrailer))
439               {
440                   return false;
441               }
442           
443               // Now add the list of items
444               Uint32 i;
445           
446               if (data.enumerationMode == WSEN_EM_OBJECT)
447               {
448                   for (i = 0; i < data.instances.size(); i++)
449 kumpf 1.4         {
450                       Buffer body;
451           
452                       if (data.polymorphismMode == WSMB_PM_EXCLUDE_SUBCLASS_PROPERTIES)
453                       {
454                           // The response does not contain the subclass properties, but
455                           // the class name is still that of the subclass. 
456                           // Replace it here.
457                           data.instances[i].setClassName(
458                               WsmToCimRequestMapper::convertResourceUriToClassName(
459                                   data.classUri).getString());
460                       }
461           
462                       WsmWriter::appendInstanceElement(body, data.instances[i]);
463                       if (!soapResponse.appendBodyContent(body))
464                       {
465                           break;
466                       }
467                   }
468               }
469               else if (data.enumerationMode == WSEN_EM_EPR)
470 kumpf 1.4     {
471                   for (i = 0; i < data.eprs.size(); i++)
472                   {
473                       Buffer body;
474           
475                       WsmWriter::appendStartTag(
476                           body, 
477                           WsmNamespaces::WS_ADDRESSING, 
478                           STRLIT("EndpointReference"));
479                       WsmWriter::appendEPRElement(body, data.eprs[i]);
480                       WsmWriter::appendEndTag(
481                           body, 
482                           WsmNamespaces::WS_ADDRESSING, 
483                           STRLIT("EndpointReference"));
484                       if (!soapResponse.appendBodyContent(body))
485                       {
486                           break;
487                       }
488                   }
489               }
490               else if (data.enumerationMode == WSEN_EM_OBJECT_AND_EPR)
491 kumpf 1.4     {
492                   for (i = 0; i < data.instances.size(); i++)
493                   {
494                       Buffer body;
495           
496                       WsmWriter::appendStartTag(
497                           body, 
498                           WsmNamespaces::WS_MAN, 
499                           STRLIT("Item"));
500           
501                       if (data.polymorphismMode == WSMB_PM_EXCLUDE_SUBCLASS_PROPERTIES)
502                       {
503                           // The response does not contain the subclass properties, but
504                           // the class name is still that of the subclass. 
505                           // Replace it here.
506                           data.instances[i].setClassName(
507                               WsmToCimRequestMapper::convertResourceUriToClassName(
508                                   data.classUri).getString());
509                       }
510           
511                       WsmWriter::appendInstanceElement(body, data.instances[i]);
512 kumpf 1.4  
513                       WsmWriter::appendStartTag(
514                           body, 
515                           WsmNamespaces::WS_ADDRESSING, 
516                           STRLIT("EndpointReference"));
517                       WsmWriter::appendEPRElement(body, data.eprs[i]);
518                       WsmWriter::appendEndTag(
519                           body, 
520                           WsmNamespaces::WS_ADDRESSING, 
521                           STRLIT("EndpointReference"));
522           
523                       WsmWriter::appendEndTag(
524                           body, 
525                           WsmNamespaces::WS_MAN, 
526                           STRLIT("Item"));
527           
528                       if (!soapResponse.appendBodyContent(body))
529                       {
530                           break;
531                       }
532                   }
533 kumpf 1.4     }
534               else
535               {
536                   PEGASUS_ASSERT(0);
537               }
538           
539               // If the list is not empty, but none of the items have been successfully
540               // added to the soapResponse, fault the request because it cannot be
541               // encoded within the specified limits.
542               if (data.getSize() > 0 && i == 0)
543               {
544                   return false;
545               }
546           
547               // Remove the items we processed. The rest will be added back 
548               // to the context
549               if (i != 0)
550               {
551                   data.remove(0, i);
552               }
553           
554 kumpf 1.4     // The request is complete but could not be encoded with MaxEnvelopeSize.
555               // Clear EndOfSequence tag.
556               if (isComplete && data.getSize() > 0)
557               {
558                   soapResponse.getBodyTrailer().remove(eosPos, eosSize);
559               }
560           
561               return true;
562 kumpf 1.2 }
563           
564 kumpf 1.4 void WsmResponseEncoder::_encodeWsenReleaseResponse(
565               WsenReleaseResponse* response)
566 kumpf 1.2 {
567 kumpf 1.4     SoapResponse soapResponse(response);
568               _sendResponse(&soapResponse);
569 kumpf 1.2 }
570           
571           void WsmResponseEncoder::_encodeWsmFaultResponse(WsmFaultResponse* response)
572           {
573 kumpf 1.4     SoapResponse soapResponse(response);
574               _sendResponse(&soapResponse);
575 kumpf 1.2 }
576           
577           void WsmResponseEncoder::_encodeSoapFaultResponse(SoapFaultResponse* response)
578           {
579 kumpf 1.4     SoapResponse soapResponse(response);
580               _sendResponse(&soapResponse);
581 kumpf 1.2 }
582           
583           PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2