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

  1 martin 1.5 //%LICENSE////////////////////////////////////////////////////////////////
  2 martin 1.6 //
  3 martin 1.5 // Licensed to The Open Group (TOG) under one or more contributor license
  4            // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
  5            // this work for additional information regarding copyright ownership.
  6            // Each contributor licenses this file to you under the OpenPegasus Open
  7            // Source License; you may not use this file except in compliance with the
  8            // License.
  9 martin 1.6 //
 10 martin 1.5 // Permission is hereby granted, free of charge, to any person obtaining a
 11            // copy of this software and associated documentation files (the "Software"),
 12            // to deal in the Software without restriction, including without limitation
 13            // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 14            // and/or sell copies of the Software, and to permit persons to whom the
 15            // Software is furnished to do so, subject to the following conditions:
 16 martin 1.6 //
 17 martin 1.5 // The above copyright notice and this permission notice shall be included
 18            // in all copies or substantial portions of the Software.
 19 martin 1.6 //
 20 martin 1.5 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 21 martin 1.6 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 22 martin 1.5 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 23            // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 24            // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 25            // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 26            // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 27 martin 1.6 //
 28 martin 1.5 //////////////////////////////////////////////////////////////////////////
 29 kumpf  1.2 //
 30            //%////////////////////////////////////////////////////////////////////////////
 31            
 32            #include <cctype>
 33            #include <cstdio>
 34            #include <Pegasus/Common/Config.h>
 35            #include <Pegasus/Common/Tracer.h>
 36            #include <Pegasus/Common/MessageLoader.h>
 37 kumpf  1.3 #include <Pegasus/Common/StringConversion.h>
 38 kumpf  1.2 #include <Pegasus/Common/AutoPtr.h>
 39            #include "WsmConstants.h"
 40 kumpf  1.8 #include "SoapResponse.h"
 41 kumpf  1.2 #include "WsmProcessor.h"
 42            
 43 kumpf  1.3 PEGASUS_USING_STD;
 44            
 45 kumpf  1.2 PEGASUS_NAMESPACE_BEGIN
 46            
 47 kumpf  1.3 Uint64 WsmProcessor::_currentEnumContext = 0;
 48            
 49 kumpf  1.2 WsmProcessor::WsmProcessor(
 50 sahana.prabhakar 1.11     MessageQueue* cimOperationProcessorQueue,
 51 kumpf            1.2      CIMRepository* repository)
 52 sahana.prabhakar 1.11     : MessageQueue(PEGASUS_QUEUENAME_WSMPROCESSOR),
 53 kumpf            1.2        _wsmResponseEncoder(),
 54                             _wsmRequestDecoder(this),
 55                             _cimOperationProcessorQueue(cimOperationProcessorQueue),
 56                             _repository(repository),
 57                             _wsmToCimRequestMapper(repository)
 58                       {
 59                       }
 60                       
 61                       WsmProcessor::~WsmProcessor()
 62                       {
 63 kumpf            1.4      // Clean up enumeration responses that have not been pulled or released.
 64                           for (EnumerationContextTable::Iterator i =
 65                                    _enumerationContextTable.start(); i; i++)
 66                           {
 67                               delete i.value().response;
 68                           }
 69 kumpf            1.2  }
 70                       
 71                       void WsmProcessor::handleEnqueue(Message* message)
 72                       {
 73                           if (!message)
 74                           {
 75                               return;
 76                           }
 77                       
 78                           PEGASUS_ASSERT(dynamic_cast<CIMResponseMessage*>(message) != 0);
 79                           handleResponse(dynamic_cast<CIMResponseMessage*>(message));
 80                       }
 81                       
 82                       void WsmProcessor::handleEnqueue()
 83                       {
 84                           Message* message = dequeue();
 85                           handleEnqueue(message);
 86                       }
 87                       
 88                       void WsmProcessor::handleRequest(WsmRequest* wsmRequest)
 89                       {
 90 kumpf            1.2      PEG_METHOD_ENTER(TRC_WSMSERVER, "WsmProcessor::handleRequest()");
 91                       
 92                           // Process requests by type.  For now, only WS-Transfer operations are
 93                           // implemented, and they all are handled by forwarding to the CIM Server.
 94                       
 95                           AutoPtr<WsmRequest> wsmRequestDestroyer(wsmRequest);
 96                       
 97                           try
 98                           {
 99                               CIMOperationRequestMessage* cimRequest =
100                                   _wsmToCimRequestMapper.mapToCimRequest(wsmRequest);
101                       
102 kumpf            1.3          // Requests that do not have a CIM representation are mapped to NULL
103                               // and are meant to be handled by the WSM processor itself.
104                               if (cimRequest)
105                               {
106                                   // Save the request until the response comes back.
107                                   // Note that the CIM request has its own unique message ID.
108                                   _requestTable.insert(cimRequest->messageId, wsmRequest);
109                       
110                                   cimRequest->queueIds.push(getQueueId());
111                                   _cimOperationProcessorQueue->enqueue(cimRequest);
112 kumpf            1.4  
113                                   wsmRequestDestroyer.release();
114 kumpf            1.3          }
115                               else
116                               {
117                                   switch (wsmRequest->getType())
118                                   {
119                                       case WS_ENUMERATION_PULL:
120                                           _handlePullRequest((WsenPullRequest*) wsmRequest);
121                                           break;
122                       
123                                       case WS_ENUMERATION_RELEASE:
124                                           _handleReleaseRequest((WsenReleaseRequest*) wsmRequest);
125                                           break;
126                       
127                                       default:
128                                           break;
129                                   }
130                               }
131 kumpf            1.2      }
132                           catch (WsmFault& fault)
133                           {
134                               sendResponse(new WsmFaultResponse(wsmRequest, fault));
135                           }
136                           catch (CIMException& e)
137                           {
138                               sendResponse(new WsmFaultResponse(
139                                   wsmRequest,
140                                   _cimToWsmResponseMapper.mapCimExceptionToWsmFault(e)));
141                           }
142                           catch (Exception& e)
143                           {
144                               sendResponse(new WsmFaultResponse(
145                                   wsmRequest,
146                                   WsmFault(
147                                       WsmFault::wsman_InternalError,
148                                       e.getMessage(),
149                                       e.getContentLanguages())));
150                           }
151                           catch (PEGASUS_STD(exception)& e)
152 kumpf            1.2      {
153                               sendResponse(new WsmFaultResponse(
154                                   wsmRequest,
155                                   WsmFault(WsmFault::wsman_InternalError, e.what())));
156                           }
157                           catch (...)
158                           {
159                               sendResponse(new WsmFaultResponse(
160                                   wsmRequest,
161                                   WsmFault(WsmFault::wsman_InternalError)));
162                           }
163                       
164                           // Note this requirement when Enumerate/Pull operations are supported:
165                           // DSP0226 R6.3-5: For operations that span multiple message sequences,
166                           // the wsman:Locale element is processed in the initial message only.
167                           // It should be ignored in subsequent messages because the first
168                           // message establishes the required locale. The service may issue a
169                           // fault if the wsman:Locale is present in subsequent messages and the
170                           // value is different from that used in the initiating request.
171                       
172                           PEG_METHOD_EXIT();
173 kumpf            1.2  }
174                       
175                       void WsmProcessor::handleResponse(CIMResponseMessage* cimResponse)
176                       {
177                           PEG_METHOD_ENTER(TRC_WSMSERVER, "WsmProcessor::handleResponse()");
178                       
179                           AutoPtr<CIMResponseMessage> cimResponseDestroyer(cimResponse);
180                       
181                           // Lookup the request this response corresponds to
182                           WsmRequest* wsmRequest;
183                           Boolean gotRequest =
184                               _requestTable.lookup(cimResponse->messageId, wsmRequest);
185                           PEGASUS_ASSERT(gotRequest);
186                           AutoPtr<WsmRequest> wsmRequestDestroyer(wsmRequest);
187 kumpf            1.3      _requestTable.remove(cimResponse->messageId);
188 kumpf            1.2  
189                           try
190                           {
191 kumpf            1.3          switch (wsmRequest->getType())
192                               {
193                                   case WS_ENUMERATION_ENUMERATE:
194                                       _handleEnumerateResponse(
195                                           cimResponse,
196                                           (WsenEnumerateRequest*) wsmRequest);
197                                       break;
198                       
199                                   default:
200                                       _handleDefaultResponse(cimResponse, wsmRequest);
201                                       break;
202                               }
203 kumpf            1.2      }
204                           catch (WsmFault& fault)
205                           {
206                               sendResponse(new WsmFaultResponse(wsmRequest, fault));
207                           }
208                           catch (CIMException& e)
209                           {
210                               sendResponse(new WsmFaultResponse(
211                                   wsmRequest,
212                                   _cimToWsmResponseMapper.mapCimExceptionToWsmFault(e)));
213                           }
214                           catch (Exception& e)
215                           {
216                               sendResponse(new WsmFaultResponse(
217                                   wsmRequest,
218                                   WsmFault(
219                                       WsmFault::wsman_InternalError,
220                                       e.getMessage(),
221                                       e.getContentLanguages())));
222                           }
223                           catch (PEGASUS_STD(exception)& e)
224 kumpf            1.2      {
225                               sendResponse(new WsmFaultResponse(
226                                   wsmRequest,
227                                   WsmFault(WsmFault::wsman_InternalError, e.what())));
228                           }
229                           catch (...)
230                           {
231                               sendResponse(new WsmFaultResponse(
232                                   wsmRequest,
233                                   WsmFault(WsmFault::wsman_InternalError)));
234                           }
235                       
236                           PEG_METHOD_EXIT();
237                       }
238                       
239                       void WsmProcessor::sendResponse(WsmResponse* wsmResponse)
240                       {
241                           PEG_METHOD_ENTER(TRC_WSMSERVER, "WsmProcessor::sendResponse()");
242                       
243                           _wsmResponseEncoder.enqueue(wsmResponse);
244                           delete wsmResponse;
245 kumpf            1.2  
246                           PEG_METHOD_EXIT();
247                       }
248                       
249                       Uint32 WsmProcessor::getWsmRequestDecoderQueueId()
250                       {
251                           return _wsmRequestDecoder.getQueueId();
252                       }
253                       
254 kumpf            1.3  void WsmProcessor::_handleEnumerateResponse(
255                           CIMResponseMessage* cimResponse,
256                           WsenEnumerateRequest* wsmRequest)
257                       {
258                           if (cimResponse->cimException.getCode() != CIM_ERR_SUCCESS)
259                           {
260                               _handleDefaultResponse(cimResponse, wsmRequest);
261 kumpf            1.8          return;
262 kumpf            1.3      }
263 kumpf            1.8  
264                           AutoPtr<SoapResponse> soapResponse;
265                       
266 kumpf            1.3      {
267                               AutoMutex lock(_enumerationContextTableLock);
268                       
269                               AutoPtr<WsenEnumerateResponse> wsmResponse(
270                                   (WsenEnumerateResponse*) _cimToWsmResponseMapper.
271                                       mapToWsmResponse(wsmRequest, cimResponse));
272                       
273                               // Get the enumeration expiration time
274                               CIMDateTime expiration;
275                               _getExpirationDatetime(wsmRequest->expiration, expiration);
276                       
277                               // Create a new context
278                               Uint64 contextId = _currentEnumContext++;
279                               _enumerationContextTable.insert(
280                                   contextId,
281                                   EnumerationContext(
282                                       contextId,
283 kumpf            1.10                 wsmRequest->userName,
284 kumpf            1.3                  wsmRequest->enumerationMode,
285 kumpf            1.7                  expiration,
286 kumpf            1.3                  wsmRequest->epr,
287                                       wsmResponse.get()));
288                               wsmResponse->setEnumerationContext(contextId);
289                       
290                               // Get the requsted chunk of results
291                               AutoPtr<WsenEnumerateResponse> splitResponse(
292 kumpf            1.7              _splitEnumerateResponse(wsmRequest, wsmResponse.get(),
293 kumpf            1.3                  wsmRequest->optimized ? wsmRequest->maxElements : 0));
294                               splitResponse->setEnumerationContext(contextId);
295                       
296 kumpf            1.8          // If no items are left in the original response, mark split
297 kumpf            1.3          // response as complete
298                               if (wsmResponse->getSize() == 0)
299                               {
300                                   splitResponse->setComplete();
301                               }
302                       
303 kumpf            1.8          Uint32 numDataItemsEncoded = 0;
304                               soapResponse.reset(_wsmResponseEncoder.encodeWsenEnumerateResponse(
305                                   splitResponse.get(), numDataItemsEncoded));
306                       
307                               if (splitResponse->getSize() > numDataItemsEncoded)
308 kumpf            1.3          {
309                                   // Add unprocessed items back to the context
310 kumpf            1.9              splitResponse->remove(0, numDataItemsEncoded);
311 kumpf            1.3              wsmResponse->merge(splitResponse.get());
312                               }
313                       
314                               // Remove the context if there are no instances left
315                               if (wsmResponse->getSize() == 0)
316                               {
317                                   _enumerationContextTable.remove(contextId);
318                               }
319                               else
320                               {
321                                   // If the context is not removed, the pointer to the response is
322                                   // now owned by the context
323                                   wsmResponse.release();
324                               }
325                           }
326 kumpf            1.8  
327                           _wsmResponseEncoder.sendResponse(soapResponse.get());
328 kumpf            1.3  }
329                       
330                       void WsmProcessor::_handlePullRequest(WsenPullRequest* wsmRequest)
331                       {
332 kumpf            1.8      AutoPtr<SoapResponse> soapResponse;
333 kumpf            1.3  
334                           {
335 kumpf            1.8          AutoMutex lock(_enumerationContextTableLock);
336                               EnumerationContext* enumContext;
337                       
338                               if (_enumerationContextTable.lookupReference(
339                                       wsmRequest->enumerationContext, enumContext))
340 kumpf            1.3          {
341 kumpf            1.8              // EPRs of the request and the enumeration context must match
342                                   if (wsmRequest->epr != enumContext->epr)
343                                   {
344                                       throw WsmFault(
345                                           WsmFault::wsa_MessageInformationHeaderRequired,
346                                           MessageLoaderParms(
347                                               "WsmServer.WsmProcessor.INVALID_PULL_EPR",
348                                               "EPR of a Pull request does not match that of "
349                                               "the enumeration context."));
350                                   }
351                       
352 kumpf            1.10             // User credentials of the request and the enumeration context must
353                                   // match.
354                                   if (wsmRequest->userName != enumContext->userName)
355                                   {
356                                       // DSP0226 R8.1-6:  The wsen:Pull and wsen:Release operations
357                                       // are a continuation of the original wsen:Enumerate operation.
358                                       // The service should enforce the same authentication and
359                                       // authorization throughout the entire sequence of operations
360                                       // and should fault any attempt to change credentials during
361                                       // the sequence.
362                       
363                                       throw WsmFault(WsmFault::wsman_AccessDenied);
364                                   }
365                       
366 kumpf            1.8              AutoPtr<WsenPullResponse> wsmResponse(_splitPullResponse(
367                                       wsmRequest, enumContext->response, wsmRequest->maxElements));
368                                   wsmResponse->setEnumerationContext(enumContext->contextId);
369                                   if (enumContext->response->getSize() == 0)
370                                   {
371                                       wsmResponse->setComplete();
372                                   }
373                       
374                                   Uint32 numDataItemsEncoded = 0;
375                                   soapResponse.reset(_wsmResponseEncoder.encodeWsenPullResponse(
376                                       wsmResponse.get(), numDataItemsEncoded));
377 kumpf            1.3  
378 kumpf            1.8              if (wsmResponse->getSize() > numDataItemsEncoded)
379                                   {
380                                       // Add unprocessed items back to the context
381 kumpf            1.9                  wsmResponse->remove(0, numDataItemsEncoded);
382 kumpf            1.8                  enumContext->response->merge(wsmResponse.get());
383                                   }
384 kumpf            1.3  
385 kumpf            1.8              // Remove the context if there are no instances left
386                                   if (enumContext->response->getSize() == 0)
387                                   {
388                                       delete enumContext->response;
389                                       _enumerationContextTable.remove(wsmRequest->enumerationContext);
390                                   }
391 kumpf            1.3          }
392 kumpf            1.8          else
393 kumpf            1.3          {
394 kumpf            1.8              throw WsmFault(
395                                       WsmFault::wsen_InvalidEnumerationContext,
396                                       MessageLoaderParms(
397                                           "WsmServer.WsmProcessor.INVALID_ENUMERATION_CONTEXT",
398                                           "Enumeration context \"$0\" is not valid.",
399                                           wsmRequest->enumerationContext));
400 kumpf            1.3          }
401                           }
402 kumpf            1.8  
403                           _wsmResponseEncoder.sendResponse(soapResponse.get());
404 kumpf            1.3  }
405                       
406                       void WsmProcessor::_handleReleaseRequest(WsenReleaseRequest* wsmRequest)
407                       {
408 kumpf            1.8      AutoPtr<WsenReleaseResponse> wsmResponse;
409                       
410 kumpf            1.3      {
411 kumpf            1.8          AutoMutex lock(_enumerationContextTableLock);
412                       
413                               EnumerationContext enumContext;
414                               if (_enumerationContextTable.lookup(
415                                       wsmRequest->enumerationContext, enumContext))
416                               {
417                                   // EPRs of the request and the enumeration context must match
418                                   if (wsmRequest->epr != enumContext.epr)
419                                   {
420                                       throw WsmFault(
421                                           WsmFault::wsa_MessageInformationHeaderRequired,
422                                           MessageLoaderParms(
423                                               "WsmServer.WsmProcessor.INVALID_RELEASE_EPR",
424                                               "EPR of a Release request does not match that of "
425                                               "the enumeration context."));
426                                   }
427                       
428 kumpf            1.10             // User credentials of the request and the enumeration context must
429                                   // match.
430                                   if (wsmRequest->userName != enumContext.userName)
431                                   {
432                                       // DSP0226 R8.1-6:  The wsen:Pull and wsen:Release operations
433                                       // are a continuation of the original wsen:Enumerate operation.
434                                       // The service should enforce the same authentication and
435                                       // authorization throughout the entire sequence of operations
436                                       // and should fault any attempt to change credentials during
437                                       // the sequence.
438                       
439                                       throw WsmFault(WsmFault::wsman_AccessDenied);
440                                   }
441                       
442 kumpf            1.8              wsmResponse.reset(new WsenReleaseResponse(
443                                       wsmRequest, enumContext.response->getContentLanguages()));
444                       
445                                   delete enumContext.response;
446                                   _enumerationContextTable.remove(wsmRequest->enumerationContext);
447                               }
448                               else
449 kumpf            1.3          {
450                                   throw WsmFault(
451 kumpf            1.8                  WsmFault::wsen_InvalidEnumerationContext,
452 kumpf            1.3                  MessageLoaderParms(
453 kumpf            1.8                      "WsmServer.WsmProcessor.INVALID_ENUMERATION_CONTEXT",
454                                           "Enumeration context \"$0\" is not valid.",
455                                           wsmRequest->enumerationContext));
456 kumpf            1.3          }
457 kumpf            1.8      }
458 kumpf            1.3  
459 kumpf            1.8      _wsmResponseEncoder.enqueue(wsmResponse.get());
460 kumpf            1.3  }
461                       
462                       void WsmProcessor::_handleDefaultResponse(
463                           CIMResponseMessage* cimResponse, WsmRequest* wsmRequest)
464                       {
465                           AutoPtr<WsmResponse> wsmResponse(
466                               _cimToWsmResponseMapper.mapToWsmResponse(wsmRequest, cimResponse));
467                       
468                           cimResponse->updateThreadLanguages();
469                           cimResponse->queueIds.pop();
470                       
471                           _wsmResponseEncoder.enqueue(wsmResponse.get());
472                       }
473                       
474                       WsenEnumerateResponse* WsmProcessor::_splitEnumerateResponse(
475                           WsenEnumerateRequest* request, WsenEnumerateResponse* response, Uint32 num)
476                       {
477                           WsenEnumerationData splitData;
478                           response->getEnumerationData().split(splitData, num);
479                       
480                           return new WsenEnumerateResponse(splitData, response->getItemCount(),
481 kumpf            1.3          request, response->getContentLanguages());
482                       }
483                       
484                       WsenPullResponse* WsmProcessor::_splitPullResponse(
485                           WsenPullRequest* request, WsenEnumerateResponse* response, Uint32 num)
486                       {
487                           WsenEnumerationData splitData;
488                           response->getEnumerationData().split(splitData, num);
489                       
490 kumpf            1.7      return new WsenPullResponse(splitData, request,
491 kumpf            1.3          response->getContentLanguages());
492                       }
493                       
494                       void WsmProcessor::_getExpirationDatetime(
495                           const String& wsmDT, CIMDateTime& cimDT)
496                       {
497                           CIMDateTime dt, currentDT;
498                       
499 kumpf            1.7      // Default expiration interval = 10 mins
500 kumpf            1.3      // ATTN WSMAN: what should the value be?
501                           CIMDateTime maxInterval(0, 0, 10, 0, 0, 6);
502                       
503                           // If expiration is not set, use the dafault.
504                           if (wsmDT == String::EMPTY)
505                           {
506                               dt = maxInterval;
507                           }
508                           else
509                           {
510                               try
511                               {
512                                   WsmToCimRequestMapper::convertWsmToCimDatetime(wsmDT, dt);
513                               }
514                               catch (...)
515                               {
516                                   throw WsmFault(
517                                       WsmFault::wsen_InvalidExpirationTime,
518                                   MessageLoaderParms(
519                                       "WsmServer.WsmToCimRequestMapper.INVALID_EXPIRATION_TIME",
520                                       "The expiration time \"$0\" is not valid", wsmDT));
521 kumpf            1.3          }
522                           }
523                       
524                           currentDT = CIMDateTime::getCurrentDateTime();
525                           if (dt.isInterval())
526                           {
527                               if (dt > maxInterval)
528                               {
529                                   dt = maxInterval;
530                               }
531                               cimDT = currentDT + dt;
532                           }
533                           else
534                           {
535                               if ((dt <= currentDT))
536                               {
537                                   throw WsmFault(
538                                       WsmFault::wsen_InvalidExpirationTime,
539                                   MessageLoaderParms(
540                                       "WsmServer.WsmToCimRequestMapper.INVALID_EXPIRATION_TIME",
541                                       "The expiration time \"$0\" is not valid", wsmDT));
542 kumpf            1.3          }
543                       
544                               if (dt - currentDT > maxInterval)
545                               {
546                                   cimDT = currentDT + maxInterval;
547                               }
548                               else
549                               {
550                                   cimDT = dt;
551                               }
552                           }
553                       }
554                       
555                       void WsmProcessor::cleanupExpiredContexts()
556                       {
557                           CIMDateTime currentDT = CIMDateTime::getCurrentDateTime();
558 kumpf            1.4      Array<Uint64> expiredContextIds;
559                           Array<WsenEnumerateResponse*> expiredResponses;
560 kumpf            1.3  
561                           AutoMutex lock(_enumerationContextTableLock);
562                           for (EnumerationContextTable::Iterator i =
563                                    _enumerationContextTable.start (); i; i++)
564                           {
565                               EnumerationContext context = i.value();
566                               if (context.expiration < currentDT)
567                               {
568 kumpf            1.4              expiredContextIds.append(context.contextId);
569                                   expiredResponses.append(context.response);
570 kumpf            1.3          }
571                           }
572                       
573 kumpf            1.4      for (Uint32 i = 0; i < expiredContextIds.size(); i++)
574 kumpf            1.3      {
575 kumpf            1.4          delete expiredResponses[i];
576                               _enumerationContextTable.remove(expiredContextIds[i]);
577 kumpf            1.3      }
578                       }
579                       
580 kumpf            1.2  PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2