(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           
 48           PEGASUS_USING_STD;
 49           
 50           PEGASUS_NAMESPACE_BEGIN
 51           
 52           WsmResponseEncoder::WsmResponseEncoder()
 53           {
 54           }
 55           
 56           WsmResponseEncoder::~WsmResponseEncoder()
 57           {
 58           }
 59           
 60           void WsmResponseEncoder::sendResponse(
 61               WsmResponse* response,
 62               const String& action,
 63               Buffer* bodygiven,
 64 kumpf 1.2     Buffer* extraHeaders)
 65           {
 66               PEG_METHOD_ENTER(TRC_WSMSERVER, "WsmResponseEncoder::sendResponse");
 67               PEG_TRACE((TRC_WSMSERVER, Tracer::LEVEL3,
 68                   "WsmResponseEncoder::sendResponse(): action = %s",
 69                   (const char*)action.getCString()));
 70           
 71               if (!response)
 72               {
 73                   PEG_METHOD_EXIT();
 74                   return;
 75               }
 76           
 77               Uint32 queueId = response->getQueueId();
 78               Boolean httpCloseConnect = response->getHttpCloseConnect();
 79           
 80               PEG_TRACE((TRC_WSMSERVER, Tracer::LEVEL3,
 81                   "WsmResponseEncoder::sendResponse()- "
 82                       "response->getHttpCloseConnect() returned %d",
 83                   httpCloseConnect));
 84           
 85 kumpf 1.2     MessageQueue* queue = MessageQueue::lookup(queueId);
 86               if (!queue)
 87               {
 88                   PEG_TRACE((TRC_DISCARDED_DATA, Tracer::LEVEL2,
 89                       "ERROR: non-existent queueId = %u, response not sent.", queueId));
 90                   PEG_METHOD_EXIT();
 91                   return;
 92               }
 93               PEGASUS_ASSERT(dynamic_cast<HTTPConnection*>(queue) != 0);
 94           
 95               HttpMethod httpMethod = response->getHttpMethod();
 96               String messageId = response->getMessageId();
 97               String relatesTo = response->getRelatesTo();
 98               Buffer message;
 99           
100               // Note: the language is ALWAYS passed empty to the xml formatters because
101               // it is HTTPConnection that needs to make the decision of whether to add
102               // the languages to the HTTP message.
103               ContentLanguageList contentLanguage;
104           
105               Uint32 httpHeaderSize = 0;
106 kumpf 1.2     Buffer bodylocal, headerslocal;
107               Buffer& body = bodygiven ? *bodygiven : bodylocal;
108               Buffer& headers = extraHeaders ? *extraHeaders : headerslocal;
109           
110               if (response->getType() == SOAP_FAULT)
111               {
112                   message = WsmWriter::formatSoapFault(
113                       ((SoapFaultResponse*) response)->getFault(),
114                       messageId,
115                       relatesTo,
116                       httpMethod,
117                       httpHeaderSize);
118               }
119               else if (response->getType() == WSM_FAULT)
120               {
121                   message = WsmWriter::formatWsmFault(
122                       ((WsmFaultResponse*) response)->getFault(),
123                       messageId,
124                       relatesTo,
125                       httpMethod,
126                       httpHeaderSize);
127 kumpf 1.2     }
128               else
129               {
130                   // else non-error condition
131                   try
132                   {
133                       message = WsmWriter::formatWsmRspMessage(
134                           action,
135                           messageId,
136                           relatesTo,
137                           httpMethod,
138                           contentLanguage,
139                           body,
140                           headers,
141                           httpHeaderSize);
142                   }
143                   catch (PEGASUS_STD(bad_alloc)&)
144                   {
145                       WsmFault fault(WsmFault::wsman_InternalError,
146                           MessageLoaderParms(
147                               "WsmServer.WsmResponseEncoder.OUT_OF_MEMORY",
148 kumpf 1.2                     "A System error has occurred. Please retry the "
149                                   "WS-Management operation at a later time."));
150                       WsmFaultResponse outofmem(relatesTo, queueId, httpMethod,
151                           httpCloseConnect, fault);
152           
153                       // try again with new error and no body
154                       body.clear();
155                       sendResponse(&outofmem);
156                       PEG_METHOD_EXIT();
157                       return;
158                   }
159               }
160           
161               // If MaxEnvelopeSize is not set, it's never been specified 
162               // in the request
163               if (response->getMaxEnvelopeSize() &&
164                   message.size() - httpHeaderSize > response->getMaxEnvelopeSize())
165               {
166                   // try again with new error and no body
167                   body.clear();
168           
169 kumpf 1.2         if (response->getType() == WSM_FAULT ||
170                       response->getType() == SOAP_FAULT)
171                   {
172                       WsmFault fault(WsmFault::wsman_EncodingLimit,
173                           MessageLoaderParms(
174                               "WsmServer.WsmResponseEncoder.FAULT_MAX_ENV_SIZE_EXCEEDED",
175                               "Fault response could not be encoded within requested "
176                               "envelope size limits."),
177                           WSMAN_FAULTDETAIL_MAXENVELOPESIZE);
178                       WsmFaultResponse faultResponse(relatesTo, queueId, httpMethod,
179                           httpCloseConnect, fault);
180           
181                       sendResponse(&faultResponse);
182                   }
183                   else
184                   {
185                       // DSP0226 R6.2-2:  If the mustUnderstand attribute is set to
186                       // "true", the service shall comply with the request.  If the
187                       // response would exceed the maximum size, the service should
188                       // return a wsman:EncodingLimit fault.  Because a service might
189                       // execute the operation prior to knowing the response size, the
190 kumpf 1.2             // service should undo any effects of the operation before
191                       // issuing the fault.  If the operation cannot be reversed (such
192                       // as a destructive wxf:Put or wxf:Delete, or a wxf:Create), the
193                       // service shall indicate that the operation succeeded in the
194                       // wsman:EncodingLimit fault with the following detail code:
195                       //     http://schemas.dmtf.org/wbem/wsman/1/wsman/faultDetail/
196                       //         UnreportableSuccess
197           
198                       WsmFault fault(WsmFault::wsman_EncodingLimit,
199                           MessageLoaderParms(
200                               "WsmServer.WsmResponseEncoder.UNREPORTABLE_SUCCESS",
201                               "Success response could not be encoded within "
202                               "requested envelope size limits."),
203                           WSMAN_FAULTDETAIL_UNREPORTABLESUCCESS);
204                       WsmFaultResponse faultResponse(relatesTo, queueId, httpMethod,
205                           httpCloseConnect, fault);
206           
207                       sendResponse(&faultResponse);
208                   }
209           
210                   PEG_METHOD_EXIT();
211 kumpf 1.2         return;
212               }
213           
214               // Note: WS-Management responses are never sent in chunks, so there is no
215               // need to check dynamic_cast<HTTPConnection*>(queue)->isChunkRequested().
216               // HTTPMessage::isComplete() defaults to true, and we leave it that way.
217           
218               AutoPtr<HTTPMessage> httpMessage(new HTTPMessage(message));
219           
220               if (response->getType() == SOAP_FAULT)
221               {
222                   httpMessage->contentLanguages =
223                       ((SoapFaultResponse*) response)->getFault().getMessageLanguage();
224               }
225               else if (response->getType() == WSM_FAULT)
226               {
227                   httpMessage->contentLanguages =
228                       ((WsmFaultResponse*) response)->getFault().getReasonLanguage();
229               }
230               else
231               {
232 kumpf 1.2         httpMessage->contentLanguages = response->getContentLanguages();
233               }
234           
235               httpMessage->setCloseConnect(httpCloseConnect);
236               queue->enqueue(httpMessage.release());
237           
238               PEG_METHOD_EXIT();
239           }
240           
241           void WsmResponseEncoder::enqueue(WsmResponse* response)
242           {
243               PEG_METHOD_ENTER(TRC_WSMSERVER, "WsmResponseEncoder::enqueue()");
244               PEGASUS_ASSERT(response);
245           
246               PEG_TRACE((TRC_WSMSERVER, Tracer::LEVEL3,
247                   "WsmResponseEncoder::enqueue()- "
248                       "response->getHttpCloseConnect() returned %d",
249                   response->getHttpCloseConnect()));
250           
251               switch (response->getType())
252               {
253 kumpf 1.2         case WS_TRANSFER_GET:
254                       _encodeGetResponse((WsmGetResponse*) response);
255                       break;
256           
257                   case WS_TRANSFER_PUT:
258                       _encodePutResponse((WsmPutResponse*) response);
259                       break;
260           
261                   case WS_TRANSFER_CREATE:
262                       _encodeCreateResponse((WsmCreateResponse*) response);
263                       break;
264           
265                   case WS_TRANSFER_DELETE:
266                       _encodeDeleteResponse((WsmDeleteResponse*) response);
267                       break;
268           
269                   case WSM_FAULT:
270                       _encodeWsmFaultResponse((WsmFaultResponse*) response);
271                       break;
272           
273                   case SOAP_FAULT:
274 kumpf 1.2             _encodeSoapFaultResponse((SoapFaultResponse*) response);
275                       break;
276           
277                   default:
278                       // Unexpected message type
279                       PEGASUS_ASSERT(0);
280                       break;
281               }
282           
283               PEG_METHOD_EXIT();
284           }
285           
286           void WsmResponseEncoder::_encodeGetResponse(WsmGetResponse* response)
287           {
288               Buffer body;
289               WsmWriter::appendInstanceElement(body, response->getInstance());
290               sendResponse(response, WSM_ACTION_GET_RESPONSE, &body);
291           }
292           
293           void WsmResponseEncoder::_encodePutResponse(WsmPutResponse* response)
294           {
295 kumpf 1.2     Buffer body;
296               Buffer headers;
297           
298               // DSP0226 R6.5-1:  A service receiving a message that contains the
299               // wsman:RequestEPR header block should return a response that contains
300               // a wsman:RequestedEPR header block.  This block contains the most recent
301               // EPR of the resource being accessed or a status code if the service
302               // cannot determine or return the EPR.  This EPR reflects any identity
303               // changes that may have occurred as a result of the current operation, as
304               // set forth in the following behavior.  The header block in the
305               // corresponding response message has the following format:
306               //     <wsman:RequestedEPR...>
307               //       [ <wsa:EndpointReference>
308               //          wsa:EndpointReferenceType
309               //       </wsa:EndpointReference> |
310               //       <wsman:EPRInvalid/> |
311               //       <wsman:EPRUnknown/> ]
312               //     </wsman:RequestedEPR>
313               if (response->getRequestedEPR())
314               {
315                   WsmWriter::appendStartTag(
316 kumpf 1.2             headers, WsmNamespaces::WS_MAN, STRLIT("RequestedEPR"));
317                   WsmWriter::appendStartTag(
318                       headers, WsmNamespaces::WS_ADDRESSING, STRLIT("EndpointReference"));
319                   WsmWriter::appendEPRElement(headers, response->getEPR());
320                   WsmWriter::appendEndTag(
321                       headers, WsmNamespaces::WS_ADDRESSING, STRLIT("EndpointReference"));
322                   WsmWriter::appendEndTag(
323                       headers, WsmNamespaces::WS_MAN, STRLIT("RequestedEPR"));
324               }
325               sendResponse(response, WSM_ACTION_PUT_RESPONSE, &body, &headers);
326           }
327           
328           void WsmResponseEncoder::_encodeCreateResponse(WsmCreateResponse* response)
329           {
330               Buffer body;
331               WsmWriter::appendStartTag(
332                   body, WsmNamespaces::WS_TRANSFER, STRLIT("ResourceCreated"));
333               WsmWriter::appendEPRElement(body, response->getEPR());
334               WsmWriter::appendEndTag(
335                   body, WsmNamespaces::WS_TRANSFER, STRLIT("ResourceCreated"));
336               sendResponse(response, WSM_ACTION_CREATE_RESPONSE, &body);
337 kumpf 1.2 }
338           
339           void WsmResponseEncoder::_encodeDeleteResponse(WsmDeleteResponse* response)
340           {
341               sendResponse(response, WSM_ACTION_DELETE_RESPONSE);
342           }
343           
344           void WsmResponseEncoder::_encodeWsmFaultResponse(WsmFaultResponse* response)
345           {
346               sendResponse(response);
347           }
348           
349           void WsmResponseEncoder::_encodeSoapFaultResponse(SoapFaultResponse* response)
350           {
351               sendResponse(response);
352           }
353           
354           PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2