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

  1 karl  1.40 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.30 // 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 karl  1.20 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.30 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.32 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.40 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.2  //
 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 kumpf 1.10 // 
 21 mike  1.2  // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22            // 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            // Author: Mike Brasher (mbrasher@bmc.com)
 33            //
 34            // Modified By: Nitin Upasani, Hewlett-Packard Company (Nitin_Upasani@hp.com)
 35            //              Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
 36 kumpf 1.13 //              Carol Ann Krug Graves, Hewlett-Packard Company
 37            //                (carolann_graves@hp.com)
 38 kumpf 1.14 //              Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
 39 dj.gorey 1.24 //              Dan Gorey (djgorey@us.ibm.com)
 40 se.gupta 1.27 //				Seema Gupta (gseema@in.ibm.com) for PEP135
 41 kumpf    1.31 //              Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
 42 joyce.j  1.33 //              Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for PEP#101
 43 j.alex   1.37 //              John Alex, IBM (johnalex@us.ibm.com) - Bug#2290
 44 dj.gorey 1.24 //
 45 mike     1.2  //%/////////////////////////////////////////////////////////////////////////////
 46               
 47               #include <Pegasus/Common/Config.h>
 48 kumpf    1.7  #include <Pegasus/Common/Constants.h>
 49 mike     1.2  #include <Pegasus/Common/HTTPConnection.h>
 50               #include <Pegasus/Common/XmlWriter.h>
 51               #include <Pegasus/Common/TimeValue.h>
 52               #include <Pegasus/Common/Exception.h>
 53 kumpf    1.8  #include <Pegasus/Common/PegasusVersion.h>
 54               
 55 mike     1.2  #include "CIMExportRequestEncoder.h"
 56               #include "CIMExportResponseDecoder.h"
 57               #include "CIMExportClient.h"
 58               
 59 humberto 1.18 // l10n
 60               #include <Pegasus/Common/MessageLoader.h>
 61               
 62 mike     1.2  #include <iostream>
 63               
 64               PEGASUS_USING_STD;
 65               
 66               PEGASUS_NAMESPACE_BEGIN
 67               
 68               CIMExportClient::CIMExportClient(
 69 mday     1.4     Monitor* monitor,
 70                  HTTPConnector* httpConnector,
 71 kumpf    1.12    Uint32 timeoutMilliseconds)
 72 mday     1.4     : 
 73 kumpf    1.14    MessageQueue(PEGASUS_QUEUENAME_EXPORTCLIENT),
 74                  _monitor(monitor),
 75 mday     1.3     _httpConnector(httpConnector),
 76 kumpf    1.14    _httpConnection(0),
 77 kumpf    1.12    _timeoutMilliseconds(timeoutMilliseconds),
 78 mday     1.3     _connected(false),
 79                  _responseDecoder(0),
 80                  _requestEncoder(0)
 81 mike     1.2  {
 82 kumpf    1.26     PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::CIMExportClient()");
 83                   PEG_METHOD_EXIT();
 84 mike     1.2  }
 85               
 86               CIMExportClient::~CIMExportClient()
 87               {
 88 kumpf    1.26     PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::~CIMExportClient()");
 89 konrad.r 1.15 
 90 kumpf    1.26     disconnect();
 91               
 92                   PEG_METHOD_EXIT();
 93 mike     1.2  }
 94               
 95 kumpf    1.14 void CIMExportClient::_connect()
 96 mday     1.4  {
 97 kumpf    1.34     PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::_connect()");
 98 kumpf    1.26 
 99 kumpf    1.34     // Create response decoder:
100 mike     1.2      
101 kumpf    1.34     _responseDecoder = new CIMExportResponseDecoder(
102                       this, _requestEncoder, &_authenticator);
103 mike     1.2      
104 kumpf    1.34     // Attempt to establish a connection:
105 mike     1.2      
106 kumpf    1.34     try
107                   {
108                       _httpConnection = _httpConnector->connect(_connectHost, 
109                           _connectPortNumber, 
110                           _connectSSLContext.get(),
111                           _responseDecoder);
112                   }
113                   catch (...)
114                   {
115                       // Some possible exceptions are CannotCreateSocketException,
116                       // CannotConnectException, and InvalidLocatorException
117 kumpf    1.14         delete _responseDecoder;
118 kumpf    1.26         PEG_METHOD_EXIT();
119 kumpf    1.34         throw;
120                   }
121 mike     1.2      
122 kumpf    1.34     // Create request encoder:
123 mike     1.2      
124 kumpf    1.34     String connectHost = _connectHost;
125                   if (connectHost.size())
126                   {
127                       char portStr[32];
128                       sprintf(portStr, ":%u", _connectPortNumber);
129                       connectHost.append(portStr);
130                   }
131 kumpf    1.29 
132 kumpf    1.34     _requestEncoder = new CIMExportRequestEncoder(
133                       _httpConnection, connectHost, &_authenticator);
134 mike     1.2  
135 kumpf    1.34     _responseDecoder->setEncoderQueue(_requestEncoder);    
136 mike     1.2  
137 kumpf    1.34     _connected = true;
138 kumpf    1.26 
139 marek    1.42     _httpConnection->setSocketWriteTimeout(_timeoutMilliseconds/1000+1);
140               
141 kumpf    1.34     PEG_METHOD_EXIT();
142 mike     1.2  }
143               
144 kumpf    1.23 void CIMExportClient::_disconnect()
145               {
146 kumpf    1.26     PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::_disconnect()");
147               
148 kumpf    1.23     if (_connected)
149                   {
150                       //
151                       // destroy response decoder
152                       //
153 kumpf    1.41         delete _responseDecoder;
154                       _responseDecoder = 0;
155 kumpf    1.23 
156                       //
157                       // Close the connection
158                       //
159                       if (_httpConnector)
160                       {
161                           _httpConnector->disconnect(_httpConnection);
162                           _httpConnection = 0;
163                       }
164 dj.gorey 1.24           
165 kumpf    1.23 
166                       //
167                       // destroy request encoder
168                       //
169 kumpf    1.41         delete _requestEncoder;
170                       _requestEncoder = 0;
171 kumpf    1.23 
172                       _connected = false;
173                   }
174 kumpf    1.26     PEG_METHOD_EXIT();
175 kumpf    1.23 }
176               
177 kumpf    1.14 void CIMExportClient::_reconnect()
178               {
179 kumpf    1.26     PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::_reconnect()");
180 kumpf    1.23     _disconnect();
181                   _authenticator.setRequestMessage(0);
182 kumpf    1.14     _connect();
183 kumpf    1.26     PEG_METHOD_EXIT();
184 kumpf    1.14 }
185               
186               void CIMExportClient::connect(
187                   const String& host,
188                   const Uint32 portNumber)
189               {
190 kumpf    1.26    PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::connect()");
191 kumpf    1.14    // If already connected, bail out!
192                   
193                  if (_connected)
194 kumpf    1.26    {
195                     PEG_METHOD_EXIT();
196 kumpf    1.14       throw AlreadyConnectedException();
197 kumpf    1.26    }
198 kumpf    1.14     
199                   //
200                   // If the host is empty, set hostName to "localhost"
201                   //
202                   String hostName = host;
203                   if (host == String::EMPTY)
204                   {
205                       hostName = "localhost";
206                   }
207               
208                   //
209                   // Set authentication information
210                   //
211 kumpf    1.23     _authenticator.clear();
212 kumpf    1.14 
213 kumpf    1.28     _connectSSLContext.reset(0);
214 kumpf    1.14     _connectHost = hostName;
215                   _connectPortNumber = portNumber;
216               
217                   _connect();
218 kumpf    1.26     PEG_METHOD_EXIT();
219 kumpf    1.14 }
220               
221 kumpf    1.17 void CIMExportClient::connect(
222                   const String& host,
223                   const Uint32 portNumber,
224                   const SSLContext& sslContext)
225               {
226 kumpf    1.26     PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::connect()");
227               
228                   // If already connected, bail out!
229 kumpf    1.17 
230 kumpf    1.26     if (_connected)
231                   {
232                      PEG_METHOD_EXIT();
233                      throw AlreadyConnectedException();
234                   }
235 kumpf    1.17 
236                   //
237                   // If the host is empty, set hostName to "localhost"
238                   //
239                   String hostName = host;
240                   if (host == String::EMPTY)
241                   {
242                       hostName = "localhost";
243                   }
244               
245                   //
246                   // Set authentication information
247                   //
248 kumpf    1.23     _authenticator.clear();
249 kumpf    1.17 
250 kumpf    1.28     _connectSSLContext.reset(new SSLContext(sslContext));
251 kumpf    1.17     _connectHost = hostName;
252                   _connectPortNumber = portNumber;
253               
254                   try
255                   {
256                       _connect();
257                   }
258 kumpf    1.34     catch (...)
259 kumpf    1.17     {
260 kumpf    1.28         _connectSSLContext.reset();
261 kumpf    1.26         PEG_METHOD_EXIT();
262 kumpf    1.17         throw;
263                   }
264 kumpf    1.26     PEG_METHOD_EXIT();
265 kumpf    1.17 }
266               
267 kumpf    1.14 void CIMExportClient::disconnect()
268 mike     1.2  {
269 kumpf    1.26     PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::disconnect()");
270 kumpf    1.23     _disconnect();
271                   _authenticator.clear();
272 kumpf    1.28     _connectSSLContext.reset();
273 kumpf    1.26     PEG_METHOD_EXIT();
274 mike     1.2  }
275               
276               void CIMExportClient::exportIndication(
277 mday     1.4     const String& url,
278 chuck    1.16    const CIMInstance& instanceName,
279 kumpf    1.39    const ContentLanguageList& contentLanguages)
280 mike     1.2  {
281 carolann.graves 1.35     PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::exportIndication()");
282 kumpf           1.26 
283 carolann.graves 1.35     try
284                          {
285                              // encode request
286                              // l10n  
287                              CIMRequestMessage* request = new CIMExportIndicationRequestMessage(
288                                  String::EMPTY,
289                                  url,
290                                  instanceName,
291                                  QueueIdStack(),
292                                  String::EMPTY,
293                                  String::EMPTY);
294 se.gupta        1.27 
295 carolann.graves 1.35         request->operationContext.set
296                                  (ContentLanguageListContainer(contentLanguages));
297 mike            1.2  
298 carolann.graves 1.35         Message* message = _doRequest(request,
299                                  CIM_EXPORT_INDICATION_RESPONSE_MESSAGE);
300 mike            1.2  
301 carolann.graves 1.35         CIMExportIndicationResponseMessage* response = 
302                                  (CIMExportIndicationResponseMessage*)message;
303 mike            1.2      
304 carolann.graves 1.35         AutoPtr<CIMExportIndicationResponseMessage> ap(response);
305                          }
306                          catch (const Exception & e)
307                          {
308                              PEG_TRACE_STRING (TRC_DISCARDED_DATA, Tracer::LEVEL4, 
309                                  "Failed to export indication: " + e.getMessage ());
310                              throw;
311                          }
312                          catch (...)
313                          {
314                              PEG_TRACE_STRING (TRC_DISCARDED_DATA, Tracer::LEVEL4, 
315                                  "Failed to export indication");
316                              throw;
317                          }
318 kumpf           1.26 
319 carolann.graves 1.35     PEG_METHOD_EXIT();
320 mike            1.2  }
321                      
322 kumpf           1.14 Message* CIMExportClient::_doRequest(
323                          CIMRequestMessage * request,
324                          const Uint32 expectedResponseMessageType
325                      )
326 mike            1.2  {
327 kumpf           1.26     PEG_METHOD_ENTER (TRC_EXPORT_CLIENT, "CIMExportClient::_doRequest()");
328                      
329 kumpf           1.14     if (!_connected)
330                          {
331                             delete request;
332 kumpf           1.26        PEG_METHOD_EXIT();
333 kumpf           1.14        throw NotConnectedException();
334                          }
335                          
336                          String messageId = XmlWriter::getNextMessageId();
337                          const_cast<String &>(request->messageId) = messageId;
338                      
339 kumpf           1.23     _authenticator.setRequestMessage(0);
340 kumpf           1.14 
341                          // ATTN-RK-P2-20020416: We should probably clear out the queue first.
342                          PEGASUS_ASSERT(getCount() == 0);  // Shouldn't be any messages in our queue
343                      
344                          //
345 kumpf           1.22     //  Set HTTP method in request to POST
346 kumpf           1.14     //
347 kumpf           1.22     request->setHttpMethod (HTTP_METHOD__POST);
348 kumpf           1.14 
349                          _requestEncoder->enqueue(request);
350                      
351                          Uint64 startMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
352                          Uint64 nowMilliseconds = startMilliseconds;
353                          Uint64 stopMilliseconds = nowMilliseconds + _timeoutMilliseconds;
354                      
355                          while (nowMilliseconds < stopMilliseconds)
356                          {
357                      	//
358                      	// Wait until the timeout expires or an event occurs:
359                      	//
360 kumpf           1.31         _monitor->run(Uint32(stopMilliseconds - nowMilliseconds));
361 kumpf           1.14        
362                      	//
363                      	// Check to see if incoming queue has a message
364                      	//
365                      
366                      	Message* response = dequeue();
367                      
368                      	if (response)
369                      	{
370                                  // Shouldn't be any more messages in our queue
371                                  PEGASUS_ASSERT(getCount() == 0);
372                      
373                                  //
374 kumpf           1.21             //  Future:  If M-POST is used and HTTP response is 501 Not
375                                  //  Implemented or 510 Not Extended, retry with POST method
376 kumpf           1.14             //
377 j.alex          1.37             //
378                      
379                                  // Reconnect to reset the connection
380                                  // if Server response contained a Connection: Close Header
381                                  //
382 j.alex          1.38             if (response->getCloseConnect() == true){
383                                      _reconnect();
384                                      response->setCloseConnect(false);
385 j.alex          1.37             }
386                      
387 kumpf           1.14 
388                                  if (response->getType() == CLIENT_EXCEPTION_MESSAGE)
389                                  {
390                                      Exception* clientException =
391                                          ((ClientExceptionMessage*)response)->clientException;
392                                      delete response;
393 kumpf           1.26                 PEG_TRACE_STRING(TRC_EXPORT_CLIENT, Tracer::LEVEL4, "Client Exception Message received.");
394 kumpf           1.21 
395 joyce.j         1.33                 AutoPtr<Exception> d(clientException);
396 kumpf           1.21 
397                                      //
398                                      // Determine and throw the specific class of client exception
399                                      //
400                      
401                                      CIMClientMalformedHTTPException* malformedHTTPException =
402                                          dynamic_cast<CIMClientMalformedHTTPException*>(
403                                              clientException);
404                                      if (malformedHTTPException)
405                                      {
406 kumpf           1.26                     PEG_METHOD_EXIT();
407 kumpf           1.21                     throw *malformedHTTPException;
408                                      }
409                      
410                                      CIMClientHTTPErrorException* httpErrorException =
411                                          dynamic_cast<CIMClientHTTPErrorException*>(
412                                              clientException);
413                                      if (httpErrorException)
414                                      {
415 kumpf           1.26                     PEG_METHOD_EXIT();
416 kumpf           1.21                     throw *httpErrorException;
417                                      }
418                      
419                                      CIMClientXmlException* xmlException =
420                                          dynamic_cast<CIMClientXmlException*>(clientException);
421                                      if (xmlException)
422                                      {
423 kumpf           1.26                     PEG_METHOD_EXIT();
424 kumpf           1.21                     throw *xmlException;
425                                      }
426                      
427                                      CIMClientResponseException* responseException =
428                                          dynamic_cast<CIMClientResponseException*>(clientException);
429                                      if (responseException)
430                                      {
431 kumpf           1.26                     PEG_METHOD_EXIT();
432 kumpf           1.21                     throw *responseException;
433                                      }
434                      
435 kumpf           1.26                 PEG_METHOD_EXIT();
436 kumpf           1.14                 throw *clientException;
437                                  }
438                                  else if (response->getType() == expectedResponseMessageType)
439                                  {
440 kumpf           1.26                 PEG_TRACE_STRING(TRC_EXPORT_CLIENT, Tracer::LEVEL4, 
441 carolann.graves 1.35                     "Received expected indication response message.");
442 kumpf           1.14                 CIMResponseMessage* cimResponse = (CIMResponseMessage*)response;
443                                      if (cimResponse->messageId != messageId)
444                                      {
445 humberto        1.18 		  // l10n
446                      		  
447                      		  // CIMClientResponseException responseException(
448                      		  //   String("Mismatched response message ID:  Got \"") +
449                      		  //    cimResponse->messageId + "\", expected \"" +
450                      		  //    messageId + "\".");
451                      
452                      		  MessageLoaderParms mlParms("ExportClient.CIMExportClient.MISMATCHED_RESPONSE_ID", 
453 kumpf           1.26                       "Mismatched response message ID:  Got \"$0\", expected \"$1\".", 
454                                            cimResponse->messageId, messageId);
455 humberto        1.18 		  String mlString(MessageLoader::getMessage(mlParms));
456                      
457                      		  CIMClientResponseException responseException(mlString);
458                      
459                      		  delete response;
460 kumpf           1.26                   PEG_METHOD_EXIT();
461 humberto        1.18 		  throw responseException;
462 kumpf           1.14                 }
463                                      if (cimResponse->cimException.getCode() != CIM_ERR_SUCCESS)
464                                      {
465 kumpf           1.26                     PEG_TRACE_STRING(TRC_EXPORT_CLIENT, Tracer::LEVEL4, 
466                                              "Received indication failure message.");
467 kumpf           1.14                     CIMException cimException(
468                                              cimResponse->cimException.getCode(),
469                                              cimResponse->cimException.getMessage());
470                                          delete response;
471 kumpf           1.26                     PEG_METHOD_EXIT();
472 kumpf           1.14 	            throw cimException;
473                                      }
474 kumpf           1.26                 PEG_METHOD_EXIT();
475 kumpf           1.14                 return response;
476                                  }
477 j.alex          1.38             else if (dynamic_cast<CIMRequestMessage*>(response) != 0)
478                                  {
479                                      // Respond to an authentication challenge
480                                      _requestEncoder->enqueue(response);
481                                      nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
482                                      stopMilliseconds = nowMilliseconds + _timeoutMilliseconds;
483                                      continue;
484                                  }
485 kumpf           1.14             else
486                                  {
487 humberto        1.18 	      // l10n
488                      
489                      	      // CIMClientResponseException responseException(
490                      	      //   "Mismatched response message type.");
491                      		
492                      	      MessageLoaderParms mlParms("ExportClient.CIMExportClient.MISMATCHED_RESPONSE", 
493                      					 "Mismatched response message type.");
494                      	      String mlString(MessageLoader::getMessage(mlParms));
495                      	      
496                      	      CIMClientResponseException responseException(mlString);
497                      
498                      	      delete response;
499 kumpf           1.26 
500                                    PEG_TRACE_STRING(TRC_EXPORT_CLIENT, Tracer::LEVEL4, mlString);
501                      
502                                    PEG_METHOD_EXIT();
503 humberto        1.18 	      throw responseException;
504 kumpf           1.14             }
505                      	}
506                      
507                              nowMilliseconds = TimeValue::getCurrentTime().toMilliseconds();
508 mike            1.43 	Threads::yield();
509 kumpf           1.14     }
510                      
511                          //
512                          // Reconnect to reset the connection (disregard late response)
513                          //
514                          try
515                          {
516 kumpf           1.26         PEG_TRACE_STRING(TRC_EXPORT_CLIENT, Tracer::LEVEL4, "Doing a _reconnect()...");
517 kumpf           1.14         _reconnect();
518                          }
519                          catch (...)
520                          {
521                          }
522                      
523 carolann.graves 1.35     PEG_TRACE_STRING(TRC_EXPORT_CLIENT, Tracer::LEVEL4, "Connection to the listener timed out.");
524 kumpf           1.26     PEG_METHOD_EXIT();
525 kumpf           1.14     //
526                          // Throw timed out exception:
527                          //
528                          throw ConnectionTimeoutException();
529 mike            1.2  }
530                      
531                      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2